<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>AI on PIYO Notes</title><link>https://blog.piyo.tech/tags/ai/</link><description>Recent content in AI on PIYO Notes</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Sun, 26 Apr 2026 20:00:00 +0900</lastBuildDate><atom:link href="https://blog.piyo.tech/tags/ai/feed.xml" rel="self" type="application/rss+xml"/><item><title>Claude DesignとClaude Codeでブログをリデザインした</title><link>https://blog.piyo.tech/posts/2026-04-26-blog-redesign-with-anthropic-design/</link><pubDate>Sun, 26 Apr 2026 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2026-04-26-blog-redesign-with-anthropic-design/</guid><description>&lt;p&gt;このブログの見た目を最後にいじったのが2020年のGWでした。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2020-05-05-hugo-tag-color/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/r0owED5cBmCrD0wSbGkZkndJpmBW1SzYJPnfeb4w6XtcRfmmAr7IEYeo2nsjt3cHb81HlpByTaF4-1_UIXqJrWCfj_m-EaPaoYEszOlNg5qSIgQPbKBiyLQVgylgohhqzlss39qtNC7C6PzmxN0t6i0tAlfN858y1NXR-p9zoGsNDD_ESSfy5xrMOqAyWcav-aqnKjggx4xOnbxK0zA7qw8zVdqztuAfysiwKZI1r39UZ13ina1SjA_TEeC3zdQ132HcK4UuGSyLFmB0W662oCOyZaCz4yaTVN4tcXQm8aGsNn1nyyp7S0MQiJk2Oy-zFHcwh4WAojtUMX9HJa9T_C34B6LNPrgoavxsVumFk76ZmCVguxzLstJ1GUg61u61j1f3g_Yd3f83cTz64mc5Tg3dn4EFrgrBRQ0ZudYx99jZDTC2vYPvlZBTxWzjkWNo0AFEwO2IcZtRf31y07Jqrp5LtXwAayPNEO138CoeS7Bhc88Llw3SM76R2KYu-gbVnbljhq1xYI_bgTT_zNNl561znfF96T9wX8bwfVYEziO8i5iVIK5vUl4l1d_JCi_9Ydy-bK8ooczLhq9hWaw0czTbT8X36HjU8NmfZLDrvZC7JaBhaki5JeMjvQEw0BlchpNVno0IHoZyEe2vv59ZJpu-_agRSarUKA=w1000-h667-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Hugoブログのタグをカラフルにしてみました - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;GW中にブログの見た目をだいぶいじりました。 ブログ書こうにもなんとなくテンションがあがらないのを見た目を変えることで無理やりテンションを上げるという作戦です。 久しぶりだったこともありローカルサーバーを動かすところですら苦労したのですがそれはまた後日メモするとして、今日は新しい見た目でちょっとだけ頑張った、タグ表示の色付けの部分を紹介したいと思います。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;タグをカラフルにしたあのとき以来、6年もそのままでした。書こうにもなんとなくテンションが上がらないというのは6年前と同じなんですが、最近Claude DesignとClaude Codeを触ることが増えたので、その流れで一気にリデザインしてみることにしました。&lt;/p&gt;
&lt;h1 id="claude-designでデザインを起こす"&gt;Claude Designでデザインを起こす&lt;/h1&gt;
&lt;p&gt;Claude DesignはAIにデザインを依頼できるツールで、HTML/CSS/JSのプロトタイプを出してくれます。&lt;/p&gt;
&lt;p&gt;ブログのトップとよく開かれている記事のURLを3つほど投げて、ざっくり「リデザインしたい、方向性は特に無し」と相談しました。すると、トーン、アクセントカラー、タイポグラフィ、レイアウトの好みなど、いくつかの質問が返ってきました。&lt;/p&gt;
&lt;p&gt;僕はこんな感じで答えました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ライト&amp;amp;ブライト（白基調）&lt;/li&gt;
&lt;li&gt;深い青・緑（落ち着いた知性）&lt;/li&gt;
&lt;li&gt;モダンサンセリフ（Noto Sans JP系）&lt;/li&gt;
&lt;li&gt;縦長リスト or 2カラム&lt;/li&gt;
&lt;li&gt;圧倒的な可読性重視&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そしたら4方向の案が出てきました。A案ミニマル縦長、B案雑誌2カラム、C案タイムライン強調、D案タグ駆動カラフル継承の4種です。それぞれトップと記事ページのセットになっていて、Canvas上でアクセントカラーを切り替えながら比較できるようになっています。&lt;/p&gt;
&lt;p&gt;A案を選びました。今のブログの正統進化という方向性です。&lt;/p&gt;
&lt;p&gt;その後、コードブロックの強化、サイドバーの追加、フッター回りなどを追加で依頼して、A案の仕上げ版が完成しました。&lt;/p&gt;
&lt;h1 id="claude-codeで実装してもらう"&gt;Claude Codeで実装してもらう&lt;/h1&gt;
&lt;p&gt;Claude Designから出てくるのはあくまでプロトタイプなので、ブログに反映するにはHugoのテンプレートに適用する必要があります。&lt;/p&gt;
&lt;p&gt;ここから先はClaude Codeに任せました。Claude DesignにはClaude Codeへ直接ハンドオフできるプロンプトが用意されていて、そのプロンプトをコピペするだけで開始できます。ハンドオフされたプロジェクトの中のREADMEを読みつつ、意図を汲んで実装してくれます。&lt;/p&gt;
&lt;p&gt;書き換えてもらった範囲はこんな感じです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;layouts/partials/styles.css&lt;/code&gt; — デザイントークン入れ替え + 新コンポーネントCSS&lt;/li&gt;
&lt;li&gt;&lt;code&gt;layouts/_default/baseof.html&lt;/code&gt; — スティッキーヘッダー + リッチフッター&lt;/li&gt;
&lt;li&gt;&lt;code&gt;layouts/_default/list.html&lt;/code&gt; — 年見出しグルーピング&lt;/li&gt;
&lt;li&gt;&lt;code&gt;layouts/_default/summary.html&lt;/code&gt; — 記事ページ構造&lt;/li&gt;
&lt;li&gt;&lt;code&gt;layouts/_default/li.html&lt;/code&gt; — リストアイテム&lt;/li&gt;
&lt;li&gt;&lt;code&gt;layouts/partials/sidebar.html&lt;/code&gt; — About / Popular / Latest / Tags&lt;/li&gt;
&lt;li&gt;&lt;code&gt;layouts/partials/share.html&lt;/code&gt; — シェアボタン (X / はてブ / URLコピー)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;このあたりを一気に書き換えてもらって、全ページ問題なくビルドされることを確認しました。&lt;/p&gt;
&lt;p&gt;また、その過程でローカルのHugoバージョンだと&lt;code&gt;hugo.IsServer&lt;/code&gt;が動かないとか、&lt;code&gt;node_modules&lt;/code&gt;が消えていたとか、一部のショートコードが未定義だったとか、付随する問題もいくつか見つけてもらって、それぞれ潰してくれました。&lt;/p&gt;
&lt;h1 id="細かい調整"&gt;細かい調整&lt;/h1&gt;
&lt;p&gt;実装してもらったあと、ブラウザで眺めながら気になるところを直してもらいました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ブログタイトルを変更&lt;/li&gt;
&lt;li&gt;サブタイトルも変更&lt;/li&gt;
&lt;li&gt;特別意味のないbio文を削除&lt;/li&gt;
&lt;li&gt;ヘッダー/メイン/フッターで横位置がズレていたのを揃える&lt;/li&gt;
&lt;li&gt;コードブロックが二重にハイライトされて崩れていたのを、Chroma単体に整理&lt;/li&gt;
&lt;li&gt;ファビコンを同心円のシンプルなデザインに刷新&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ファビコンもClaude Designに何パターンか作ってもらって、その中から同心円のシンプルなSVGを採用しました。それをClaude Codeに渡したら、各サイズのPNGへの変換やICOの作成、置き換えという流れを全部やってくれました。&lt;/p&gt;
&lt;p&gt;ヘッダーとフッターには同じマークをインラインSVGで配置していますが、&lt;code&gt;fill&lt;/code&gt;/&lt;code&gt;stroke&lt;/code&gt;を&lt;code&gt;currentColor&lt;/code&gt;にしておいて、CSS側で&lt;code&gt;color: var(--accent)&lt;/code&gt;（ヘッダー）と&lt;code&gt;color: #fff&lt;/code&gt;（フッター）に切り替えるようにしました。1つのSVGで明背景にも暗背景にも対応できます。&lt;/p&gt;
&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;p&gt;6年前はTailwindの9色でカラフルなタグを実装したのを、今回はNavy一色の単色ピルにぜんぶ置き換えました。見た目を変えてテンションを上げる、という動機は6年前と変わっていません。&lt;/p&gt;</description></item><item><title>patch-packgeでpackage.jsonの差分を含める</title><link>https://blog.piyo.tech/posts/2020-05-13-patch-package/</link><pubDate>Wed, 13 May 2020 06:13:40 +0900</pubDate><guid>https://blog.piyo.tech/posts/2020-05-13-patch-package/</guid><description>&lt;p&gt;patch-packageっていうnpmパッケージありますよね？&lt;/p&gt;
&lt;p&gt;この記事↓が詳しいので紹介はだいぶ任せちゃうのですが、npmパッケージを手元でちょっとだけ直したいときに重宝する仕組みです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://bagelee.com/programming/javascript-2/patch-package/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://bagelee.s3-ap-northeast-1.amazonaws.com/wp-content/uploads/2018/12/a-1024x610.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;かゆいところに手が届く！patch-packageでnpmパッケージを乗りこなそう - bagelee（ベーグリー）&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;npmパッケージを利用する際、バージョンの違いなどで動かなかったり、少しだけカスタマイズしたいといったような場面に遭遇することはないでしょうか？そんなときに使えるpatch-packageというツールをご紹介します。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://bagelee.com/wp-content/themes/bagelee/img/icon/favicon.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;bagelee.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;使い方はこう。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;手元でnode_modules配下のとあるパッケージのコードをいじる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npx patch-package xxx_target_package&lt;/code&gt; を実行&lt;/li&gt;
&lt;li&gt;1の差分のpatchができる&lt;/li&gt;
&lt;li&gt;post-installに書いとけば自動的にpatchが当たる&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;（もちろん明らかな問題の場合はプルリクエストを投げるなりIssueで報告するなりが望ましいのですが、React Nativeのライブラリに含まれるネイティブコードがまれによく壊れる関係で、こういう仕組みも必要なのです！！）&lt;/p&gt;
&lt;h2 id="なんですが"&gt;なんですが！&lt;/h2&gt;
&lt;p&gt;パッケージによってはimport時にビルド済のコード（&lt;code&gt;dist&lt;/code&gt;とか）が参照されるために、パッチを当てにくい場合があります。&lt;/p&gt;
&lt;p&gt;minifyされたコードを無理やり変更して&lt;code&gt;npx patch-package&lt;/code&gt;した場合、コード全部がパッチ対象になるのでかなり厳しいことになります。&lt;/p&gt;
&lt;p&gt;ところで昨今、大抵のプロジェクトではアプリケーション側で何かしらのビルドの仕組みを入れていることが多いと思われます。であればimport対象をビルド前のソースコードにして、アプリケーション側でビルドさせてしまうこともできるはず。そしてそうすればpatch-packageの修正も数行に収めることができるはずです。&lt;/p&gt;
&lt;p&gt;ということで、とある架空のプロジェクトの&lt;code&gt;package.json&lt;/code&gt;にこういう変更を加えます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-patch" data-lang="patch"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;--- a/node_modules/xxx-lib/package.json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+++ b/node_modules/xxx-lib/package.json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;@@ -108,7 +112,7 @@
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;- &amp;#34;main&amp;#34;: &amp;#34;dist/index.js&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+ &amp;#34;main&amp;#34;: &amp;#34;src/index.js&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &amp;#34;name&amp;#34;: &amp;#34;hogehoge&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そして実際に変更を加えたいところも直して&lt;code&gt;npx patch-package&lt;/code&gt;します。&lt;/p&gt;
&lt;p&gt;するとなんと、&lt;code&gt;package.json&lt;/code&gt;への差分が無視されてしまいます。実はpatch-packageには除外の仕組みがあって、&lt;code&gt;package.json&lt;/code&gt;は除外対象となっているのです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/ds300/patch-package/issues/219" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/bd566759a22830545c71a53053b0fbb4bb11694f3db65b3d9cde2aadf00acc10/ds300/patch-package/issues/219" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Fails to recognize diffs in package.json · Issue #219 · ds300/patch-package&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;I was trying to modify a package&amp;#39;s main field, but patch-package reported no changes found my guess is the package.json is intentionally ignored to avoid anomalous diffs made by package managers. b...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ということで、今回の場合は↓のように除外対象を上書きすることでpackage.jsonを対象にできました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;npx patch-package xxx-lib --exclude &amp;#39;^$&amp;#39;
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>バッテリー監視のMacアプリを作ったんだけど難しかった</title><link>https://blog.piyo.tech/posts/2020-05-12-mac-app-memo/</link><pubDate>Tue, 12 May 2020 21:39:12 +0900</pubDate><guid>https://blog.piyo.tech/posts/2020-05-12-mac-app-memo/</guid><description>&lt;p&gt;久しぶりにMacアプリを作りました（5年ぶりぐらい）。難しかったです。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p lang="ja" dir="ltr"&gt;5年ぶりぐらいにMacのネイティブアプリ書いたけどさー、相変わらず情報なさすぎるしiOSの情報ばっか出てくるからググりにくいし、世の中のMacアプリ書いてる人はみんな天才なのかな？と思うよね&lt;/p&gt;&amp;mdash; 大野ぴーちゃん (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/status/1254365918315962368?ref_src=twsrc%5Etfw"&gt;April 26, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;Macbook Proをドッキングステーション経由の給電で使ってるせいか、たまに接触が悪いのか充電できない状態になることがあります。気がついたらバッテリー切れでMacが死んでしまうのでとても不便です。&lt;/p&gt;
&lt;p&gt;バッテリー残量監視アプリはストアにいくつか並んでいますが、これらはたいていMacの通知センターで通知してくれます。おやすみモードを有効にしているときや離席中にはMacの通知では気づけません。そこで、定期的にバッテリー残量を監視してSlackやその他ツールのWebhookのURLにメッセージを投げることができるアプリを自分で作りました。特にストアなどには公開していません。&lt;/p&gt;
&lt;h1 id="ステータスバーへの表示"&gt;ステータスバーへの表示&lt;/h1&gt;
&lt;p&gt;いわゆる常駐アプリのような形で作ったので、ステータスバーへの表示は必須と考えました。&lt;/p&gt;
&lt;p&gt;ステータスバーへのアイコン表示は↓のような感じで実現できました。ここではImage AssetとしてIcon.pdfというファイルがあるとします。&lt;/p&gt;
&lt;p&gt;（カラーアイコンの表示方法はわかりませんでした。白黒のPDF画像を用意しておくとダークモードかどうかで自動的に色を反転させてくれるようです。）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; statusBarItem = NSStatusBar.system.statusItem(withLength: CGFloat(NSStatusItem.squareLength))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; button = &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.statusBarItem.button {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; size = NSMakeSize(&lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; image = NSImage(named: &lt;span style="color:#e6db74"&gt;&amp;#34;Icon&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; image?.size = size
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; button.image = image
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ステータスバーのアイコンを押したらメニューを出すのがよくあるパターンだと思います。先程の&lt;code&gt;statusBarItem&lt;/code&gt;にメニューを追加すると表示してくれるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; statusBarMenu = NSMenu(title: &lt;span style="color:#e6db74"&gt;&amp;#34;Menu&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;statusBarItem.menu = statusBarMenu
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;statusBarMenu.addItem(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; withTitle: &lt;span style="color:#e6db74"&gt;&amp;#34;Preferences...&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; action: &lt;span style="color:#66d9ef"&gt;#selector&lt;/span&gt;(AppDelegate.togglePopover),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; keyEquivalent: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;statusBarMenu.addItem(NSMenuItem.separator())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;statusBarMenu.addItem(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; withTitle: &lt;span style="color:#e6db74"&gt;&amp;#34;Quit&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; action: &lt;span style="color:#66d9ef"&gt;#selector&lt;/span&gt;(AppDelegate.quit),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; keyEquivalent: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;設定、セパレータ、終了の3つを並べています。&lt;code&gt;action&lt;/code&gt;引数にはメニューを押したときの挙動をかけます。このアプリでは、設定メニューは設定画面Popoverの切り替えを、終了メニューは単にアプリを終了させる処理を書いています。&lt;/p&gt;
&lt;h1 id="dockに表示させない"&gt;Dockに表示させない&lt;/h1&gt;
&lt;p&gt;Info.plistに&lt;code&gt;LSUIElement = true&lt;/code&gt;な設定を追加することでアプリアイコンをDockに表示させないようにできます。&lt;/p&gt;
&lt;p&gt;LSUIElementはバックグラウンドアプリのための設定です。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A Boolean value indicating whether the app is an agent app that runs in the background and doesn&amp;rsquo;t appear in the Dock&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://docs.developer.apple.com/documentation/bundleresources/information-property-list/lsuielement" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://docs.developer.apple.com/tutorials/developer-og.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;LSUIElement | Apple Developer Documentation&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;A Boolean value indicating whether the app is an agent app that runs in the background and doesn’t appear in the Dock.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://developer.apple.com/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;developer.apple.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;# Info.plist
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;LSUIElement&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="swiftui"&gt;SwiftUI&lt;/h1&gt;
&lt;p&gt;SwiftUIが発表されて依頼はじめてマジメに触りました。今回はせいぜい設定画面のみでたくさんの画面を作るわけではないのでSwiftUIを採用してみました。&lt;/p&gt;
&lt;h2 id="プレビュー"&gt;プレビュー&lt;/h2&gt;
&lt;p&gt;SwiftUIでUIを定義すると、Xcodeが即座にプレビューを更新してくれます。最初は即座に確認できて便利、、、と思っていました。&lt;/p&gt;
&lt;p&gt;しかし、ちょっとタイピングして保存とするとすぐにプレビューを更新し、エディタ部分のフォーカスが失われるのでめちゃくちゃ不便ということがわかりました。しかもしらないうちにプレビューが壊れていたりして、Resumeしないと動かないという。&lt;/p&gt;
&lt;p&gt;これは僕の感想ですが、まだ実用的ではないなと思いました。&lt;/p&gt;
&lt;h2 id="toggleのクセ"&gt;Toggleのクセ&lt;/h2&gt;
&lt;p&gt;今回SwiftUIを使ったのは設定画面です。設定画面なので、値を変更したら即座にUserDefaultsに保存しようと考えていました。&lt;/p&gt;
&lt;p&gt;当初TextFieldやSliderは&lt;code&gt;onEditingChanged&lt;/code&gt;で変更を検知できるので、そのタイミングで保存処理を書いていました。&lt;/p&gt;
&lt;p&gt;しかし後述する「ログイン時に起動」をToggle（チェックボックス）で実現しようとしたときに困ったことになりました。Toggleには&lt;code&gt;onEditingChanged&lt;/code&gt;がなかったのです。&lt;/p&gt;
&lt;p&gt;プロパティのdidSetで実現できないかとか、もっと苦しいワークアラウンド（空のテキストを返す関数を定義してViewに埋め込み、その関数内でToggleの値を使って処理する）とか、色々考えました。しかしUserDefaultsの保存のコードがうまく動かないし、そもそもワークアラウンドだと関数が何度も呼ばれてしまうなど、あまりよろしくありません。&lt;/p&gt;
&lt;p&gt;変更を検知できないなら、ユーザーが保存ボタンを押すしかないだろうということで、保存ボタンをキャンセルボタンを設けることにして逃げました。&lt;/p&gt;
&lt;h1 id="ログイン時に起動"&gt;ログイン時に起動&lt;/h1&gt;
&lt;p&gt;常駐アプリであるからには、Macを再起動したときにも勝手に立ち上がって欲しいですよね。これを実現するには&lt;code&gt;Service Management Framework&lt;/code&gt;という仕組みを使ってログイン時に起動する項目に追加する必要があるようです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLoginItems.html" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Adding Login Items&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Explains how to write background processes that perform work on behalf of applications or serve content over the network.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;span class="truncate"&gt;developer.apple.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Service Management Frameworkについての情報（特に日本語情報）はあまり多くないのですが、幸いまるっとライブラリ化されているOSSがあったので、それを活用させてもらうことにしました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/sindresorhus/LaunchAtLogin-Legacy" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/b8e314b5f35fc9270f01baf4787924005d4f9c23675c39a4949510b42e0f6068/sindresorhus/LaunchAtLogin-Legacy" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - sindresorhus/LaunchAtLogin-Legacy: Add “Launch at Login” functionality to your macOS app in seconds&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Add “Launch at Login” functionality to your macOS app in seconds - sindresorhus/LaunchAtLogin-Legacy&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;導入はとても簡単で、&lt;code&gt;Run Script Phase&lt;/code&gt;にスクリプトを追加することと、コードを少々追加するだけです。&lt;/p&gt;
&lt;p&gt;今回の僕のアプリでは設定画面を保存する際に、Toggleの状態に応じて設定を更新してやるだけでいけました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;LaunchAtLogin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Toggleのstate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;@State &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; launchAtLogin = &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 保存時&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;LaunchAtLogin.isEnabled = &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.launchAtLogin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これだけで実際にログイン時に起動してくれるようになりました。自分で書いていたらMacの作法に乗るのが大変だったと思うのでこのライブラリには感謝しています。&lt;/p&gt;</description></item><item><title>フォント JetBrains Monoが素敵だったので導入しまくった</title><link>https://blog.piyo.tech/posts/2020-05-07-introduce-jetbrains-mono/</link><pubDate>Thu, 07 May 2020 06:01:57 +0900</pubDate><guid>https://blog.piyo.tech/posts/2020-05-07-introduce-jetbrains-mono/</guid><description>&lt;p&gt;JetBrains Monoが素敵すぎていろんなエディタに設定して回ったという話です。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.jetbrains.com/lp/mono" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://www.jetbrains.com/lp/mono/static/preview-0d5da2c7dc8a75121b80e025c50e3bd4.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;JetBrains Mono: A free and open source typeface for developers&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Try JetBrains Mono in your IDE. Its simple forms and attention to every detail make coding a nice experience for developers’ eyes, no matter which IDE you choose.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://www.jetbrains.com/data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAC6klEQVR4XrXUP4qlaxlF8d/6&amp;#43;lRVB4KYaKBBIxh7AwfQsZkjEEfgEE51J05DA2On0M7AxMBEryAIRoIIVjV9toH3JI33dgdVK3l432Rv9vOnf53ufT5ed3n588tevubu1dyZW3OHW7zcZTfp5bab5s66w53t1vpf1Z3Lbv5w8LMXPpOb/fvscvw6x4/ZdyANUIWloGKogDAqRh3fm774LAMv/eN8WffVmKlDg1GANASkMKsCcTiGStOrTxr4dn89bzurkCpBrGKSVA0B2jEAKUECKt9o4EfHn8/jvorYFmCUpEVmUhoCSSpZlDREWjv5Gn5y/OnMzRmAqXVZlGM2NRqk1sgMtCYN1zJqJi39XwM/Pf54nrv7mUPGkNlRDTPAHGVjiokhBWDCJEPYfNwCfnX8/TzumQSoZhTEyKhiVASgw7GRUVnrEExlpmq3PwCAc49/u/eE/LPfXm8FX9Xtlq9uxAnAt5w9dO/Rk9IeJqVd6Fi7pAmcwHedPXbvYsgT0vGYMTqwdMwuKZz88PTKw4d7BvHkCZgJQ2yl2dLJiw9nt4OZZzDxKAzJCDQHO7n1Wpg8C/&amp;#43;RgQkTYqOTu70SoDw1eURoyWgySju5wQAuTz&amp;#43;EPdqIsJkAk5ObIRjlicmD2LAqbKmgk1tjKDxLC1Y121JgLoiTGxBj9ixbMJsVzGDJ9pergSE8SwvWakatCsbs9ye3kmfj2MMuZgkaa&amp;#43;CD483J7ZBno8dCaxfCbGxv8eXJjWd28ACkhsrFPd7Aya3YKDb09IeIIXaxt1dxrluggALY5lNUnzOEQ&amp;#43;RD3uIe4JoANnu2O5Bie/OxOHw0AwNQeQrqwWX&amp;#43;r/g1gYB5DraHrxW/JgAA2y&amp;#43;/n4fxPh6vFY/mPd6Xx/Fg3sd7PF7/Xd/Xv28UvyZAmxVjGAwBAwFjUEIAQwD0aXE4Oe2deW2oAMxYAEADg2VGATCG4/gscThpv3Db77QviIEhQQAQAFAC2Je8eGeX3&amp;#43;Cdz&amp;#43;S/wDiIq9yBSX0AAAAASUVORK5CYII=" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;www.jetbrains.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;まあ↑をみにいってくれればそれまでなのですが、以下のようにプログラミングに適したフォントでオープンだという特徴があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;高さを増やして可読性を向上&lt;/li&gt;
&lt;li&gt;コードリーディングに最適化&lt;/li&gt;
&lt;li&gt;コード固有のリガチャ&lt;/li&gt;
&lt;li&gt;JetBrains Monoは無料かつオープンソースです&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;特にリガチャがかっこよかったので即導入です。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;!==&lt;/code&gt;とか&lt;code&gt;&amp;gt;=&lt;/code&gt;とか&lt;code&gt;&amp;lt;=&lt;/code&gt;とか&lt;code&gt;~=&lt;/code&gt;とか、こうなるんですよ！&lt;/p&gt;
&lt;p&gt;このブログにも似たようなフォントであるFira Codeを入れているので、それっぽいリガチャになってるはず…！&lt;/p&gt;
&lt;p&gt;ちなみにFira Codeはこちらです。こちらもリガチャが使えます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/tonsky/FiraCode" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://repository-images.githubusercontent.com/26500787/bf313080-6b02-11ea-9cd5-c3dca880736d" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - tonsky/FiraCode: Free monospaced font with programming ligatures&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Free monospaced font with programming ligatures. Contribute to tonsky/FiraCode development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="emacsでの設定"&gt;Emacsでの設定&lt;/h1&gt;
&lt;p&gt;JetBrains Monoを僕のメインエディタであるEmacsで設定する方法については特に情報がなく、色々調べていたらほぼFiraCodeと同じ設定方法でいけることがわかりました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/tonsky/FiraCode/wiki/Emacs-instructions#using-composition-char-table"&gt;https://github.com/tonsky/FiraCode/wiki/Emacs-instructions#using-composition-char-table&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Mac port版のEmacsでは一行書けば動くようなのですが、僕のEmacsは色々パッチを当てたりなんだりだった気がしなくもない（覚えてない）ので、↑のWikiにあるのを順に試していった結果↓のコードで動くようになりました。ただし、一部エラーが発生したので&lt;code&gt;46&lt;/code&gt;をコメントアウトしました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-elisp" data-lang="elisp"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;;; フォント設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;(set-face-font &lt;span style="color:#e6db74"&gt;&amp;#39;default&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;JetBrains Mono-14&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;;; リガチャを有効にする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;(let ((alist &lt;span style="color:#f92672"&gt;&amp;#39;&lt;/span&gt;((&lt;span style="color:#ae81ff"&gt;33&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:\\(?:==\\|!!\\)\\|[!=]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;35&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:###\\|##\\|_(\\|[#(?[_{]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;36&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:&amp;gt;\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:\\(?:%%\\)\\|%\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;38&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:\\(?:&amp;amp;&amp;amp;\\)\\|&amp;amp;\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:\\(?:\\*\\*/\\)\\|\\(?:\\*[*/]\\)\\|[*/&amp;gt;]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:\\(?:\\+\\+\\)\\|[+&amp;gt;]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;45&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:\\(?:-[&amp;gt;-]\\|&amp;lt;&amp;lt;\\|&amp;gt;&amp;gt;\\)\\|[&amp;lt;&amp;gt;}~-]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;;; (46 . &amp;#34;.\\(?:\\(?:\\.[.&amp;lt;]\\)\\|[.=-]\\)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:\\(?:\\*\\*\\|//\\|==\\)\\|[*/=&amp;gt;]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;48&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:x[a-zA-Z]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;58&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:::\\|[:=]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:;;\\|;\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:\\(?:!--\\)\\|\\(?:~~\\|-&amp;gt;\\|\\$&amp;gt;\\|\\*&amp;gt;\\|\\+&amp;gt;\\|--\\|&amp;lt;[&amp;lt;=-]\\|=[&amp;lt;=&amp;gt;]\\||&amp;gt;\\)\\|[*$+~/&amp;lt;=&amp;gt;|-]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;61&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:\\(?:/=\\|:=\\|&amp;lt;&amp;lt;\\|=[=&amp;gt;]\\|&amp;gt;&amp;gt;\\)\\|[&amp;lt;=&amp;gt;~]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;62&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:\\(?:=&amp;gt;\\|&amp;gt;[=&amp;gt;-]\\)\\|[=&amp;gt;-]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;63&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:\\(\\?\\?\\)\\|[:=?]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;91&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;92&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:\\(?:\\\\\\\\\\)\\|\\\\\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;94&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:=\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;119&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:ww\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;123&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:-\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;124&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:\\(?:|[=|]\\)\\|[=&amp;gt;|]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;126&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.\\(?:~&amp;gt;\\|~~\\|[&amp;gt;=@~-]\\)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; ))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; (dolist (char-regexp alist)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#a6e22e"&gt;set-char-table-range&lt;/span&gt; composition-function-table (&lt;span style="color:#a6e22e"&gt;car&lt;/span&gt; char-regexp)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;`&lt;/span&gt;([&lt;span style="color:#f92672"&gt;,&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;cdr&lt;/span&gt; char-regexp) &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;font-shape-gstring&lt;/span&gt;]))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="vscodeでの設定"&gt;VSCodeでの設定&lt;/h1&gt;
&lt;p&gt;VSCodeはさすがに簡単でした。&lt;/p&gt;
&lt;p&gt;Font Familyに&lt;code&gt;JetBrains Mono&lt;/code&gt;を追加します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/NW3c3uMUM5Of-Wr41Bgi4sABeZqN_0QNGXJ8CIciWeiRG_YgjtDqbknNrUEpJaDm6yMWaD7baNVi75_Iz3Fdz2fF4ycN3ZXu0k62ui6O4HOAfGO-Ljvyqog4NhygG8F353RGwOHQfzU0WGqBRpKdcs-5Dly073H4IN_xPtanqJ13TLSfwFurYI_b8jNFulRxeB3zo1pc5SLjaXbFikXcGY43NXXBol9Vw3XSUwQW3mH1W772QHrAw1Hyl6dkJj-eQ8mWvVoB7kD93foevBjP0GwNZg3nAsvJeA4xI4SIDLZnYyF3pNOTJj8R43L9AYyhQyXZvQjyBoNI5aixZjAWwQunssO7n-1I5Ut3IsO64cK85zZ2Ijyqrgyqghl2TcVuK8LJGhgqXVEpacFwjxLM5Q4YkWjsG5zPZ0_xxczov_EqSX4-ypfP5-S_p9g5Z43XGslGLoTRgWn1TG5C0_6zROietMMkEQLzIyY9TUI1jnU3pHOq0cJwCwtAO1vRLToge1q1Wbtr7VzttjCgs5OFz9JzGZfZllf88BFZcs5Wf84yBX7Udx3bviWrqBwKcrFPb3G87QzQJOnzb5evLq2FRJsfxs3TvEakbvzda7IQQleuDbMEutG-045thJtavhwVLJVBpo8VWkhNF-McVa6rrmZztXzGWxQ2Y2IktAO6b8yoeJ1kZEttmc9s0PTSTrM0mmymWDTHdSMOAH42Nth1WSl2L3gkCbX6L9-FyPxk7_VaF4Vg9BduiTUS=w868-h264-no"&gt;&lt;img src="https://lh3.googleusercontent.com/NW3c3uMUM5Of-Wr41Bgi4sABeZqN_0QNGXJ8CIciWeiRG_YgjtDqbknNrUEpJaDm6yMWaD7baNVi75_Iz3Fdz2fF4ycN3ZXu0k62ui6O4HOAfGO-Ljvyqog4NhygG8F353RGwOHQfzU0WGqBRpKdcs-5Dly073H4IN_xPtanqJ13TLSfwFurYI_b8jNFulRxeB3zo1pc5SLjaXbFikXcGY43NXXBol9Vw3XSUwQW3mH1W772QHrAw1Hyl6dkJj-eQ8mWvVoB7kD93foevBjP0GwNZg3nAsvJeA4xI4SIDLZnYyF3pNOTJj8R43L9AYyhQyXZvQjyBoNI5aixZjAWwQunssO7n-1I5Ut3IsO64cK85zZ2Ijyqrgyqghl2TcVuK8LJGhgqXVEpacFwjxLM5Q4YkWjsG5zPZ0_xxczov_EqSX4-ypfP5-S_p9g5Z43XGslGLoTRgWn1TG5C0_6zROietMMkEQLzIyY9TUI1jnU3pHOq0cJwCwtAO1vRLToge1q1Wbtr7VzttjCgs5OFz9JzGZfZllf88BFZcs5Wf84yBX7Udx3bviWrqBwKcrFPb3G87QzQJOnzb5evLq2FRJsfxs3TvEakbvzda7IQQleuDbMEutG-045thJtavhwVLJVBpo8VWkhNF-McVa6rrmZztXzGWxQ2Y2IktAO6b8yoeJ1kZEttmc9s0PTSTrM0mmymWDTHdSMOAH42Nth1WSl2L3gkCbX6L9-FyPxk7_VaF4Vg9BduiTUS=w868-h264-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;さらにリガチャを有効にしたい場合には、設定ファイル（Settings.json）に以下を記載します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;editor.fontLigatures&amp;#34;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="ブログはfira-codeで"&gt;…ブログはFira Codeで&lt;/h1&gt;
&lt;p&gt;ブログにも入れるぞーと一瞬思ったものの、Fira CodeがCDNで配信されていて簡単そうだったのでFira Codeを使うことにしました。&lt;/p&gt;
&lt;p&gt;なので設定はめちゃくちゃ簡単でした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;@&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#f92672"&gt;url&lt;/span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#f92672"&gt;https&lt;/span&gt;&lt;span style="color:#f92672"&gt;://&lt;/span&gt;&lt;span style="color:#f92672"&gt;cdn&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;jsdelivr&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;net&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#f92672"&gt;gh&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#f92672"&gt;tonsky&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#f92672"&gt;FiraCode&lt;/span&gt;@&lt;span style="color:#66d9ef"&gt;3&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#f92672"&gt;distr&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#f92672"&gt;fira_code&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;css&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;body&lt;/span&gt; { &lt;span style="color:#f92672"&gt;font-family&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Fira Code&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#f92672"&gt;..&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;other&lt;/span&gt; &lt;span style="color:#f92672"&gt;fonts&lt;/span&gt;&lt;span style="color:#f92672"&gt;;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ソースコード部分だけじゃなく、全体でFira Code最優先にさせてしまえ！ということで本文や見出しなどでも英字部分はFira Codeになっているはずです。&lt;/p&gt;</description></item><item><title>Hugoブログのタグをカラフルにしてみました</title><link>https://blog.piyo.tech/posts/2020-05-05-hugo-tag-color/</link><pubDate>Tue, 05 May 2020 16:45:46 +0900</pubDate><guid>https://blog.piyo.tech/posts/2020-05-05-hugo-tag-color/</guid><description>&lt;p&gt;GW中にブログの見た目をだいぶいじりました。&lt;/p&gt;
&lt;p&gt;ブログ書こうにもなんとなくテンションがあがらないのを見た目を変えることで無理やりテンションを上げるという作戦です。&lt;/p&gt;
&lt;p&gt;久しぶりだったこともありローカルサーバーを動かすところですら苦労したのですがそれはまた後日メモするとして、今日は新しい見た目でちょっとだけ頑張った、タグ表示の色付けの部分を紹介したいと思います。&lt;/p&gt;
&lt;p&gt;記事中のタグ部分をHugoで処理するときには、タグの配列をループしてその中身（タグ本体）に対してHTMLを書くような感じで定義します。&lt;/p&gt;
&lt;p&gt;たとえばこんな感じで、&lt;code&gt;ul&lt;/code&gt;の中に&lt;code&gt;li&lt;/code&gt;を並べたりします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{{ $params := .Params }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{{ range $key, $value := $.Site.Taxonomies }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;{{ if isset $params $key }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;taglist&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; {{ range (index $params $key) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;tagitem&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;i&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;fa fa-tag&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;i&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; {{ . }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; {{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただし、この方法だと全てのタグが同じ見た目になってしまいますよね。&lt;/p&gt;
&lt;p&gt;今回の見た目の変更では、タグ用の色を何色か用意してある程度ランダムに割り振るということを行いました。ただし、同じタグはいつも必ず同じ色になるようにしなければいけません。ビルドするたびにタグの色が変わっては行けないし、あるタグが別の記事に紐付いたときに色が変わるようではいけません。つまりただランダムに色を割り振るだけではダメということです。&lt;/p&gt;
&lt;p&gt;タグを唯一識別する情報は&lt;strong&gt;タグ名&lt;/strong&gt;です。なので、タグ名からあるロジックで色を割り振ることができれば良いと考えました。&lt;/p&gt;
&lt;h1 id="タグの実装"&gt;タグの実装&lt;/h1&gt;
&lt;h2 id="tailwindの導入"&gt;Tailwindの導入&lt;/h2&gt;
&lt;p&gt;そしてココから先は割と力技でいきました。&lt;/p&gt;
&lt;p&gt;まずタグの見た目には、Tailwind CSSというユーティリティ用のクラスがたくさん定義されているCSSフレームワークを用いました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://tailwindcss.com/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://tailwindcss.com/opengraph-image.jpg?opengraph-image.c1dec83c.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Tailwind CSS - Rapidly build modern websites without ever leaving your HTML.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Tailwind CSS is a utility-first CSS framework for rapidly building modern websites without ever leaving your HTML.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://tailwindcss.com/favicons/favicon.ico?v=4" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;tailwindcss.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;このフレームワークには背景色用のclassがいくつか定義されていて、グレースケール系を除くと、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;red&lt;/li&gt;
&lt;li&gt;orange&lt;/li&gt;
&lt;li&gt;yellow&lt;/li&gt;
&lt;li&gt;green&lt;/li&gt;
&lt;li&gt;teal&lt;/li&gt;
&lt;li&gt;blue&lt;/li&gt;
&lt;li&gt;indigo&lt;/li&gt;
&lt;li&gt;purple&lt;/li&gt;
&lt;li&gt;pink&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;の9種類です。&lt;/p&gt;
&lt;p&gt;また、それぞれに&lt;code&gt;bg-red-600&lt;/code&gt;や&lt;code&gt;bg-green-100&lt;/code&gt;のように数値で色の段階を指定できます。&lt;/p&gt;
&lt;p&gt;参考）
&lt;a href="https://tailwindcss.com/docs/background-color/#app"&gt;https://tailwindcss.com/docs/background-color/#app&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今回はこれらの9色にタグを割り振ることにしました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;span&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text-xs mr-2 py-1 px-2 items-center bg-red-600 text-red-100 leading-none rounded-full flex inline-flex&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;i&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;fa fa-tag&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;aria-hidden&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;i&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; タグだよ
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Tailwindの他のクラスも駆使して↑のようなHTMLを書くと、↓のようなタグを出せます。&lt;/p&gt;
&lt;span class="text-xs mr-2 py-1 px-2 items-center bg-red-600 text-red-100 leading-none rounded-full flex inline-flex"&gt;
&lt;i class="fa fa-tag" aria-hidden="true"&gt;&lt;/i&gt;
タグだよ
&lt;/span&gt;
&lt;h2 id="タグ名から色名にマッピングする"&gt;タグ名から色名にマッピングする&lt;/h2&gt;
&lt;p&gt;タグ名をキーとして、なんらかの計算を駆使して色名にマッピングすることができれば、あとは表示するのは簡単です。&lt;/p&gt;
&lt;p&gt;9色に分けるという点から、整数を9で割った余りを使うのがよさそうだと考えました。つまり、タグ名を何らかの整数値に変換した上で9で割った余りを得て、その数値を色名配列のインデックスとして用いることで色名を得るというアイデアです。&lt;/p&gt;
&lt;p&gt;そして、Hugoではこれをなんとか実現できましたので、コードを紹介します。&lt;/p&gt;
&lt;p&gt;まず最初に紹介したようなループでタグを書き出す部分ですが、ここは大きく変わらずに↓のようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{{ $params := .Params }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{{ range $key, $value := $.Site.Taxonomies }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;{{ if isset $params $key }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;{{ range (index $params $key) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $.Site.BaseURL }}tags/{{ . | urlize }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text-xs&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;span&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;mr-2 py-1 px-2 items-center bg-{{ $variant }}-600 text-{{ $variant }}-100 leading-none rounded-full flex inline-flex&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;i&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;fa fa-tag mr-1&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;aria-hidden&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;i&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; {{ . }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;HTMLになっている箇所の大部分が先程紹介したタグ定義の部分です。ここで注目してもらいたいのが、&lt;code&gt;bg-{{ $variant }}-600 text-{{ $variant }}-100&lt;/code&gt;のところです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$variant&lt;/code&gt;という変数にTailwindの色名が適切に割り振られることで、色違いのタグを実現できます。&lt;/p&gt;
&lt;p&gt;次に、その&lt;code&gt;$variant&lt;/code&gt;を計算するところです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{{ $colors := slice &amp;#34;red&amp;#34; &amp;#34;orange&amp;#34; &amp;#34;yellow&amp;#34; &amp;#34;green&amp;#34; &amp;#34;teal&amp;#34; &amp;#34;blue&amp;#34; &amp;#34;indigo&amp;#34; &amp;#34;purple&amp;#34; &amp;#34;pink&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;{{ $val := ((md5 .) | replaceRE &amp;#34;[0a-z]&amp;#34; &amp;#34;&amp;#34;) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;{{ $val = substr $val 0 5 | int }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;{{ $mod := mod $val (len $colors)}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;{{ $variant := index $colors $mod }}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コードの意図は上のから順にこうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;色の配列を定義&lt;/li&gt;
&lt;li&gt;タグ名のmd5ハッシュを計算し、その結果から0とアルファベットを除去&lt;/li&gt;
&lt;li&gt;↑の結果の先頭5桁を整数に変換する&lt;/li&gt;
&lt;li&gt;↑の整数を $colorsの要素数（9）で割った余りを得る&lt;/li&gt;
&lt;li&gt;↑の余りをインデックスとして$colorsから色名を得る&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hugoのこのあたりの関数を使いました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/functions/slice/"&gt;https://gohugo.io/functions/slice/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/functions/md5/"&gt;https://gohugo.io/functions/md5/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/functions/replacere/"&gt;https://gohugo.io/functions/replacere/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/functions/substr/"&gt;https://gohugo.io/functions/substr/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/functions/int/"&gt;https://gohugo.io/functions/int/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/functions/math/"&gt;https://gohugo.io/functions/math/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/functions/len/"&gt;https://gohugo.io/functions/len/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/functions/index-function/"&gt;https://gohugo.io/functions/index-function/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;コード全体はこんな感じになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{{ $colors := slice &amp;#34;red&amp;#34; &amp;#34;orange&amp;#34; &amp;#34;yellow&amp;#34; &amp;#34;green&amp;#34; &amp;#34;teal&amp;#34; &amp;#34;blue&amp;#34; &amp;#34;indigo&amp;#34; &amp;#34;purple&amp;#34; &amp;#34;pink&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;{{ $params := .Params }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;{{ range $key, $value := $.Site.Taxonomies }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;{{ if isset $params $key }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;{{ range (index $params $key) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;{{ $val := ((md5 .) | replaceRE &amp;#34;[0a-z]&amp;#34; &amp;#34;&amp;#34;) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;{{ $val = substr $val 0 5 | int }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;{{ $mod := mod $val (len $colors)}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;{{ $variant := index $colors $mod }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $.Site.BaseURL }}tags/{{ . | urlize }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text-xs&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;span&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;mr-2 py-1 px-2 items-center bg-{{ $variant }}-600 text-{{ $variant }}-100 leading-none rounded-full flex inline-flex&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;i&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;fa fa-tag mr-1&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;aria-hidden&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;i&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; {{ . }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;おしまい。&lt;/p&gt;</description></item><item><title>Soundflowerを使ってMacで再生中の音声をMacのサウンド入力にする</title><link>https://blog.piyo.tech/posts/2019-07-08-sound-flower/</link><pubDate>Mon, 08 Jul 2019 17:00:38 +0900</pubDate><guid>https://blog.piyo.tech/posts/2019-07-08-sound-flower/</guid><description>&lt;p&gt;Macの画面収録と合わせて、Mac上で鳴っている音を録音したくなったことがあります。&lt;/p&gt;
&lt;p&gt;音を鳴らした状態で画面収録＋録音をするとMac標準のマイクで音を拾ってしまうので音が割れるなどして劣化します。微妙です。&lt;/p&gt;
&lt;p&gt;今回の用途は子どもの習い事に関するものなのですが、やろうと思えば再生中の音楽を録音する、みたいなことができてしまうので要注意です。&lt;/p&gt;
&lt;p&gt;で、その方法ですが、こちらのSoundflowerというツールを使います。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/mattingalls/Soundflower" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/1ab0f768138bce5657b4d5f807536663decac5fcd40e2f1cfef0a953316ad2cf/mattingalls/Soundflower" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - mattingalls/Soundflower: MacOS system extension that allows applications to pass audio to other applications. Soundflower works on macOS Catalina.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;MacOS system extension that allows applications to pass audio to other applications. Soundflower works on macOS Catalina. - mattingalls/Soundflower&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;インストール方法や使い方の説明はむしろこちらにあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mattingalls/Soundflower/releases/tag/2.0b2"&gt;https://github.com/mattingalls/Soundflower/releases/tag/2.0b2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;カーネルエクステンションを入れたら出力デバイスを作るという流れです。&lt;/p&gt;
&lt;h2 id="soundflowerのインストール"&gt;Soundflowerのインストール&lt;/h2&gt;
&lt;p&gt;まずは、2.0b2のページ下部のリンクから&lt;code&gt;Soundflower-2.0b2.dmg&lt;/code&gt;をダウンロードし開きます。
中に&lt;code&gt;Soundflower.pkg&lt;/code&gt;が入っていますので、ダブルクリックなどして開き、インストールを始めます。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ただし、初回は失敗します。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;先程のダウンロードページにあるように、設定のセキュリティとプライバシー、設定ペインでsoundflowerを許可する必要があります（すいません、スクショは撮れず）。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;The first time you run the installer (Soundflower.pkg), it will ask for your admin password, and will FAIL! A security alert will appear, with a button to take you to System Preferences &amp;#34;Security &amp;amp; Privacy - General&amp;#34; pane. Once there, there should be an &amp;#34;Allow&amp;#34; button (**) that you will need to click on to give permission to use Soundflower (developer: MATT INGALLS). Then, RUN THE INSTALLER AGAIN. It should inform you installation was successfull.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;その上で再度&lt;code&gt;Soundflower.pkg&lt;/code&gt;を実行すればインストール完了となります。&lt;/p&gt;
&lt;p&gt;Soundflowerという名前のオーディオデバイスが作成され、音声入力として利用できるようになります。&lt;/p&gt;
&lt;p&gt;ただし、これだけではMacで鳴っている音を入力として使うことができません。Macの音をSoundflowerに流すような設定が必要です。&lt;/p&gt;
&lt;h2 id="出力デバイスの作成"&gt;出力デバイスの作成&lt;/h2&gt;
&lt;p&gt;続いて出力デバイスを作ります。&lt;/p&gt;
&lt;p&gt;SpotlightなどでMIDIと入力すると&lt;code&gt;Audio MIDI設定.app&lt;/code&gt;という名前のアプリがみつかりますので、こちらのアプリ上で設定を進めます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Rm1xmc0S_dJQS_5Jr2sa8g06tHG82edxyGlkzT8sYRfBSUjwU--Ut-sKGHfbojCoumVhSaAcjahluhQdNTUBGb8YD8fZbhzTSYoD_ioCSqZNCAopGS4wwbzMQdPcs9naypr0B2IpEfb3_XtEGDGgZW_qp8TvaVFpcZfSDOueTJw5pgsjasdXgB9Y-iBBQFRphbpmYqAISauWKrCCvw_4c_W1foB5ZWVVElh0ahSOYsG7_gaTsyyXWKO5m8c7XlTGh_orYfp1KYHd7uKYgLCxT5ClBAAiEuuRDwAZZ1f5CaFrryl4mC9O6SeWOQFVCeksaHi9B2Udl9GjbgzHJsJreJD9doyjn9KaYBsXLCutYdygWDdBMm1VBpZqK8RFsO8b875YIcDh2pb5j7P1QlTgN5Dy5l4CzuSZik8-LTtsipxEWx5qjDQsE-me9zesVHBqttFb1dkaiuc7J9gIxJETDs_mwSADRAO2-2P8rf5Yrr2lbVF9GUX0gieS_J5dgjqxmbb6X2vai1-NeZgESuXa1PNgk0fTkx_mMbB5PnlPPSQXUYCdHFyfEZBL3SDytnZKDARpJBNvdIgm0FAnSp_ymHlG_3gFgwWuZ8agHZNPj_HmOcyNQD_3-qhxhR6tDhXXMGE5n5BEjffZdOEXTjn8Ep5y44rwG7cXezPVM7x1wrH2lNJ-On23YRNEGMbZR0PDy5eNpevqmpYFNmsOHOQ4u_u6tg=w600-h510-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Rm1xmc0S_dJQS_5Jr2sa8g06tHG82edxyGlkzT8sYRfBSUjwU--Ut-sKGHfbojCoumVhSaAcjahluhQdNTUBGb8YD8fZbhzTSYoD_ioCSqZNCAopGS4wwbzMQdPcs9naypr0B2IpEfb3_XtEGDGgZW_qp8TvaVFpcZfSDOueTJw5pgsjasdXgB9Y-iBBQFRphbpmYqAISauWKrCCvw_4c_W1foB5ZWVVElh0ahSOYsG7_gaTsyyXWKO5m8c7XlTGh_orYfp1KYHd7uKYgLCxT5ClBAAiEuuRDwAZZ1f5CaFrryl4mC9O6SeWOQFVCeksaHi9B2Udl9GjbgzHJsJreJD9doyjn9KaYBsXLCutYdygWDdBMm1VBpZqK8RFsO8b875YIcDh2pb5j7P1QlTgN5Dy5l4CzuSZik8-LTtsipxEWx5qjDQsE-me9zesVHBqttFb1dkaiuc7J9gIxJETDs_mwSADRAO2-2P8rf5Yrr2lbVF9GUX0gieS_J5dgjqxmbb6X2vai1-NeZgESuXa1PNgk0fTkx_mMbB5PnlPPSQXUYCdHFyfEZBL3SDytnZKDARpJBNvdIgm0FAnSp_ymHlG_3gFgwWuZ8agHZNPj_HmOcyNQD_3-qhxhR6tDhXXMGE5n5BEjffZdOEXTjn8Ep5y44rwG7cXezPVM7x1wrH2lNJ-On23YRNEGMbZR0PDy5eNpevqmpYFNmsOHOQ4u_u6tg=w600-h510-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;左下の+ボタンを押す&lt;/li&gt;
&lt;li&gt;複数出力装置を作成&lt;/li&gt;
&lt;li&gt;新しくできた装置を選び、右側から内蔵出力、Soundflower(2ch)の2つを選ぶ&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/zjUS-FWdhvQ8Lqbt-mGpbMJSRRW8qiX5blcNRcEa2AUBGGy_NDDdDPhjbgCV_tuFdWzs4lk4eB2LWDrLl4OdHQfdSJ6HXJLiMX3vDOZr1_xqgthjnkw0IDVp8q5aCEIvaZ3qPQXBzb4MS-4yRJjopM_OXIYdbmz7T8sj6lY_TozX6QrKyNisMbCdwx3vxoSEzMb1YehqDGrAPMMDMtJ3KUqxc58yokdPYeUmHKcI78Zj4IDtxpdSG_OREK084876JDK46hYHFXwFzcrZ_znLRObXq8xVtxzMWWuMHbJ00YO0KYR7qj_ZpKEub6uDiv2mMVtWWiEY70eUxcKJyxr9c-YKT4Suoj_I2VM_zNUN70BK44QFspONLFh7T_gEDe6hObZpMDerdbX_b4NIg2Bn0_0HU8yq9zP4gK_WP4j1c4HNCPJS2t50twXczbd69b9XGq7V-e66bPb1JKcz6S2zdqrDhSZLv0LpBbaY2VxwPyS_QQ_1vJXmZZNRyFsTdpCmHiysLQ146lfDua_caO-TzZ5IClkTEMwVfgvknIjFgqQrbBXI2XNLlHV7rXupzozc8kNBrPFTrtweXc4OeeajlZKYvkSKnvgjTxUe3GYKNjPcPj6cqBG0adw8VAK8UneY69LfFNp184Rbo-H5wnCSzmXKIqyIoMfefoiRmASi0FWjn0XHH7dRmvmtA-Z8Qq7KP6BCzDgN7TU5XqiWEItAPLrHKg=w800-h790-no"&gt;&lt;img src="https://lh3.googleusercontent.com/zjUS-FWdhvQ8Lqbt-mGpbMJSRRW8qiX5blcNRcEa2AUBGGy_NDDdDPhjbgCV_tuFdWzs4lk4eB2LWDrLl4OdHQfdSJ6HXJLiMX3vDOZr1_xqgthjnkw0IDVp8q5aCEIvaZ3qPQXBzb4MS-4yRJjopM_OXIYdbmz7T8sj6lY_TozX6QrKyNisMbCdwx3vxoSEzMb1YehqDGrAPMMDMtJ3KUqxc58yokdPYeUmHKcI78Zj4IDtxpdSG_OREK084876JDK46hYHFXwFzcrZ_znLRObXq8xVtxzMWWuMHbJ00YO0KYR7qj_ZpKEub6uDiv2mMVtWWiEY70eUxcKJyxr9c-YKT4Suoj_I2VM_zNUN70BK44QFspONLFh7T_gEDe6hObZpMDerdbX_b4NIg2Bn0_0HU8yq9zP4gK_WP4j1c4HNCPJS2t50twXczbd69b9XGq7V-e66bPb1JKcz6S2zdqrDhSZLv0LpBbaY2VxwPyS_QQ_1vJXmZZNRyFsTdpCmHiysLQ146lfDua_caO-TzZ5IClkTEMwVfgvknIjFgqQrbBXI2XNLlHV7rXupzozc8kNBrPFTrtweXc4OeeajlZKYvkSKnvgjTxUe3GYKNjPcPj6cqBG0adw8VAK8UneY69LfFNp184Rbo-H5wnCSzmXKIqyIoMfefoiRmASi0FWjn0XHH7dRmvmtA-Z8Qq7KP6BCzDgN7TU5XqiWEItAPLrHKg=w800-h790-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここで作った複数出力装置をサウンド設定から出力に変更することでSoundflower(2ch)にMacの音が流れるようになります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/ERSZJVj6sAUYBFARdqWGT-dehSCaaKxjDcqmnkSOfGBbG2P4RPytqLFMjeSI66OdamaShKvZeuSF2nkKdYjcYAAbyG9USLhoDdvyjbfFjpNyl1wMSz7pEuaqR732zwJExCs-jWAx_aq1wOqoP_UGX27IBe6qyymIN1Ts-GsDxbjHeoIpEFyWab5ceBHQkZLAnKlwYmjRw0WqVmEAafBgWo0VRtPjVXronbA0FKitlD_0TscA7H_eF1seTciYByQdC8jYE8w0S_fRjlvh--ojsgimaHrJO2nP9a9tzTzVQDrWBhOriRDmyifQu8uPQcdbb7jcAhV9mOOIJESjJbGKm405G3ceOsH0ikQqu9Pv6NHwVNxEECQg4CfcWxSe0_ATe-Q_5nZuqLmHBdxF3jo7T9ABUZcSmrn6AUyz7lOTLXBzLVl3heAXT1AOWJ4DWnWQl2Gqz3Yi4TuH5YwM1vfzxCM8uAbMNKBLAYgo0To3otjaBIhRwk1yKW4tLUrNjrxGO_N1yI0k0kUWJkQblyxKGWnv1sXzjdzy0rn98wi9yMyNNea446qkd0o0ea1zfMw6SGcpOMiYVPcoVKBZX_U967QBJVyqEZiA3B2XmTVcqN0K-5LUafCl-DjzMluJQh9_hMMHhv_rO3Gw0VSLesdfrVTpA5e_EpFDKqscD9qNqUskWEaziu-t8siA9hdU1QBiAGGmqftPsxTy0HexyUL17WdDDA=w1334-h996-no"&gt;&lt;img src="https://lh3.googleusercontent.com/ERSZJVj6sAUYBFARdqWGT-dehSCaaKxjDcqmnkSOfGBbG2P4RPytqLFMjeSI66OdamaShKvZeuSF2nkKdYjcYAAbyG9USLhoDdvyjbfFjpNyl1wMSz7pEuaqR732zwJExCs-jWAx_aq1wOqoP_UGX27IBe6qyymIN1Ts-GsDxbjHeoIpEFyWab5ceBHQkZLAnKlwYmjRw0WqVmEAafBgWo0VRtPjVXronbA0FKitlD_0TscA7H_eF1seTciYByQdC8jYE8w0S_fRjlvh--ojsgimaHrJO2nP9a9tzTzVQDrWBhOriRDmyifQu8uPQcdbb7jcAhV9mOOIJESjJbGKm405G3ceOsH0ikQqu9Pv6NHwVNxEECQg4CfcWxSe0_ATe-Q_5nZuqLmHBdxF3jo7T9ABUZcSmrn6AUyz7lOTLXBzLVl3heAXT1AOWJ4DWnWQl2Gqz3Yi4TuH5YwM1vfzxCM8uAbMNKBLAYgo0To3otjaBIhRwk1yKW4tLUrNjrxGO_N1yI0k0kUWJkQblyxKGWnv1sXzjdzy0rn98wi9yMyNNea446qkd0o0ea1zfMw6SGcpOMiYVPcoVKBZX_U967QBJVyqEZiA3B2XmTVcqN0K-5LUafCl-DjzMluJQh9_hMMHhv_rO3Gw0VSLesdfrVTpA5e_EpFDKqscD9qNqUskWEaziu-t8siA9hdU1QBiAGGmqftPsxTy0HexyUL17WdDDA=w1334-h996-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;あとは音声入力としてSoundflowerを選ぶことでMacで鳴っている音を色々なアプリでも使えるようになります。&lt;/p&gt;</description></item><item><title>Nuxt.jsと同等ESLint設定を他のプロジェクトでも使う</title><link>https://blog.piyo.tech/posts/2019-03-09-fix-eslint-config/</link><pubDate>Sat, 09 Mar 2019 06:57:20 +0900</pubDate><guid>https://blog.piyo.tech/posts/2019-03-09-fix-eslint-config/</guid><description>&lt;p&gt;先日書いたようにVisual Studio Codeを使い始めました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2019-03-05-setup-vscode/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/CxCGKJ2Qvd4b-3twoW9UdNtqzX7j3ej2jM5ZnWuu6AKq_sOB5FaPin1Nf_uxanKyIg7QqpkUsMbiCEFBwqECsCEoeoowTyNLfKLXM8bZiGq9MLLzrPOF3OaiAx8qmgFSOR4-PaQed3eJA1XRwE_ewGBCSpYdGk1U1aDpR4G_gI5ZWHya0GMjrsFS6q6owxR2qypzVaA_ngLl2Hr8big6HOJdcygmrIauM2Mnbv-nrPKNRtQfH_dvsvlYQIRaFwvYn4tdmIB1GOtK3ztlJRCtNLehvoDaB9pd16ZxN5_zndl0B8veab8ZhTOIzJthc2nEwDJVow25pHDZq4p6Fi-8jsWd3Adf5NDZ5HwP5riwdaZybPOP9cVjcqmsytxU4QI0Sv6cG5s64SHqhr7QI62efy2Smg8VoVDWyuVESGk5aND83I6b24RKitMMWWam45GaCYT81QBl1paCvuAvZoxji6yCytl3lEyuMMsoyfY0yKfd2bKfbJHGkZm3n6Snq-jdBfZ49JTYHRYwonFWdNEy-Zm4GvSra6A7FNpvZy12Qp0FdDLqaC1M_6CJ34ZfXehSyeZ0KrvLt2E-Ke3yrT4caw2bA23KjKMUWw6umEWOSgIqHbD7Ytd9ibFmQ2M0iThe_OWhNBWATVAoM0Ph1A___cBXJQ_vxqH5K7BgsxngSvVsOpXtgSS5yY5iEGjv_lQOyz-7VUvrMqV-qpby4O765SUCbA=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Emacs卒業なるか。JS用のエディタとしてVS Code使い始める際に設定したこと。 - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;普段使いのエディターはEmacsでして、仕事で一番書いている割合の多いRailsやテキストを書く際に使っています。 JavaScriptが面倒です。JSXやVueコンポーネントなど少々複雑なフォーマットのファイルを編集したり、サクっとESlintを書けたりするのがうまくいきません。いや、できないことはないけど惜しい感じで便利ではないのです。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;いざ手持ちのReact NativeプロジェクトをVS Codeで開いて編集し保存したら自動的にESLintによるフォーマットが効いてくれた！&lt;/p&gt;
&lt;p&gt;のですが…、保存のたびに結果が変わる挙動をしてしまいました。かわるというか、2つのパターンを行ったり来たりというか、結果が揺れる感じです。&lt;/p&gt;
&lt;p&gt;そのプロジェクトはReact Nativeのプロジェクトで、保存のたびに↓のような感じで&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;View&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{...}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;となったり、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;View&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{...}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;のようになったりといったり来たり。
こんなの困ります。保存するたびに差分ができるなんて！&lt;/p&gt;
&lt;p&gt;まあね、言われてみればESLintの設定をごちゃっとやっていてなんだかよくわかっておらず設定した節があります。どこかに矛盾があるんですかね。&lt;/p&gt;
&lt;p&gt;そこでESLintの設定を見直すことに。&lt;/p&gt;
&lt;h2 id="nuxtのeslintがよかった"&gt;NuxtのESLintがよかった&lt;/h2&gt;
&lt;p&gt;Nuxt.jsを触ったとき、ESLintの効きがちょうどいいなーと思った記憶があります。それを思い出して調べてみると、Nuxtのプロジェクトに&lt;code&gt;@nuxtjs/eslint-config&lt;/code&gt;なるパッケージが入っていました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/nuxt/eslint" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/b625f38c407293ef4bda8cc237cd12893e157e40224e724389e8f6cfa3e64fd0/nuxt/eslint" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - nuxt/eslint: Collection of ESLint-related packages for Nuxt&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Collection of ESLint-related packages for Nuxt. Contribute to nuxt/eslint development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;あのいい感じにできるのならやってみようかなと思い、READMEにしたがって入れてみました。
そして、既存の&lt;code&gt;.eslintrc&lt;/code&gt;をバッサリ捨てて新しく以下のように書き換えて実際にファイルを触ってみると、保存のたびに結果が揺れることがなくなりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;parserOptions&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;parser&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;babel-eslint&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;sourceType&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;module&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;extends&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;@nuxtjs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="reactreact-nativeでの追加設定"&gt;React/React Nativeでの追加設定&lt;/h2&gt;
&lt;p&gt;NuxtはVueベースなので、React Nativeに関係する指摘をしてほしい場合にはルールが足りません。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;eslint-plugin-react&lt;/li&gt;
&lt;li&gt;eslint-plugin-react-native&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;の導入と設定追加を行います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% npm install --save-dev eslint-plugin-react
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;% npm install --save-dev eslint-plugin-react-native
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;.eslintrc&lt;/code&gt;に以下のように追加。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;plugins&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;/*&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;...&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;*/&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;react&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;react-native&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;extends&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;/*&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;...&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;*/&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;@nuxtjs&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;plugin:react/recommended&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;plugin:react-native/all&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;plugins&lt;/code&gt;の指定は必須、&lt;code&gt;extends&lt;/code&gt;するのか、個別にルールを選んでいくのかはお好みです。&lt;/p&gt;</description></item><item><title>Working CopyとGoCoEditでiPadでコードリーディング</title><link>https://blog.piyo.tech/posts/2019-03-07-source-code-reading-on-ipad/</link><pubDate>Thu, 07 Mar 2019 05:37:22 +0900</pubDate><guid>https://blog.piyo.tech/posts/2019-03-07-source-code-reading-on-ipad/</guid><description>&lt;p&gt;iPhoneが出てからというもの、ソースコードリーディングを暇な時にできればなーとずっと画策していたのですが、なかなかかなわず。&lt;/p&gt;
&lt;p&gt;iPadでコードを書ける環境を整備するってのをちょくちょく見かけてたし、つい最近もバズったのがあったんで改めて調べてみました。&lt;/p&gt;
&lt;p&gt;いつも「iPad コードリーディング」などと調べることがいいんですが、観点を「読む」から「書く」に変えて「iPad プログラミング エディター」などと調べてみました。&lt;/p&gt;
&lt;p&gt;なぜか今まであまり考えたことがなかったけど、プログラミングができるなら読むのだってそれなりにできるはずです。&lt;/p&gt;
&lt;h1 id="working-copy"&gt;Working Copy&lt;/h1&gt;
&lt;p&gt;まずGitHubを参照するにあたり、&lt;strong&gt;Working Copy&lt;/strong&gt;というアプリを入れます。&lt;/p&gt;
&lt;p&gt;Working CopyはiOSデバイスで動くGitクライアントでリポジトリをクローンしたり、手元でファイルを変更してリモートリポジトリへPushしたり色々なことができます。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://itunes.apple.com/jp/app/working-copy/id896694807?mt=8" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;itunes.apple.com →&lt;/span&gt;&lt;span&gt;https://itunes.apple.com/jp/app/working-copy/id896694807?mt=8&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;実はこれ単体だけでもそれなりにコードを読むことができます。ディレクトリツリーを辿ってファイルを開けるし、ある程度シンタックスハイライトしてくれるし、シンボルの検索もできます。&lt;/p&gt;
&lt;p&gt;読みたいプロジェクトによってはこれだけでも十分使えるレベルと言えそうです。&lt;/p&gt;
&lt;p&gt;キャプチャでちょっと紹介します。&lt;/p&gt;
&lt;h2 id="railsrailsをクローンしてみる"&gt;&lt;code&gt;rails/rails&lt;/code&gt;をクローンしてみる&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/avCg3bV40xs5QJb2gIhDc8rzZVPl91CEV8AhXYEOzICWjUqJlz5pNP0yZg_Q1MrwufTtP3CsjmJfMAwVWtyVpSLSlJsxwGeJN4c6wfydqHzTfVBoTEGoAUUkfWWQHrbr8zOjZdx_5bWaNHSaWbpPUGRnDZUS9GYih5hKx0ib-uEZy3UP3mLhkL6fds_ux8rfIgW_1SoYm5Cxw403ELNaFE4GB2-Y38maxsw1JGUeh2BMKImn8PEV3XZji8kZ3E5F5Rogt463ZzZAmBcYS2ZsvK82vxceuvByh9xk0FsWhHa0wTV-Vuer3U6JBGu4tvVQ9vwBZ6YIKLmaafc3QCuocIJ40uKUBJU07jgs7oI6r-CveaO2qhHDCsoFZBP0ioAozMDVKEze1dG7XrzznFxtr1vjWFY7LwjT7M7zDl2MVZ94_OyKBbc5-xWkMx-uKXKuc2G6XWvu1lsmeBLcjwk3DFZHm3B7Uz5dgWi4mbqNchXDt06Q7cpMKPkJq6nh7h9bkwmoQjGgwDGi949jNzP5QlIEpoXgp_EBMrLBCELC50wgOpolEVBKvBpPBE6yLxQBzSGGPHedWghkQQAdo7V8K78J-v--xQEdvInL6F4ChmYTry-YPqAOX1PufJ4D_ZClJJpxFBConfwfZSwifhG2w8Kob6uKrt97GsdeaLkpmPq9c6V01mAFqNt24PISjwleA9K6hJ4fixRAFIxkve4lFdvWhg=w1360-h974-no"&gt;&lt;img src="https://lh3.googleusercontent.com/avCg3bV40xs5QJb2gIhDc8rzZVPl91CEV8AhXYEOzICWjUqJlz5pNP0yZg_Q1MrwufTtP3CsjmJfMAwVWtyVpSLSlJsxwGeJN4c6wfydqHzTfVBoTEGoAUUkfWWQHrbr8zOjZdx_5bWaNHSaWbpPUGRnDZUS9GYih5hKx0ib-uEZy3UP3mLhkL6fds_ux8rfIgW_1SoYm5Cxw403ELNaFE4GB2-Y38maxsw1JGUeh2BMKImn8PEV3XZji8kZ3E5F5Rogt463ZzZAmBcYS2ZsvK82vxceuvByh9xk0FsWhHa0wTV-Vuer3U6JBGu4tvVQ9vwBZ6YIKLmaafc3QCuocIJ40uKUBJU07jgs7oI6r-CveaO2qhHDCsoFZBP0ioAozMDVKEze1dG7XrzznFxtr1vjWFY7LwjT7M7zDl2MVZ94_OyKBbc5-xWkMx-uKXKuc2G6XWvu1lsmeBLcjwk3DFZHm3B7Uz5dgWi4mbqNchXDt06Q7cpMKPkJq6nh7h9bkwmoQjGgwDGi949jNzP5QlIEpoXgp_EBMrLBCELC50wgOpolEVBKvBpPBE6yLxQBzSGGPHedWghkQQAdo7V8K78J-v--xQEdvInL6F4ChmYTry-YPqAOX1PufJ4D_ZClJJpxFBConfwfZSwifhG2w8Kob6uKrt97GsdeaLkpmPq9c6V01mAFqNt24PISjwleA9K6hJ4fixRAFIxkve4lFdvWhg=w1360-h974-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="中身を見たり検索したり"&gt;中身を見たり検索したり&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/SYNH8imzcrc1HT-xF-ECaEc-JmZgYsbOm7zNs1FPNfKmq0z111a0BnnER6CLn8Qkq5pyDb2unTULcUoR_zX2rTtt1NCyQv4Lt0rt5M0Q0OqcfqONbIU2LM25XXt3prPOIJdUkQpytgA9dLw0v0HAkW2D2eNS49AjNPqvELyM2CWpQjYn9Kgjrp1MDR8Pn0c1xyUPePPt5wyvtwHs1WAiAcCM1-ujA5diwKmXRBZjBoCW0Hr6HzVRaZobpLyHn3K6Qc-q4O6gs97P5yXTeg47PcGV9VJJwpOvOA8tGRky0RTiEZtgT3qpEWNTP7jOGdWiWHmMPMtpkztJIfXTdpqlJEAXcVIxxR_hfKZa2pVDj3oYbtZQwQIgc53EntGnaUERhWUrqa3poiJNVQ20est28wqdUziEO0KU7kOZyRSsZZtW2cMnZhtu5Wu-Kw9e7HG4Okcw1QGtV1bcr14eLNMLxWTDo6cYYP2nxx6W2bvaBO_CWZNkiP29w1lRXvKwYRGS7kikJil9rFXpUQHwjOrp2yQbnCWI9PJy5CVa7dSBMbhcTVn1czny5PN5TlPPft5djgHzcXwJ0iXFINyxBEw-Rlzhzh5ic-8c7LL0bDVD_kbUOrDG_xxvkEU6COrIm7Pp7mSmFzmM_30JKJDzNNzo3M1vpaayLqjA4E80sTxzQW5KXJSSRJWQD7Yy689EXWr_8v_Cgw1LdsHoFozgi19qi7vFGA=w1815-h974-no"&gt;&lt;img src="https://lh3.googleusercontent.com/SYNH8imzcrc1HT-xF-ECaEc-JmZgYsbOm7zNs1FPNfKmq0z111a0BnnER6CLn8Qkq5pyDb2unTULcUoR_zX2rTtt1NCyQv4Lt0rt5M0Q0OqcfqONbIU2LM25XXt3prPOIJdUkQpytgA9dLw0v0HAkW2D2eNS49AjNPqvELyM2CWpQjYn9Kgjrp1MDR8Pn0c1xyUPePPt5wyvtwHs1WAiAcCM1-ujA5diwKmXRBZjBoCW0Hr6HzVRaZobpLyHn3K6Qc-q4O6gs97P5yXTeg47PcGV9VJJwpOvOA8tGRky0RTiEZtgT3qpEWNTP7jOGdWiWHmMPMtpkztJIfXTdpqlJEAXcVIxxR_hfKZa2pVDj3oYbtZQwQIgc53EntGnaUERhWUrqa3poiJNVQ20est28wqdUziEO0KU7kOZyRSsZZtW2cMnZhtu5Wu-Kw9e7HG4Okcw1QGtV1bcr14eLNMLxWTDo6cYYP2nxx6W2bvaBO_CWZNkiP29w1lRXvKwYRGS7kikJil9rFXpUQHwjOrp2yQbnCWI9PJy5CVa7dSBMbhcTVn1czny5PN5TlPPft5djgHzcXwJ0iXFINyxBEw-Rlzhzh5ic-8c7LL0bDVD_kbUOrDG_xxvkEU6COrIm7Pp7mSmFzmM_30JKJDzNNzo3M1vpaayLqjA4E80sTxzQW5KXJSSRJWQD7Yy689EXWr_8v_Cgw1LdsHoFozgi19qi7vFGA=w1815-h974-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;なかなか、それなりに見えますよね。&lt;/p&gt;
&lt;h2 id="ipadでも使える"&gt;iPadでも使える&lt;/h2&gt;
&lt;p&gt;サイドバーとエディター画面にわかれているのでもう少し使いやすいです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/H9zh1Nt8veRLXacQxs7v_BQRqEaE73qjqkrxXwDl_ALSbEMgfm7NdMnfj6CSeIM-UXzyxK8_FH3ZWk881D5e_2-lIe7proU6cUhSIbu6VAbdcB6yVM3Kz5JApEPUa7bUtsdlFP0DT7TxQ1FBSlHBnufm6RRpL-fdrpfjVZG4zqM3uSidOCji3pMc8ku3_00AUOWNv5goqhTPPu2eou6dPbMnDUUski2l_kdbhiduoq0choS7RGQ0cTdBR_o5uAnhgHpxYRjHhVoq0-DYLeaTHGxOO01Hnl6aNEIb2wQsUSOkIk6t3owIybps-4eJp_NfMcmf9yNCOb2kMRavIwLafjpo6yc0vCwcxzA3QMwwghQcl7vp1brpSb3aEYOiakw_HVq-h4efglZLDnZB-TNjcqRmInAB8rUbShe0a_8yEP8KAPJ5f95zOfyjxcI66ubvqlX_yusNccS3lsFxmyYASterk0wdWeZarVpPfsFf2Ap45BcUzInOYT5HiCZAiGec8vKrEgdfiR9duLVTWoBczWAvVERGW546lcUX19738Ies77Gutz0oUWhzpqyfvsKEfRHQ7L-1OASXfG-38tB0nw0djpbd8ZYmC_SmvPpDPt2Vpe8NTUajpFC-puc5kAJExsgKssTjGjNEQGHjbekMkyYI7jYkIrCh2LS-tK6Ub7eM7-INmnL6DnZiFVtcNqjjLBBJWTgX2jygM4wTXRXXsIlhlQ=w819-h614-no"&gt;&lt;img src="https://lh3.googleusercontent.com/H9zh1Nt8veRLXacQxs7v_BQRqEaE73qjqkrxXwDl_ALSbEMgfm7NdMnfj6CSeIM-UXzyxK8_FH3ZWk881D5e_2-lIe7proU6cUhSIbu6VAbdcB6yVM3Kz5JApEPUa7bUtsdlFP0DT7TxQ1FBSlHBnufm6RRpL-fdrpfjVZG4zqM3uSidOCji3pMc8ku3_00AUOWNv5goqhTPPu2eou6dPbMnDUUski2l_kdbhiduoq0choS7RGQ0cTdBR_o5uAnhgHpxYRjHhVoq0-DYLeaTHGxOO01Hnl6aNEIb2wQsUSOkIk6t3owIybps-4eJp_NfMcmf9yNCOb2kMRavIwLafjpo6yc0vCwcxzA3QMwwghQcl7vp1brpSb3aEYOiakw_HVq-h4efglZLDnZB-TNjcqRmInAB8rUbShe0a_8yEP8KAPJ5f95zOfyjxcI66ubvqlX_yusNccS3lsFxmyYASterk0wdWeZarVpPfsFf2Ap45BcUzInOYT5HiCZAiGec8vKrEgdfiR9duLVTWoBczWAvVERGW546lcUX19738Ies77Gutz0oUWhzpqyfvsKEfRHQ7L-1OASXfG-38tB0nw0djpbd8ZYmC_SmvPpDPt2Vpe8NTUajpFC-puc5kAJExsgKssTjGjNEQGHjbekMkyYI7jYkIrCh2LS-tK6Ub7eM7-INmnL6DnZiFVtcNqjjLBBJWTgX2jygM4wTXRXXsIlhlQ=w819-h614-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/v1obNCzf3dbRt9IXCiKRq1zNMCcwi7kYvSVBW4QRYN22aar4N9ry2-3UqltwQV7HIh2u8kya4iYVBOruEjpzK5rvdtG-MceWdUR63wT6EfLyXzq_CsWN-2CCcWr7R2TL_XxJPVyW4MQUtIElLWRH_sjFBeTjUJ41t7NiYJm8O2xrLKO-UyQ6wJ8L7cpj4yO22dbHjlFsAKgE9_cOtYSVVT8PRPxs4I40xK-S0SooYBZvPrfFa2X6GxvyEqghXtgNp9rzgEE9GMfXqEl-v-2WmUcZu0s9A-DwZmo2KJgL90769e1XqDmYx2jwCD-TcalZ5EpY5Eyc-_2z9G8VVK4TqZTV01kVCOiZAj-Gu5_lpoaDL9kZrun_-7SIoNPRm8zHS4gF8xrY9kOd8ZOCNLa4jdhTVgXaKom_D0sQvvlvc0nWYVBHBdSbl6TaEGadN--Li-vPdIfOX_U0IwKKpsEMNc9xCmyU9j96DaGWaBhSdAPfnOlHPmhTxnlEbyCdShyQZn_kz9uqxdz8l6sqbLn7c5MhQjBSs6R7ehqGRGf5NnZG4D0MydB26EZqjCSEBDfGJtiYCGs36vumifm5vDB35Xj6NrlNEIf1x0RbePewEuj6KHFZa79-E4cu66-c1Uk4cPiRXsaJ4DslqyWU161417BGvA_ssObpSAKHn-evSZXfBavWE5lbJTQzEdtUzupVabDYmrLnRMqkUHebGZZhGaXSXw=w819-h614-no"&gt;&lt;img src="https://lh3.googleusercontent.com/v1obNCzf3dbRt9IXCiKRq1zNMCcwi7kYvSVBW4QRYN22aar4N9ry2-3UqltwQV7HIh2u8kya4iYVBOruEjpzK5rvdtG-MceWdUR63wT6EfLyXzq_CsWN-2CCcWr7R2TL_XxJPVyW4MQUtIElLWRH_sjFBeTjUJ41t7NiYJm8O2xrLKO-UyQ6wJ8L7cpj4yO22dbHjlFsAKgE9_cOtYSVVT8PRPxs4I40xK-S0SooYBZvPrfFa2X6GxvyEqghXtgNp9rzgEE9GMfXqEl-v-2WmUcZu0s9A-DwZmo2KJgL90769e1XqDmYx2jwCD-TcalZ5EpY5Eyc-_2z9G8VVK4TqZTV01kVCOiZAj-Gu5_lpoaDL9kZrun_-7SIoNPRm8zHS4gF8xrY9kOd8ZOCNLa4jdhTVgXaKom_D0sQvvlvc0nWYVBHBdSbl6TaEGadN--Li-vPdIfOX_U0IwKKpsEMNc9xCmyU9j96DaGWaBhSdAPfnOlHPmhTxnlEbyCdShyQZn_kz9uqxdz8l6sqbLn7c5MhQjBSs6R7ehqGRGf5NnZG4D0MydB26EZqjCSEBDfGJtiYCGs36vumifm5vDB35Xj6NrlNEIf1x0RbePewEuj6KHFZa79-E4cu66-c1Uk4cPiRXsaJ4DslqyWU161417BGvA_ssObpSAKHn-evSZXfBavWE5lbJTQzEdtUzupVabDYmrLnRMqkUHebGZZhGaXSXw=w819-h614-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="working-copyの弱点"&gt;Working Copyの弱点&lt;/h1&gt;
&lt;h2 id="navigationが大変"&gt;Navigationが大変&lt;/h2&gt;
&lt;p&gt;iPhoneにしてもiPadにしてもナビゲーションが大変です。ファイルの移動をするのにディレクトリを戻ったり潜ったり。&lt;/p&gt;
&lt;p&gt;iPadはサイドバーがありますが、選べるのは同一階層のみ。別階層のファイルを交互に読みたいときなどには適していません。&lt;/p&gt;
&lt;h2 id="シンタックスハイライトが弱い"&gt;シンタックスハイライトが弱い&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;haml&lt;/code&gt;とか&lt;code&gt;vue&lt;/code&gt;とか、プログラミング言語そのものではないフォーマットのハイライトができません。&lt;/p&gt;
&lt;p&gt;たとえばvueコンポーネントはこんな感じになっちゃってまともに読めません。実は最近Vueアプリのコードを読みたいと思っていたのでこれは困ります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/mPVT5XjaUuwvO90NfdFoVjY804zzfX0WXBYGGdnIwF4awwWehnNHSbXEcFfXyXTjma72MY9Dzi4q4rI1_jICbygF3i39rU6w06US45L_a2kJK_XL05ZyE1hNjFwBdaJ2KfLcqT57-Pn1YEXB_IVZTSogzKceevhRyi60rjCNtuyak4YKJt3hsddnCxDI7I867saJGNNnh2awazX7kMyNrrQdcxqXRmOhK4RkJMLs1lVNAnbkHeMR6ZROVCpGGz9qlaXwMjJBhAnPiAysNWn2a9bD5aI_88pz0gotx3sSH1IHq73gJAnQ_h3dWq8L8x44S9P_hd922KnhVdjnGMs5T_c1gPjU3Y61E0dkMx9oPsGEvnh1wUZk4RUpxeQuasyzv1zOz_hyu15MU_AqYWM_tVB0T6zItUpyxEjrcD_0CMvpNy8r3x7eDfs5Z9LuAK75UyX0D0JMhu_h96D4kDyRfBK9TXD4PiDqHXShRHssVramGnf5kO-xBLoaXWXBBIjKuRlZy_UIp9h_N2mb1OC4SL1pQCtt1j4JiHxo5MAmMENnS9zotZhm2irRP7wUp-AwQbgTLkJPaguH9ueE7ewc78ZMNotPHFffbIz51gU5bS-ghOayNmUsuKRoFncISbcaFTIrN7ZE1LhVOYgSIbhpt_mjbflHCxAo-Wb4s-g67dpdbD-XoGluJSnm4mLJ_buikL9Xf17kj5gqtTWBN9SO3ogR3A=w819-h614-no"&gt;&lt;img src="https://lh3.googleusercontent.com/mPVT5XjaUuwvO90NfdFoVjY804zzfX0WXBYGGdnIwF4awwWehnNHSbXEcFfXyXTjma72MY9Dzi4q4rI1_jICbygF3i39rU6w06US45L_a2kJK_XL05ZyE1hNjFwBdaJ2KfLcqT57-Pn1YEXB_IVZTSogzKceevhRyi60rjCNtuyak4YKJt3hsddnCxDI7I867saJGNNnh2awazX7kMyNrrQdcxqXRmOhK4RkJMLs1lVNAnbkHeMR6ZROVCpGGz9qlaXwMjJBhAnPiAysNWn2a9bD5aI_88pz0gotx3sSH1IHq73gJAnQ_h3dWq8L8x44S9P_hd922KnhVdjnGMs5T_c1gPjU3Y61E0dkMx9oPsGEvnh1wUZk4RUpxeQuasyzv1zOz_hyu15MU_AqYWM_tVB0T6zItUpyxEjrcD_0CMvpNy8r3x7eDfs5Z9LuAK75UyX0D0JMhu_h96D4kDyRfBK9TXD4PiDqHXShRHssVramGnf5kO-xBLoaXWXBBIjKuRlZy_UIp9h_N2mb1OC4SL1pQCtt1j4JiHxo5MAmMENnS9zotZhm2irRP7wUp-AwQbgTLkJPaguH9ueE7ewc78ZMNotPHFffbIz51gU5bS-ghOayNmUsuKRoFncISbcaFTIrN7ZE1LhVOYgSIbhpt_mjbflHCxAo-Wb4s-g67dpdbD-XoGluJSnm4mLJ_buikL9Xf17kj5gqtTWBN9SO3ogR3A=w819-h614-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="そこでgocoedit"&gt;そこでGoCoEdit&lt;/h1&gt;
&lt;p&gt;そんな弱点を補ってくれるのが&lt;strong&gt;GoCoEdit&lt;/strong&gt;というiOSアプリです。買い切りの有料アプリで、大体1000円ほど。ファイルの移動やシンタックスハイライトもだいぶ快適です。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://itunes.apple.com/jp/app/gocoedit-code-text-editor/id869346854?mt=8" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;itunes.apple.com →&lt;/span&gt;&lt;span&gt;https://itunes.apple.com/jp/app/gocoedit-code-text-editor/id869346854?mt=8&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;iCloud Driveからファイルの読み出しができるほかGoogleDriveやDropboxなどとも連携できますが、なんといってもWorking Copyからファイルをまるっと読み出せるのが良いです。&lt;/p&gt;
&lt;p&gt;つまりGitHubからCloneしたリポジトリのコードを全部GoCoEdit側で開くことができ、Working Copyよりも便利にコードを読めるというわけです。&lt;/p&gt;
&lt;p&gt;初期設定ではエディター部を選択したときにかならずキーボードが開いてしまいますが、これは設定の「Enable Auto-Keyboard」の設定を無効にすることで回避でき、読むことに専念できます。&lt;/p&gt;
&lt;p&gt;参考までにスクショを載せてみます。まずはファイルツリー。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/E_d_Hjy-sXGWGOh3nyo3P8dzVDq_TjnUpDkxbir4xDiEKZElWSK-KHVKfbOAldYPWHnmN_P7scN_EfFJ1jvOLVBmj8kEv123eIAqSsN9C22bx0n9JksoIbLWyt8-JkEQU_tsrNiRFl5h2EC4axvymSbFPXrHJ3frktLW9slRN0LhecQPN4Djn_6XlyFuDWnwj7_EdIQOM1VmDfN7BBgO1tf0Y0Y2bDh3SMAdB00qXxWptTUqVD0gG35Gfx1dsBM1S2mXqpu0I3NawO_B_rC1NgGoC6tse6GenZ3GutpkhCWT71rA7uyIO4z5NRf3PoPKzVutFApQbub1ygMxFOfpOFQ_E_E0UMfkYTDqR-w2Xb23L7yXgOk-gfJEFO6kVzzW2ygfvEHgf7cmhJF-uSC0ZsZLdQFEet94pAnMLnjCXgYF1xAV0SZNnqsNpgkPnClRB_UeIU2sRD3zPnFcTfZMSaqFef5KywKX1KX51N0m87S0SItVofN4H9nWmglfPngSdVGXV-lUkSTGPLY_STzdeQxzi9kw3MsnttKW2cgA_bMqVlfvZPmaE1gxewycbnGxWAMOGjxD74HVH2osW_zhIkVjxbAq28uZrBsYYsNK_YeufPcevQVwPi0MEE3OqPxgLXDhRjpM-a_lYjUPjb5ljDjjVYXCraK9gPLPRu4iXrp4d_TrNGsUA5RLaoxr-6DPFghFyezP5_vKFoB-QnANzNNZOg=w819-h614-no"&gt;&lt;img src="https://lh3.googleusercontent.com/E_d_Hjy-sXGWGOh3nyo3P8dzVDq_TjnUpDkxbir4xDiEKZElWSK-KHVKfbOAldYPWHnmN_P7scN_EfFJ1jvOLVBmj8kEv123eIAqSsN9C22bx0n9JksoIbLWyt8-JkEQU_tsrNiRFl5h2EC4axvymSbFPXrHJ3frktLW9slRN0LhecQPN4Djn_6XlyFuDWnwj7_EdIQOM1VmDfN7BBgO1tf0Y0Y2bDh3SMAdB00qXxWptTUqVD0gG35Gfx1dsBM1S2mXqpu0I3NawO_B_rC1NgGoC6tse6GenZ3GutpkhCWT71rA7uyIO4z5NRf3PoPKzVutFApQbub1ygMxFOfpOFQ_E_E0UMfkYTDqR-w2Xb23L7yXgOk-gfJEFO6kVzzW2ygfvEHgf7cmhJF-uSC0ZsZLdQFEet94pAnMLnjCXgYF1xAV0SZNnqsNpgkPnClRB_UeIU2sRD3zPnFcTfZMSaqFef5KywKX1KX51N0m87S0SItVofN4H9nWmglfPngSdVGXV-lUkSTGPLY_STzdeQxzi9kw3MsnttKW2cgA_bMqVlfvZPmaE1gxewycbnGxWAMOGjxD74HVH2osW_zhIkVjxbAq28uZrBsYYsNK_YeufPcevQVwPi0MEE3OqPxgLXDhRjpM-a_lYjUPjb5ljDjjVYXCraK9gPLPRu4iXrp4d_TrNGsUA5RLaoxr-6DPFghFyezP5_vKFoB-QnANzNNZOg=w819-h614-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;続いてVueコンポーネントのシンタックスハイライト。ちなみにこちらのスクショでは画面上部にファイルごとのタブが見えるのがわかります。開いているファイルはタブで切り替えることも可能です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/2uThoI1CKUv_X1sl3srGCsIdarEQNq-z4gkardMW75jQw7b8fnGhKgmgrcKB6N6TrivlviodaBjukpu-1MwDyoLJp5se2VwHELbNsJccVmGydI8pWzCNneZJTD90UGCT-MTQ0QTNfG7An727zVz5twTZ8i3XizlGNn040zjlg2EhpccaG2keq0MPabck12L2DLhWyiJR9E-plepTejxvc2eYcFjV-DIGDS0bfvUbg3hQruJ08kVWIptd4DFuW0v60xB49knlxm-EbPDWvPIC1se3gt9UKRUKaLqAk_Er0S8Tb7tVV8JH5YxpentCTmzJkpOcLrCse30RtvgMhflU1DDx9Jh9zr2KfThYP3wQQVRdtkE8rqzdGPzbLL74BwsVa9hPjRvpAzkeELgXptAjxjczSD0iHUYEjapGBzwVc1dqGsUQti2BYGyRxXl5uAJvmYAQR0hmGAre3V9KCa_nlS1jW9IUNIgUuFw4piU5P5LHCohf1xbn5xPytgHg7ewLfZ6Sy0CBfNV-wVRsr22LXr08mHmJa0_HkLOSNRavpRqAdbOSJOoJKO4UpMUWXbnOAMm-a8M-5ABYvel3mMJ8pKzmaAkHCTV-OOHqnAv2WQZu59SRcKx84eLARCJcnw-kACXiGyntOGtvFDkFVpM4kM0ddo4R13EJYVANRhDjqekL_eA42IndbBTbE7TLFgpMTX6YLV61kSgIuRmuFAT8OFltHg=w819-h614-no"&gt;&lt;img src="https://lh3.googleusercontent.com/2uThoI1CKUv_X1sl3srGCsIdarEQNq-z4gkardMW75jQw7b8fnGhKgmgrcKB6N6TrivlviodaBjukpu-1MwDyoLJp5se2VwHELbNsJccVmGydI8pWzCNneZJTD90UGCT-MTQ0QTNfG7An727zVz5twTZ8i3XizlGNn040zjlg2EhpccaG2keq0MPabck12L2DLhWyiJR9E-plepTejxvc2eYcFjV-DIGDS0bfvUbg3hQruJ08kVWIptd4DFuW0v60xB49knlxm-EbPDWvPIC1se3gt9UKRUKaLqAk_Er0S8Tb7tVV8JH5YxpentCTmzJkpOcLrCse30RtvgMhflU1DDx9Jh9zr2KfThYP3wQQVRdtkE8rqzdGPzbLL74BwsVa9hPjRvpAzkeELgXptAjxjczSD0iHUYEjapGBzwVc1dqGsUQti2BYGyRxXl5uAJvmYAQR0hmGAre3V9KCa_nlS1jW9IUNIgUuFw4piU5P5LHCohf1xbn5xPytgHg7ewLfZ6Sy0CBfNV-wVRsr22LXr08mHmJa0_HkLOSNRavpRqAdbOSJOoJKO4UpMUWXbnOAMm-a8M-5ABYvel3mMJ8pKzmaAkHCTV-OOHqnAv2WQZu59SRcKx84eLARCJcnw-kACXiGyntOGtvFDkFVpM4kM0ddo4R13EJYVANRhDjqekL_eA42IndbBTbE7TLFgpMTX6YLV61kSgIuRmuFAT8OFltHg=w819-h614-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この組み合わせでコードリーディングを捗らせたいです。&lt;/p&gt;</description></item><item><title>Emacs卒業なるか。JS用のエディタとしてVS Code使い始める際に設定したこと。</title><link>https://blog.piyo.tech/posts/2019-03-05-setup-vscode/</link><pubDate>Tue, 05 Mar 2019 09:42:33 +0900</pubDate><guid>https://blog.piyo.tech/posts/2019-03-05-setup-vscode/</guid><description>&lt;p&gt;普段使いのエディターはEmacsでして、仕事で一番書いている割合の多いRailsやテキストを書く際に使っています。&lt;/p&gt;
&lt;p&gt;JavaScriptが面倒です。JSXやVueコンポーネントなど少々複雑なフォーマットのファイルを編集したり、サクっとESlintを書けたりするのがうまくいきません。いや、できないことはないけど惜しい感じで便利ではないのです。&lt;/p&gt;
&lt;p&gt;そこでこれまではWebStormを使ってきました。有償のIDEで必要な機能は大体揃っているし、JSの対応もバッチリでほぼ言うことありません。&lt;/p&gt;
&lt;p&gt;WebStormの唯一の欠点は鈍重であることです。いちいち動作が遅いし、メモリを食うので他のアプリケーションへの影響もあります。正確にいえばメモリ使用上限は設定ファイルで書き換えられますが、メモリを食わないようにすると動作がもっと遅くなるという状況に陥るため詰んでいます。&lt;/p&gt;
&lt;p&gt;そこで大体としてVisual Studio Codeを試してみることにしました。なんとなくイメージ的にJavaScriptな人がよく使っている印象があったからです。&lt;/p&gt;
&lt;h1 id="入れたもの変えた設定メモ"&gt;入れたもの・変えた設定メモ&lt;/h1&gt;
&lt;p&gt;前置きが長くなりましたが、EmacsユーザーとしてCodeにも入れておきたい拡張や設定などをメモしておきます。&lt;/p&gt;
&lt;p&gt;というのも、しばらく使ってみて諦める可能性が高く、そしてさらにしらばく経ってからまたVS Codeに戻ってみようと思うことになるのが目に見えているからです。そうです、「VS Codeでも使ってみるか」と思ったの、これで3回目ぐらいです。&lt;/p&gt;
&lt;p&gt;EmacsとWebStorm（というかJetBrains系）のいいとこどりというか、無理なくできる範囲で設定しました。&lt;/p&gt;
&lt;h3 id="ようこそ画面非表示"&gt;ようこそ画面非表示&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/VVqpwiGN2PqD4RjcJ4yRH9hJs42bqvXg0K2U_BHNuzqKsnD0OIKYfaI3L5CmVJOz1Um4VEW1qamSLjB0tMBCoUqLq6_ip4O8oNoBbiL3q2yi7-YTsv6_-UGBiBIOyaU0b1avZnwEpEgLWTC6WekHbGihVVqm8jY2FPzV2rn8gx61tbSA_LG-GGHNT2ss-RHwKSEIaO_xU2asT46AfnEFSbncOYs-eBLpJ-gAfHQfga-Tv2GufKBlTmDb74VUzriYl7BBsLaW48AXPAXRDneL9pIQy2fJVlemVxM8eLoT0LyMaxAVMn5I7SDdcDVCOc2V9A3yAXvHc2jGFWVX6QV8sSifNiVbVxz64Lt6r7Z2HG_vOYJNcK7KOZOBnemwPY-m6SZ1ocBzScY0S7bTx0a0eW-0pvvGKmxFIdqXiXqeF4h2C8vD-XsN0Kix4aaTYGKL99nFwt-0kCNd--qZRMo5sZUcQ1Shnrk7RvSvsu1hI0GEg3ol4beexYy_nd7z30NzHiRkXSs_FHuy-MDyEi_NYjkVw-GwuoAOqadU_zOtycpTdFw8supaG6uLHsZpM8u8seHlD_PvywEOuI0V87gi5NADe8oi-ZpO9BMPy72S0qlrJ6cIj_mVicxoCu8PR-XfiYzmIntkmCWqHGqYgPbn4xS2TrVBQAnAQcdh-2GDwoaB6PZQA5J-vhWMpIbpdx5twxNviDgWQvKXquQDFWGQ3BkKvA=w810-h376-no"&gt;&lt;img src="https://lh3.googleusercontent.com/VVqpwiGN2PqD4RjcJ4yRH9hJs42bqvXg0K2U_BHNuzqKsnD0OIKYfaI3L5CmVJOz1Um4VEW1qamSLjB0tMBCoUqLq6_ip4O8oNoBbiL3q2yi7-YTsv6_-UGBiBIOyaU0b1avZnwEpEgLWTC6WekHbGihVVqm8jY2FPzV2rn8gx61tbSA_LG-GGHNT2ss-RHwKSEIaO_xU2asT46AfnEFSbncOYs-eBLpJ-gAfHQfga-Tv2GufKBlTmDb74VUzriYl7BBsLaW48AXPAXRDneL9pIQy2fJVlemVxM8eLoT0LyMaxAVMn5I7SDdcDVCOc2V9A3yAXvHc2jGFWVX6QV8sSifNiVbVxz64Lt6r7Z2HG_vOYJNcK7KOZOBnemwPY-m6SZ1ocBzScY0S7bTx0a0eW-0pvvGKmxFIdqXiXqeF4h2C8vD-XsN0Kix4aaTYGKL99nFwt-0kCNd--qZRMo5sZUcQ1Shnrk7RvSvsu1hI0GEg3ol4beexYy_nd7z30NzHiRkXSs_FHuy-MDyEi_NYjkVw-GwuoAOqadU_zOtycpTdFw8supaG6uLHsZpM8u8seHlD_PvywEOuI0V87gi5NADe8oi-ZpO9BMPy72S0qlrJ6cIj_mVicxoCu8PR-XfiYzmIntkmCWqHGqYgPbn4xS2TrVBQAnAQcdh-2GDwoaB6PZQA5J-vhWMpIbpdx5twxNviDgWQvKXquQDFWGQ3BkKvA=w810-h376-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="ghq"&gt;GHQ&lt;/h3&gt;
&lt;p&gt;各ソースコードをGHQ管理にしているので入れてあります。いつも開くプロジェクトは&lt;code&gt;ctrl+r&lt;/code&gt;でいいけど、たまに開くプロジェクトの場合はGHQ必須です。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=marchrock.vscode-ghq" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;marketplace.visualstudio.com →&lt;/span&gt;&lt;span&gt;https://marketplace.visualstudio.com/items?itemName=marchrock.vscode-ghq&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id="expand-selection"&gt;Expand Selection&lt;/h3&gt;
&lt;p&gt;カーソル位置を基準に選択範囲を広げられる拡張、必須です。選択するのって大体変数とか文字列といった単位なので。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=letrieu.expand-region" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://letrieu.gallerycdn.vsassets.io/extensions/letrieu/expand-region/0.1.4/1576295022325/Microsoft.VisualStudio.Services.Icons.Default" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;expand-region - Visual Studio Marketplace&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Extension for Visual Studio Code - expand selection , It works similar to ExpandRegion for Emacs and “Structural Selection” (Control-W) in the JetBrains IDE&amp;#39;s (i.e. IntelliJ IDEA).&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;span class="truncate"&gt;marketplace.visualstudio.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id="eslint"&gt;ESLint&lt;/h3&gt;
&lt;p&gt;ESLintを入れて保存のたびauto fixさせるようにしました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/ytnuClcmlR6QzcogvGJr4wbYcMoTdjCh8ia7BQheCsONer4YjOTxtQ9d-wva6235CO9YPvefkCsmiVFT5jQxC-8tJjxyFk0dkSWgZIp7NLy_QseqJovQgBhZTygLGTbzPhh3Pi5xC5GPaJ690MLJ2yR9bqzqF5efstvp8-7TBZ6jprkaM_2ir3uok9aQG5VDgAx8OCg4hNjGWLKEXy3UUg2wA_jplrNHw6Gix_msPHkgT9OcQ4aBaOcb5n_jK3R22KtsfYsQg7DIAHUxNbaaEeyJL-dDmIn-cxwHZrF4fuXhcKGZBFNbtY3-OWVpBzD259koGg1w3e8mIVsZV827gjTh_UE8xstPb39dl1zBPDgPNkM7-vGEDnRbiEEzs8hc66pmpnEJqSidGDzKZwxqRHP1jwU-ThRfDVbNKoHn_sTlnGxbphJPv1NV8M2NFJFFzM0MXxq_6vGJfI6Er1mkk9so3bmMe0qqvTLM4JiDU8huOqcZM7750BW20WweDZ6gIOR0KXAUZVwIv6ADlg7cMIAtEIwo0mg6bxD2wmTv5lmggoId_dteCJlPAeiRnhlf4qJvlmzKHdh1qoQKw5Uw7hYo9DMFpru8n-MIg_5RQHRvrOJQwrPjzoQResArtnE3tA91PB8E349-XOOoYrDDsAf86QWetB21wP-i_nvzdaU0XBhCO_bbX9NSM4Y4oypHXMH03lkjfRoJHM6OS6IZSQyIDw=w1004-h662-no"&gt;&lt;img src="https://lh3.googleusercontent.com/ytnuClcmlR6QzcogvGJr4wbYcMoTdjCh8ia7BQheCsONer4YjOTxtQ9d-wva6235CO9YPvefkCsmiVFT5jQxC-8tJjxyFk0dkSWgZIp7NLy_QseqJovQgBhZTygLGTbzPhh3Pi5xC5GPaJ690MLJ2yR9bqzqF5efstvp8-7TBZ6jprkaM_2ir3uok9aQG5VDgAx8OCg4hNjGWLKEXy3UUg2wA_jplrNHw6Gix_msPHkgT9OcQ4aBaOcb5n_jK3R22KtsfYsQg7DIAHUxNbaaEeyJL-dDmIn-cxwHZrF4fuXhcKGZBFNbtY3-OWVpBzD259koGg1w3e8mIVsZV827gjTh_UE8xstPb39dl1zBPDgPNkM7-vGEDnRbiEEzs8hc66pmpnEJqSidGDzKZwxqRHP1jwU-ThRfDVbNKoHn_sTlnGxbphJPv1NV8M2NFJFFzM0MXxq_6vGJfI6Er1mkk9so3bmMe0qqvTLM4JiDU8huOqcZM7750BW20WweDZ6gIOR0KXAUZVwIv6ADlg7cMIAtEIwo0mg6bxD2wmTv5lmggoId_dteCJlPAeiRnhlf4qJvlmzKHdh1qoQKw5Uw7hYo9DMFpru8n-MIg_5RQHRvrOJQwrPjzoQResArtnE3tA91PB8E349-XOOoYrDDsAf86QWetB21wP-i_nvzdaU0XBhCO_bbX9NSM4Y4oypHXMH03lkjfRoJHM6OS6IZSQyIDw=w1004-h662-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="monokai-theme"&gt;Monokai Theme&lt;/h3&gt;
&lt;p&gt;最初から入っているMonokaiテーマはRubyのインスタンス変数&lt;code&gt;@hogehoge&lt;/code&gt;をハイライトしれくれませんでしたので、他のMonokaiを入れました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=GoliafRS.monokai-grs" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://GoliafRS.gallerycdn.vsassets.io/extensions/goliafrs/monokai-grs/1.0.15/1732523714908/Microsoft.VisualStudio.Services.Icons.Default" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Monokai GRS - Visual Studio Marketplace&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Extension for Visual Studio Code - Dark theme based on color schema Monokai&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;span class="truncate"&gt;marketplace.visualstudio.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id="マルチカーソル"&gt;マルチカーソル&lt;/h3&gt;
&lt;p&gt;VS Codeに最初からはいってますね。&lt;code&gt;cmd+d&lt;/code&gt;でいけそうなのでひとまず使ってみます。&lt;/p&gt;
&lt;h3 id="プロジェクトツリー"&gt;プロジェクトツリー&lt;/h3&gt;
&lt;p&gt;サイドバーにちょっとクセがありました。&lt;/p&gt;
&lt;p&gt;Macだと&lt;code&gt;enter&lt;/code&gt;キーでリネームになってしまいますが、リネームはめったにありませんのでそのまま開いてほしい。あとはエディターグループを新しく開くのも好きじゃなかったのでちょっと設定をいじりました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;enter&lt;/code&gt;にあたっていた&lt;code&gt;renameFile&lt;/code&gt;をはずし、&lt;code&gt;ctrl+enter&lt;/code&gt;にもっていくことで、&lt;code&gt;enter&lt;/code&gt;でファイルを開けるようになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ctrl+enter&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;renameFile&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;when&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;explorerViewletVisible &amp;amp;&amp;amp; filesExplorerFocus &amp;amp;&amp;amp; !explorerResourceIsRoot &amp;amp;&amp;amp; !explorerResourceReadonly &amp;amp;&amp;amp; !inputFocus&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; }&lt;span style="color:#960050;background-color:#1e0010"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;enter&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;-renameFile&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;when&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;explorerViewletVisible &amp;amp;&amp;amp; filesExplorerFocus &amp;amp;&amp;amp; !explorerResourceIsRoot &amp;amp;&amp;amp; !explorerResourceReadonly &amp;amp;&amp;amp; !inputFocus&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; }&lt;span style="color:#960050;background-color:#1e0010"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="画面分割"&gt;画面分割&lt;/h3&gt;
&lt;p&gt;Emacsユーザーとしては画面をゴリゴリに分割したいという要望があります。そこを求めてしまうとEmacsからは出られなくなりますのである程度妥協します。&lt;/p&gt;
&lt;p&gt;VS Codeでは&lt;code&gt;cmd+1&lt;/code&gt;、&lt;code&gt;cmd+2&lt;/code&gt;などのキーでグループという列に移動できます。グループにはエディターのタブが含まれる感じ。今画面上にあるグループよりもひとつ上のグループへ移動しようとする（ショートカットキーを押す）と自動的にあたらしいグループが作られます。&lt;/p&gt;
&lt;p&gt;例）グループ2まである場合、&lt;code&gt;cmd+3&lt;/code&gt;でグループ3が開く。&lt;code&gt;cmd+4&lt;/code&gt;は何も起こらない。&lt;/p&gt;
&lt;h3 id="最近開いたファイルへの移動"&gt;最近開いたファイルへの移動&lt;/h3&gt;
&lt;p&gt;最近開いたファイルへ移動する手段がほしい。Emacsでいうところのopen-recentみたいなやつ。これは最近開いたファイルというよりは、同時に編集しているファイルへ戻りたいという意図が強いです。&lt;/p&gt;
&lt;p&gt;僕はWebStorm等のIDEに合わせて&lt;code&gt;cmd+e&lt;/code&gt;に&lt;code&gt;quickOpen&lt;/code&gt;を割り当てています。&lt;/p&gt;
&lt;h3 id="bookmark"&gt;Bookmark&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ブックマークのトグル&lt;/li&gt;
&lt;li&gt;次のブックマークへ移動&lt;/li&gt;
&lt;li&gt;前へ移動&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;の3つにEmacs時代と同じキーバインドを割り当てました。&lt;/p&gt;
&lt;h3 id="キーボードで選択"&gt;キーボードで選択&lt;/h3&gt;
&lt;p&gt;マウスやカーソルキーで範囲選択をするは大変です。Emacsのようにmark setして起点を設定したら、通常のカーソル移動（&lt;code&gt;ctrl+nなど&lt;/code&gt;）で移動しながら選択範囲をいじれるほうが断然よいです。&lt;/p&gt;
&lt;p&gt;なのでこれを入れました。キーバインドは多少調整してあります。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://yng.hatenablog.jp/entry/2016/03/06/114836" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://cdn.image.st-hatena.com/image/scale/4374c73732dbd5cb25ff2ced550c79316ebbb2f5/backend=imagemagick;version=1;width=1300/http%3A%2F%2Fcdn-ak.f.st-hatena.com%2Fimages%2Ffotolife%2Ft%2Ft-yng%2F20160306%2F20160306104340.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Visual Studio Code でEmacsのリージョン選択できるExtensionを作ってみた - にわとりプログラマーの備忘録&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Visual Studio Code でEmacsのリージョン選択を行えるextensionを作ってみました。 https://github.com/t-yng/vscode-emacs-region 作り方については、 こちらのEXTENSIONSのページを参考にしました。 [開発環境] OS : OS X El Capitan プロジェクトの雛形を作成 雛形の生成にはYeomanとgenerator-code(Yoemanにおけるvscodeのextension生成ツール)を利用します。 Yeomanとはアプリケーション開発における、雛形の作成やビルドなどの作業をサポートしてくれる便利ツー…&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://yng.hatenablog.jp/icon/favicon" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;yng.hatenablog.jp&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id="ctrl-deleteで文字削除"&gt;ctrl deleteで文字削除&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ctrl+backspace&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;deleteWordPartLeft&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;when&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;textInputFocus &amp;amp;&amp;amp; !editorReadonly&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; }&lt;span style="color:#960050;background-color:#1e0010"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ctrl-kで削除コピー"&gt;ctrl kで削除&amp;amp;コピー&lt;/h3&gt;
&lt;p&gt;VS Codeに最初からある&lt;code&gt;ctrl+k&lt;/code&gt;は右側を削除するだけで、ペーストすることができません。そりゃこまるってことで↓をいれています。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=cou929.vscode-cut-all-right" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://cdn.vsassets.io/v/M272_20260413.10/_content/Header/vs-logo.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Cut All Right - Visual Studio Marketplace&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Extension for Visual Studio Code - Cut rest of line. Like `Delete All Right` but cut it and store to clipboard.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;span class="truncate"&gt;marketplace.visualstudio.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id="wakatime"&gt;Wakatime&lt;/h3&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=WakaTime.vscode-wakatime" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://WakaTime.gallerycdn.vsassets.io/extensions/wakatime/vscode-wakatime/30.0.8/1776214571045/Microsoft.VisualStudio.Services.Icons.Default" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;WakaTime - Visual Studio Marketplace&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Extension for Visual Studio Code - Metrics, insights, and time tracking automatically generated from your programming activity.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;span class="truncate"&gt;marketplace.visualstudio.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id="ctrlgをエスケープに"&gt;ctrl+gをエスケープに&lt;/h3&gt;
&lt;p&gt;Emacsのように&lt;code&gt;ctrl+g&lt;/code&gt;でなんでもキャンセルしたいです。↓を参考にいろんなキャンセル系を&lt;code&gt;ctrl+g&lt;/code&gt;に割り当てました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://qiita.com/uehaj/items/f2c71325c9f7dc10357c" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFtYXpvbmF3cy5jb20lMkYwJTJGOTk3OSUyRnByb2ZpbGUtaW1hZ2VzJTJGMTUyNjQ0OTc3OD9peGxpYj1yYi00LjAuMCZhcj0xJTNBMSZmaXQ9Y3JvcCZtYXNrPWVsbGlwc2UmYmc9RkZGRkZGJmZtPXBuZzMyJnM9NzY4ZTgyZDY1ODA4Y2RkOTRhMDZkYmVjNGMwNWExMGQ%26blend-x%3D120%26blend-y%3D467%26blend-w%3D82%26blend-h%3D82%26blend-mode%3Dnormal%26s%3Dcb7fce33d4120f72a5e62c4988e08942?ixlib=rb-4.0.0&amp;amp;w=1200&amp;amp;fm=jpg&amp;amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9VmlzdWFsJTIwU3R1ZGlvJTIwQ29kZSVFMyU4MSVBNyVFMyU4MiVBOCVFMyU4MiVCOSVFMyU4MiVCMSVFMyU4MyVCQyVFMyU4MyU5NyVFMyU4MiVBRCVFMyU4MyVCQyVFMyU4MSVBRSVFNCVCQiVBMyVFMyU4MiU4QSVFMyU4MSVBQiU1RSU1QiVFMyU4MiU5MiVFNCVCRCVCRiVFNyU5NCVBOCVFMyU4MSU5OSVFMyU4MiU4QiVFOCVBOCVBRCVFNSVBRSU5QSZ0eHQtYWxpZ249bGVmdCUyQ3RvcCZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTU2JnR4dC1wYWQ9MCZzPWIzYjBjMjQ5MzgxOTkyMTM4ODljZTJmMTI3YjUxNzkx&amp;amp;mark-x=120&amp;amp;mark-y=112&amp;amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDB1ZWhhaiZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTM2JnR4dC1wYWQ9MCZzPTMwNjAzYzQzMTdkMGQyYWZkOTE3ZGNiMDRjOWY2NmUy&amp;amp;blend-x=242&amp;amp;blend-y=480&amp;amp;blend-w=838&amp;amp;blend-h=46&amp;amp;blend-fit=crop&amp;amp;blend-crop=left%2Cbottom&amp;amp;blend-mode=normal&amp;amp;s=2b870a881ac71023a80ce232ff14e63d" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Visual Studio Codeでエスケープキーの代りに^[を使用する設定 - Qiita&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;TouchBarつきのMacBookでは、エスケープキーが使いにくいので、Escapeキーの代りに ^[を割り当てます。Cmd-K Cmd-s からkeybindigs.jsonを開いて以下を追加。 [ { &amp;#34;key&amp;#34;: &amp;#34;ctrl&amp;#43;[&amp;#34;, &amp;#34;comma...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;qiita.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;でもすべてには対応しきれていないので、Mac全体を統制しているhammerspoon側での対応をしたほうがいいんじゃないかと思っています。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/Hammerspoon/hammerspoon" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/7f820665de46d231eee48c046401451405c7e60eb9d997e94c23f8c3b3fe7bc5/Hammerspoon/hammerspoon" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - Hammerspoon/hammerspoon: Staggeringly powerful macOS desktop automation with Lua&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Staggeringly powerful macOS desktop automation with Lua - Hammerspoon/hammerspoon&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id="solargraph"&gt;solargraph&lt;/h3&gt;
&lt;p&gt;Ruby用のLanugage Serverのsolargraphというのも入れてみました。Railsを書くときにあると良さそうだったので。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/castwide/solargraph" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/b6ee83fcc504ae5dbaa3b9137c5430b32bbd041666938936e23692a12e8bcdbd/castwide/solargraph" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - castwide/solargraph: A Ruby language server.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;A Ruby language server. Contribute to castwide/solargraph development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;こちらもちょっと参考にしました。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://seroku.jp/wp/visual-studio-code-%E3%81%A7-ruby-on-rails-%E9%96%8B%E7%99%BA%E3%81%AB%E3%81%8A%E3%81%99%E3%81%99%E3%82%81%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;seroku.jp →&lt;/span&gt;&lt;span&gt;https://seroku.jp/wp/visual-studio-code-%E3%81%A7-ruby-on-rails-%E9%96%8B%E7%99%BA%E3%81%AB%E3%81%8A%E3%81%99%E3%81%99%E3%82%81%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;p&gt;JavaScriptを書くのにはやはりいいですね。WebStormより起動が速いし、ESLintとかはサクッと効いてくれるので。&lt;/p&gt;
&lt;p&gt;一番よく書くRubyのサポートが若干弱い気もしますが、そもそもそんなものEmacsではなかったようなもんなので、まずまず使えています。&lt;/p&gt;</description></item><item><title>社内用アプリのReact Nativeを0.58にアップグレード</title><link>https://blog.piyo.tech/posts/2019-02-06-upgrade-react-native-app-to-0-58/</link><pubDate>Thu, 07 Feb 2019 21:20:38 +0900</pubDate><guid>https://blog.piyo.tech/posts/2019-02-06-upgrade-react-native-app-to-0-58/</guid><description>&lt;p&gt;RNアプリを0.50.3から0.58.3に一気に上げました。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p lang="ja" dir="ltr"&gt;社内アプリのReact Nativeのバージョンを上げてる&lt;/p&gt;&amp;mdash; Hiromasa Ohno（ぴー） (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/status/1093018299103772674?ref_src=twsrc%5Etfw"&gt;February 6, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;案外苦労しませんでしたが、ちょっとだけ困ったのでメモ。&lt;/p&gt;
&lt;h1 id="typeerror-undefined-is-not-a-function-near-addlistener"&gt;TypeError: undefined is not a function (near &amp;lsquo;&amp;hellip;addListener&amp;hellip;&amp;rsquo;)&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;react-navigation&lt;/code&gt;が古すぎました。もともと&lt;code&gt;1.0.0-beta2&lt;/code&gt;を使っていたんですが、最新バージョンはなんと3.x系。Navigation周りはさすがにアプリ全体への影響が大きく簡単には変えられないなと思い、一旦1.x系の最新までアップグレードしました。&lt;/p&gt;
&lt;p&gt;そのときに出たのが、&lt;code&gt;TypeError: undefined is not a function (near '...addListener...')&lt;/code&gt; のエラーです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;react-navigation&lt;/code&gt;のRedux連携の実装が変わっているらしく、&lt;code&gt;react-navigation-redux-helpers&lt;/code&gt;というのを入れる必要がありました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+import {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+ createReduxBoundAddListener,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+ createReactNavigationReduxMiddleware,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+} from &amp;#39;react-navigation-redux-helpers&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; import RootNavigator from &amp;#39;./RootNavigator&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+const middleware = createReactNavigationReduxMiddleware(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+ &amp;#34;root&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+ state =&amp;gt; state.Nav,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+const addListener = createReduxBoundAddListener(&amp;#34;root&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; class Navigator extends Component {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; render() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; return (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &amp;lt;RootNavigator
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; navigation={addNavigationHelpers({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; dispatch: this.props.dispatch,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; state: this.props.Nav,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+ addListener
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; })}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;中で&lt;code&gt;addListener&lt;/code&gt;ってのが必要になってるから渡さないといけないんですねー。詳細は正直よくわかってないし、最新バージョンではまた変わっていそう。&lt;/p&gt;
&lt;p&gt;別アプリ作って試すしかないかなって感じです。&lt;/p&gt;
&lt;h1 id="error-duplicate-resources-appmergereleaseresources-failed"&gt;Error: Duplicate resources :app:mergeReleaseResources FAILED&lt;/h1&gt;
&lt;p&gt;Androidでビルドエラーが出ました。同名のアイコンが存在しててダメだよってエラーのようです。&lt;/p&gt;
&lt;p&gt;過去のバージョンではアプリケーション側のディレクトリに&lt;code&gt;node_modules_reactnative_libraries_customcomponents_navigationexperimental_assets_backicon.png&lt;/code&gt;みたいな名前の画像ファイルが入っていました。新しくなったバージョンではライブラリ側から読み込まれるようなのでアプリ側のアイコンは不要です。&lt;/p&gt;
&lt;p&gt;↓これ系のファイルを全部消せばビルドはOKとなりました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;android/app/src/main/res/drawable-hdpi/node_modules_reactnative_libraries_customcomponents_navigationexperimental_assets_backicon.png&lt;/code&gt;&lt;/p&gt;</description></item><item><title>deviseのskip confirmationの話</title><link>https://blog.piyo.tech/posts/2019-01-31-rails-devise-skip-confirmation/</link><pubDate>Thu, 31 Jan 2019 17:27:59 +0900</pubDate><guid>https://blog.piyo.tech/posts/2019-01-31-rails-devise-skip-confirmation/</guid><description>&lt;p&gt;Railsのdeviseの話です。&lt;/p&gt;
&lt;p&gt;deviseは使わない派、deviseは悪派な人も多いですが、deviseの標準的な範囲で使えそうならとりあえず使っちゃう派です。まあ、その辺の論争は置いといて。&lt;/p&gt;
&lt;p&gt;（ユーザーを一括作成するなど）都合により認証メールを送らないでいるための方法と、認証メールとか関係なく認証済にしてしまう方法、それぞれ別の手段が提供されています。&lt;/p&gt;
&lt;p&gt;コードをみれば一目瞭然ですが、こないだ開発中に「どっちだっけ？」となったので、メモっておこうかと思いました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/heartcombo/devise/blob/main/lib/devise/models/confirmable.rb" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/063e2c23054666d9ee04684ac41f6c0302a69dc379d9acd702fb471a9a8f6a6d/heartcombo/devise" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;devise/lib/devise/models/confirmable.rb at main · heartcombo/devise&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Flexible authentication solution for Rails with Warden. - heartcombo/devise&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="認証メールを送らない方法"&gt;認証メールを送らない方法&lt;/h1&gt;
&lt;p&gt;こうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;user &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;User&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#e6db74"&gt;email&lt;/span&gt;: email)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;skip_confirmation_notification!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;save
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;中身的にはこうなってて、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;skip_confirmation_notification!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; @skip_confirmation_notification &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;フラグの状態でメールを制御します。↓このへん。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/heartcombo/devise/blob/main/lib/devise/models/confirmable.rb#L305-L307"&gt;devise/confirmable.rb at main - heartcombo/devise&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この方法だと認証メールは送られませんが、ユーザーは未認証のままです。あとから認証メールを送りたい場合は&lt;code&gt;user.send_confirmation_instructions&lt;/code&gt;で送れます。&lt;/p&gt;
&lt;h1 id="認証済にしてしまう方法"&gt;認証済にしてしまう方法&lt;/h1&gt;
&lt;p&gt;こうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;user &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;User&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#e6db74"&gt;email&lt;/span&gt;: email)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;skip_confirmation!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;save
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;中身はこうなってます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;skip_confirmation!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;confirmed_at &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Time&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;now&lt;span style="color:#f92672"&gt;.&lt;/span&gt;utc
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;confirmed_at&lt;/code&gt;に値をいれることで、認証済と判断されることになります。&lt;code&gt;confirmed&lt;/code&gt;な場合には認証メールも送られません。&lt;/p&gt;
&lt;p&gt;seedで初期データを作るときとか、管理者がユーザーを手動作成するようなケースではこっちを使うことが多い気がします。&lt;/p&gt;
&lt;h1 id="メールアドレス変更時の再認証をスキップする方法"&gt;メールアドレス変更時の再認証をスキップする方法&lt;/h1&gt;
&lt;p&gt;もう一つ似たメソッドがあって、&lt;code&gt;skip_reconfirmation!&lt;/code&gt;というやつです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;email &lt;span style="color:#f92672"&gt;=&lt;/span&gt; new_email
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;skip_reconfirmation!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;save
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;deviseの&lt;code&gt;reconfirmable&lt;/code&gt;が有効な場合、メールアドレスを変更すると新しいアドレスに対して再度認証メールが送られます。これをスキップして即座にメールアドレスを変更したい場合に使います。&lt;/p&gt;
&lt;p&gt;管理画面からメールアドレスを変更するような場面で地味に必要になるやつです。&lt;/p&gt;
&lt;h1 id="整理"&gt;整理&lt;/h1&gt;
&lt;p&gt;3つの違いを表にするとこんな感じ。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;メソッド&lt;/th&gt;
&lt;th&gt;用途&lt;/th&gt;
&lt;th&gt;認証状態&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;skip_confirmation_notification!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;メールを送らない&lt;/td&gt;
&lt;td&gt;未認証のまま&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;skip_confirmation!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;認証済にする&lt;/td&gt;
&lt;td&gt;認証済になる&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;skip_reconfirmation!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;メアド変更時の再認証をスキップ&lt;/td&gt;
&lt;td&gt;認証済のまま&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>Emacs26のdisplay-line-numbers-modeがlinum-modeよりちょっと速くて快適になりそう</title><link>https://blog.piyo.tech/posts/2019-01-24-emacs-display-line-numbers/</link><pubDate>Thu, 24 Jan 2019 06:24:42 +0900</pubDate><guid>https://blog.piyo.tech/posts/2019-01-24-emacs-display-line-numbers/</guid><description>&lt;p&gt;先日Emacsを26系にアップしました↓↓&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2019-01-22-update-emacs-to-26.1/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/ck_CrgYRzuSb_yWhDIbAzmlreuuXBefoKrhxVgLxTq_lFO5TCQW1PcPw6mkFY2paNg9R_YWKALeyLw1vwz6j6zkC1xnKTE08R5GxS1hTi-9tMSpuPMpmmfJdQaL2O9KSvUDmW1LSdDdpTR6Puy_IkIQjJF-lSvMKVV8mK3YHkRJTqxAY-mz1Sn0ZrRoGLgYEE1n8Nb0i3qnOaldp3XRikjyx7pS64Yi1B2jvF955vxx4pPiiiRAnXD53yoaLroa7JCGjPqcQcqcmhwuwlzt7TDkspKiZbczkl0IeDj7phypB87TqF0WqkfWrZOqxae2DY9N1pPB24a3XCeJrBZptzfFRhTHqcG9rfYRoBuamnPyX5wFz3SbBjkIc6xNnc5MsBpoKt20qfsQMngccz4OB921_5cClaWTEK9_PNL-4T0lYW1CSoQXdlQIOstFDUxlL6DEMbUqLqqry6-QHvNXnYGw-xxQKHv0HZ6xK7eSoF5dUriS6m-laN-gZ1ewG3nIOo6u6I-6Bl0Io8Yxy1qpn_-hQpVKyRGQut-_yllxucaN_OMq-te3FpZwNi3lNhWtBLdyNGyESaVb50LPqkVmttYHS8jLnacKl5N-F_P8wbMLyK9cR8PdDN27_XhEe18qMPv86hovT5CVcfRtBjEBDaehx3kdpbFPkcRJ-6lmfQvsmpoTpLYiiHgeeVQ1ZQ8w5Bg8ewVo6_Yrztp9d-dg=w1200-h600-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Emacsを24.5から26.1にアップデートした - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;長いこと古めのバージョンの24.5を使っていたようなのでEmacsのアップデートを試みました。もはや新機能とか把握していませんが、まあ、なんか良くなっているだろうという期待をこめて。 こちらによると24.5は2015年4月のリリースだったようです。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;どんな変更があるのかなと&lt;a href="https://www.gnu.org/software/emacs/news/NEWS.26.1"&gt;NEWS&lt;/a&gt;を眺めていると、こんな記述が↓↓。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;** Emacs now supports optional display of line numbers in the buffer.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;This is similar to what &amp;#39;linum-mode&amp;#39; provides, but much faster and
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;doesn&amp;#39;t usurp the display margin for the line numbers. Customize the
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;buffer-local variable &amp;#39;display-line-numbers&amp;#39; to activate this optional
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;display. Alternatively, you can use the &amp;#39;display-line-numbers-mode&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;minor mode or the global &amp;#39;global-display-line-numbers-mode&amp;#39;. When
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;using these modes, customize &amp;#39;display-line-numbers-type&amp;#39; with the same
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;value as you would use with &amp;#39;display-line-numbers&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;平たく言うとlinum-modeより速い行番号表示ができるようになったよ、とのこと。&lt;/p&gt;
&lt;p&gt;これまでは&lt;code&gt;linum-mode&lt;/code&gt;ってのを使えば行番号表示ができていたのですが、数千行（いや数百行でも？）ぐらいのファイルを開くと異様に重くなるのでした。そういうときは行番号表示をやめるとまともにスクロールできるので、時折切り替えながら使っていました。&lt;/p&gt;
&lt;p&gt;Emacs 26.1では&lt;code&gt;display-line-numbers-mode&lt;/code&gt;を有効にすることで新しい行番号表示を使うことができます。&lt;/p&gt;
&lt;p&gt;僕は起動時にグローバルに有効にしたい派なので、initに&lt;code&gt;global-display-line-numbers-mode&lt;/code&gt;を書いておくようにしました。&lt;/p&gt;
&lt;p&gt;しばらくこれで様子見。&lt;/p&gt;</description></item><item><title>Emacsを24.5から26.1にアップデートした</title><link>https://blog.piyo.tech/posts/2019-01-22-update-emacs-to-26.1/</link><pubDate>Tue, 22 Jan 2019 22:03:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2019-01-22-update-emacs-to-26.1/</guid><description>&lt;p&gt;長いこと古めのバージョンの24.5を使っていたようなのでEmacsのアップデートを試みました。もはや新機能とか把握していませんが、まあ、なんか良くなっているだろうという期待をこめて。&lt;/p&gt;
&lt;p&gt;こちらによると24.5は2015年4月のリリースだったようです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.gnu.org/software/emacs/history.html" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GNU Emacs Release History&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://www.gnu.org/graphics/gnu-head-mini.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;www.gnu.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;このページからMac版をダウンロードして使いました。バージョンは26.1-2です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://emacsformacosx.com/"&gt;https://emacsformacosx.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;起動時に以下の警告がでました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;Warning (bytecomp): ‘isearch-word’ is an obsolete variable (as of 25.1); use ‘isearch-regexp-function’ instead. [6 times]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;どうやらmigemo関連で警告がでているようなのでmigemoのパッケージをアップデートしました。その際こちらにあるような、Not Foundエラーにハマりました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://qiita.com/room661/items/fa712064c78e200b83eb" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFtYXpvbmF3cy5jb20lMkYwJTJGMzc3MDglMkZwcm9maWxlLWltYWdlcyUyRjE0NzM2ODc1MTY_aXhsaWI9cmItNC4wLjAmYXI9MSUzQTEmZml0PWNyb3AmbWFzaz1lbGxpcHNlJmJnPUZGRkZGRiZmbT1wbmczMiZzPThlNGJhYjMwNTY1NmFhN2ZkZGY5YTNmODU0OTBlZmMw%26blend-x%3D120%26blend-y%3D467%26blend-w%3D82%26blend-h%3D82%26blend-mode%3Dnormal%26s%3Dabf9d84cd473c1019e4dbc95cb774543?ixlib=rb-4.0.0&amp;amp;w=1200&amp;amp;fm=jpg&amp;amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9TUVMUEElRTMlODElQUUlMjBwYWNrYWdlLWluc3RhbGwlMjAlRTMlODElQTclRTclOTklQkElRTclOTQlOUYlRTMlODElOTklRTMlODIlOEIlMjBOb3QlMjBmb3VuZCUyMCVFMyU4MiVBOCVFMyU4MyVBOSVFMyU4MyVCQyVFMyU4MiU5MiVFNSU5QiU5RSVFOSU4MSVCRiVFMyU4MSU5OSVFMyU4MiU4QiZ0eHQtYWxpZ249bGVmdCUyQ3RvcCZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTU2JnR4dC1wYWQ9MCZzPTRjOTcxNjdlYzU4ZWVjYmUzMmJiOGRkNjQyZDQ2MjBk&amp;amp;mark-x=120&amp;amp;mark-y=112&amp;amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDByb29tNjYxJnR4dC1jb2xvcj0lMjMxRTIxMjEmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9MzYmdHh0LXBhZD0wJnM9MDA2MWVlOWU2ODNhYzlmMmE4YmZkYWExYWUxMDI4Nzc&amp;amp;blend-x=242&amp;amp;blend-y=480&amp;amp;blend-w=838&amp;amp;blend-h=46&amp;amp;blend-fit=crop&amp;amp;blend-crop=left%2Cbottom&amp;amp;blend-mode=normal&amp;amp;s=ac5cd777b37c72df0b70df7da9910d51" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;MELPAの package-install で発生する Not found エラーを回避する - Qiita&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Not found エラー MELPAで公開されたパッケージを package install でインストールしている最中に、次のようなエラーが発生してインストールが止まってしまうことがある。 file-error &amp;#34;http://melpa.milkbox.net/pa...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;qiita.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;時間をおいたらできるようになったのでmigemoをアップデート。すると起動時の警告は解消し、今まで通り使えるようになりました。&lt;/p&gt;
&lt;p&gt;また、最近動作がもっさりしているような気がしているMagitもアップデートしてみました。こちらはなんとなく速くなったような気がします。Emacs自体を上げたおかげか、パッケージのおかげかはわかりませんが快適になりました。&lt;/p&gt;
&lt;p&gt;以前Emacs25.1にアップデートしようとした際に失敗したことがあって敬遠してましたが、こんなにうまくいならもっとアップデートしてもよさそう。&lt;/p&gt;</description></item><item><title>React NativeアプリでAndroidでstartsWith関数の実行結果が異なる（っぽい）のにハマった</title><link>https://blog.piyo.tech/posts/2019-01-18-react-native-starts-with-bug/</link><pubDate>Fri, 18 Jan 2019 14:05:41 +0900</pubDate><guid>https://blog.piyo.tech/posts/2019-01-18-react-native-starts-with-bug/</guid><description>&lt;p&gt;React Nativeのアプリで、ある文字列が特定の文字列で始まる場合に何かするみたいな、↓こんなif文を書いていたんですが、Androidの実機で動かないケースに遭遇しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;text&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;startsWith&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;xxxx&amp;#39;&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// do something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;正確にいうと、実機デバッグ中Remote Debuggerにつないでいるときは想定通りの動きをするものの、Remote Debugger無しで動かすとif文の中に入ってくれないというものでした。&lt;/p&gt;
&lt;p&gt;最初これに気がつくまで苦労しました。デバッグしたら必ず動くからなんだこれ？、と。Remote DebuggerにつなぐとJSの実行環境がDebuggerに載っているものに変わるようですね。&lt;/p&gt;
&lt;p&gt;タイトルに（っぽい）とつけたのは、実際に値を確認してはいないからです。デバッグできないとなると結果の確認も少々面倒でして。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;これに気づいて調べてみるとissueがいくつか見つかりました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/facebook/react-native/issues/11370" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/e64514cb9aa4067a8f1ed683d8cdc00c8bd1ea67027797e962c5253d6bce61e1/facebook/react-native/issues/11370" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Different String.startsWith behaviour on Android vs iOS · Issue #11370 · facebook/react-native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Description I&amp;#39;m using the startsWith method on JavaScript strings to compare some values. Specifically the string contains emoji characters, but not at the beginning of the string. On iOS: &amp;#39;Fish an...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/facebook/react-native/issues/19699" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/d9b3f5ad97ff7767b9badff447cf144ff5a697da5ba379c9fe8d67edeebb848c/facebook/react-native/issues/19699" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;string `startsWith` produces false negatives · Issue #19699 · facebook/react-native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Review the documentation: https://facebook.github.io/react-native Search for existing issues: https://github.com/facebook/react-native/issues Use the latest React Native version: https://github.com...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ざっくり読んだ感じ、JavaScriptCoreっていうJSのエンジン的なものが古いから一部挙動がおかしいけど、最新を使うように直そうとしているよ、ということです。&lt;/p&gt;
&lt;p&gt;そして実際に修正コミットが2018年末にされているようなので近い内にリリースされるはずです。&lt;/p&gt;
&lt;p&gt;RN本体のアップグレードはそれなりに大変なので、アップグレードするまではstartsWithは使わないように回避するとよさそうです。&lt;/p&gt;
&lt;p&gt;↓のようにindexOfを使って回避しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;text&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;startsWith&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;xxxx&amp;#39;&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// do something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;↓&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;text&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;indexOf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;xxxx&amp;#39;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// do something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>TestFlightのベータ版アプリに公開リンクからの参加が可能になった</title><link>https://blog.piyo.tech/posts/2018-12-17-testflight-public-link/</link><pubDate>Mon, 17 Dec 2018 14:46:42 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-12-17-testflight-public-link/</guid><description>&lt;p&gt;iOSアプリのベータ版にURLから参加するための方法が公式にサポートされました！&lt;/p&gt;
&lt;p&gt;今までもfastlaneで参加用ページを作ってそこからサブミットしてもらうことで半自動化できていたものの、サイト運用の手間がかかっていました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-05-12-testflight-boarding/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/pmLyMtIHIlVBX8X1FKReXDWNQFn1iIb46OVSy99fhAnJDCJc5mGgJ5jwxcMXIrlt-gTPh6jaB2s475K1ZUjd9vfpdPXJnvwXE024TS_nfpN9f6o6lCBAiF8y2LHmsqkeyx4Dfa3d1DstGswPnGrz-nHx9V5uXJ7zJEw-L6lCu4kgT6ly0Oz9CmpXXzNvPsJjDrbn-d8BWiEje5pgHVymMzRvgrhkBtgvduwOvuNFBhEW6nqXrt2fpWnQ2JprcLPlATdpik4g6LvcN-dxKkAdgHUGw8YufGxe54z3lCxOgpUisczmkcW7d5kt_fsPEQD-71yWpSn-J5_1HiFhXuRPfSaDEcgvl2xQQ5oezrTPYJ7r_8LsgMe_y4S5pnogGL3UVjGdcrv7xFl6BxMoXMiQUBB4WEKv19SDzipWuVy_zHcNhNqXVDtKKM_tD9P5tinEBFvx1RJEKm3BoTmzPntHitaOgUOgu5X9UV1c_Ct2oaOjk73AO59eH76zvXRZOLfopW_D5KwsfBfoEjlGC5enUq99hCaIHq8wI6ylh-A-Y0KDo_9yaP86EH-jHd-vco8ym_oUVFfm8fdIjFYQWQQxc0V-qAtlUgD_5JpPs0pGg2Gw5qMfSi4OeL_kWiBQcAfGgYICAE4X3TE6Ipw0oxT8OlqonzIdupbGBg=w1560-h780-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;fastlane/boardingでTestFlightのベータ版の配布ページが一瞬で作れた - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;社内用に作ったiPhoneアプリをメンバーに配るのにTestFlightのベータ配布を使いますが、いちいちメールアドレスを使うのが面倒です。Google Playにはオープンベータテストにしておくと参加用のURLから勝手に入ってもらうことができるのに、TestFlightはできないのかな、なんて調べていたら自分でホスティングすれば似たようなことを実現できることがわかりました。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;公式の方法だともちろん運用の手間は要らないし、iOSデバイスで直接リンクを踏んで参加できるため利用者側の手間も軽減されます。&lt;/p&gt;
&lt;p&gt;App Store ConnectでTestFlightのページへ移動します。&lt;/p&gt;
&lt;p&gt;テスターグループを選択すると、ページの真ん中あたりに「パブリックリンク」というブロックができています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/a3dtthx6DkJ8AKeGW_exqqF9EoFl1LBZGgkPZAXRqnlmqCXnv1QVvqT5s0b2QuFXa_WX1mxiArCEL-sXMp9tfDRxkVI45R6x8N3IsDe4QiASmKXpBmPDqJ1PCX8YC8iJwkFRasO8Omdcv_7-hIHbX2ScEAJXBXXqBXV8bIp1AbP90JU4oxSXfze658ro2nM1wSlzUnkTk9IIDUdF1M5W7KkIUB6DtciInJ_C_21ZeAOtgQoaBfmszc0YxDHhoT0Xz2kEzcfWRje28_8EpvUAdMBvcz3x-r-Hc4SRjNV5DRdaO4MyqY2YbR-p31xdHjW9Wj65E12vFV3B6k25PMVavF9gwcTl5RIgVxd88YrSBdQYP2r4Uq9WhLxt9OciAEytw8BEScuP1iypBv9zfZzOyTcRN3XGT7YfhMud37QCNGs62RXeEpcqJ-LxnRp4ad3t6E0-uZkstr2ORAAZR2OK2Wq_mkk3YV1IdTH_HdNi16GS--UaU4DiKI1GZKv0ffk0lAce-3BEHkgatFOgk4Jxrvx6bUsPfUUBj-dByoufCUQfpiFit09T_L23Q4ME7ExgzDGugtYZUhfkq_kDIcuPS012TKgx8AdxA0ipaMnwr0HKX25bZ1-xajhtUAopjT4G1Ds-VHdUx6vrraAhRq8fzG7J-Iyl6cclBHUt7kwBa_6KDJpJwyG8Ko3Fhc8pR27pKqzRrH6Wl9tGsWnmmMQ=w2078-h874-no"&gt;&lt;img src="https://lh3.googleusercontent.com/a3dtthx6DkJ8AKeGW_exqqF9EoFl1LBZGgkPZAXRqnlmqCXnv1QVvqT5s0b2QuFXa_WX1mxiArCEL-sXMp9tfDRxkVI45R6x8N3IsDe4QiASmKXpBmPDqJ1PCX8YC8iJwkFRasO8Omdcv_7-hIHbX2ScEAJXBXXqBXV8bIp1AbP90JU4oxSXfze658ro2nM1wSlzUnkTk9IIDUdF1M5W7KkIUB6DtciInJ_C_21ZeAOtgQoaBfmszc0YxDHhoT0Xz2kEzcfWRje28_8EpvUAdMBvcz3x-r-Hc4SRjNV5DRdaO4MyqY2YbR-p31xdHjW9Wj65E12vFV3B6k25PMVavF9gwcTl5RIgVxd88YrSBdQYP2r4Uq9WhLxt9OciAEytw8BEScuP1iypBv9zfZzOyTcRN3XGT7YfhMud37QCNGs62RXeEpcqJ-LxnRp4ad3t6E0-uZkstr2ORAAZR2OK2Wq_mkk3YV1IdTH_HdNi16GS--UaU4DiKI1GZKv0ffk0lAce-3BEHkgatFOgk4Jxrvx6bUsPfUUBj-dByoufCUQfpiFit09T_L23Q4ME7ExgzDGugtYZUhfkq_kDIcuPS012TKgx8AdxA0ipaMnwr0HKX25bZ1-xajhtUAopjT4G1Ds-VHdUx6vrraAhRq8fzG7J-Iyl6cclBHUt7kwBa_6KDJpJwyG8Ko3Fhc8pR27pKqzRrH6Wl9tGsWnmmMQ=w2078-h874-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここで「パブリックリンクを有効にする」というリンクをクリックするとURLが発行されます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Cd2mW2PLi7P0rrTigYx26rygp3JagS5I0K87T5VHHR2Ysledl2KlG1ESgEk_wcuWja4POM2Q5KVEfQeRf5PUxZdn6bA32grRDiw65uEfvZNF5MHhiZTC42B012UjH-h0jOxgcKodsWryQhTVgbsVu-rFNPSE-7U3ciADY7PaE9ixW68J1N82N4cQ6aaBlusgXeQ9Tn1N_brWDBDMEY8RhIRaAVHGTdqvWsxvQ59li8PqYZBL9o8JYkw6iA7ajnJ7qYJNPFFSWmxNKxsO7K30CoGr21Ep37giNBeaxZRWrYDNCLJG3JFfXmrrK-WW92kUhvgTa1w3Ipos-MSohpFJB3kG4o2nRe9tP_cSeDQop0xUHA2P7IcHzy1x5IRxFWqf4VahR5QLP4dsMvi29zSH3cqETwgrzlgiVwOuLgrpQm4inr8VzyC042yV9jCrUe4tJUvX-D51FdxpOH39AtH3sUHIYnLym1DjmDtBnO9A_f2ZlSZndsbIb2AP0PMOrnFgJHPA57PYx_0pK8LB_q2AOBJBMwbyDi2aZlbElsxF_fT9yvBMapj45P_90p1pjUf05dk5tK6O6LbGKowc1HQOnnfslCrH7quY7yyPLHxLdOfF3Ky7YXSu_5ey0VKmSTIqptieMEoDNx2Lh8evgn-B0NpBnFX-89iNn1Rsu4Tr8dgCYsQROpRPvHX7F0nzfqImBPQux08vxjiui76eong=w1208-h318-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Cd2mW2PLi7P0rrTigYx26rygp3JagS5I0K87T5VHHR2Ysledl2KlG1ESgEk_wcuWja4POM2Q5KVEfQeRf5PUxZdn6bA32grRDiw65uEfvZNF5MHhiZTC42B012UjH-h0jOxgcKodsWryQhTVgbsVu-rFNPSE-7U3ciADY7PaE9ixW68J1N82N4cQ6aaBlusgXeQ9Tn1N_brWDBDMEY8RhIRaAVHGTdqvWsxvQ59li8PqYZBL9o8JYkw6iA7ajnJ7qYJNPFFSWmxNKxsO7K30CoGr21Ep37giNBeaxZRWrYDNCLJG3JFfXmrrK-WW92kUhvgTa1w3Ipos-MSohpFJB3kG4o2nRe9tP_cSeDQop0xUHA2P7IcHzy1x5IRxFWqf4VahR5QLP4dsMvi29zSH3cqETwgrzlgiVwOuLgrpQm4inr8VzyC042yV9jCrUe4tJUvX-D51FdxpOH39AtH3sUHIYnLym1DjmDtBnO9A_f2ZlSZndsbIb2AP0PMOrnFgJHPA57PYx_0pK8LB_q2AOBJBMwbyDi2aZlbElsxF_fT9yvBMapj45P_90p1pjUf05dk5tK6O6LbGKowc1HQOnnfslCrH7quY7yyPLHxLdOfF3Ky7YXSu_5ey0VKmSTIqptieMEoDNx2Lh8evgn-B0NpBnFX-89iNn1Rsu4Tr8dgCYsQROpRPvHX7F0nzfqImBPQux08vxjiui76eong=w1208-h318-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;よくある限定公開URL系の仕組みなのでリンクを無効にすることもできるらしい。&lt;/p&gt;
&lt;p&gt;このリンクをiOSデバイスで開くと↓のような画面になります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/_UhH_pGQM9qajlIkQKT57gMGTccwS6xQqAvo3z3kDdHUVG1rCFb4JLA4j4VzeOsjfrGr3g-twadSETmaOIt16aR5GBgi1gRZHrF46UNUfgbYO96x7j3Ny2ifXXG-YOUO9V6OKXBxP1cIaDrXPx4is0xlNXLf5LC0Jdng1GEfvDzscIrnEFDOZVM12lVhPQL2cm5kn6emBNdxOwgx4kdmfWcq4KeRJu8dvzKZJSOl-gbftyEfFaKsg3QsJkZpMYqPR8s1uL4M231jpqLwsH5uXrD__sR1o9OuDoZ2Fmc2Iu86xQFCjCSXgyykN88EOM5n4jN6nHar7GA3hz3ydHp-d6z9JksCZhp81DW5QCkA-QPPxiUPCbJaiR31J__ucGSreYl6f5HAqqi-zcPGVwxJYGipnjnczbbrIE2Owz9aWapxWP0BOpJds2Ou_QM1ySIAL-gwdZgsvWawNv7KPp4cEeGVRb74bZAKYvczAXoP4xy2INuoSwQHFwONFqsPpt1y3s7VuKg3PcSo0WMzqK7woi-CSEj2HErruNVczZiDHEjkip3nbRhJP_Zhkt5H0n3dBo9GNVDn2GjpXvh7OD6DT00xXqMv-1nalL2g_bgsE_Vfp77tx-PiBqG_Iip5r4z__vEg8NlP4g6xzbfV-pQ-99MzdL29Y3YYIE_WPrvvetS7XHi9Ls0mrJCckjulNC9jZcqXkBLYkAAMiaNF3OQ=w1125-h1947-no"&gt;&lt;img src="https://lh3.googleusercontent.com/_UhH_pGQM9qajlIkQKT57gMGTccwS6xQqAvo3z3kDdHUVG1rCFb4JLA4j4VzeOsjfrGr3g-twadSETmaOIt16aR5GBgi1gRZHrF46UNUfgbYO96x7j3Ny2ifXXG-YOUO9V6OKXBxP1cIaDrXPx4is0xlNXLf5LC0Jdng1GEfvDzscIrnEFDOZVM12lVhPQL2cm5kn6emBNdxOwgx4kdmfWcq4KeRJu8dvzKZJSOl-gbftyEfFaKsg3QsJkZpMYqPR8s1uL4M231jpqLwsH5uXrD__sR1o9OuDoZ2Fmc2Iu86xQFCjCSXgyykN88EOM5n4jN6nHar7GA3hz3ydHp-d6z9JksCZhp81DW5QCkA-QPPxiUPCbJaiR31J__ucGSreYl6f5HAqqi-zcPGVwxJYGipnjnczbbrIE2Owz9aWapxWP0BOpJds2Ou_QM1ySIAL-gwdZgsvWawNv7KPp4cEeGVRb74bZAKYvczAXoP4xy2INuoSwQHFwONFqsPpt1y3s7VuKg3PcSo0WMzqK7woi-CSEj2HErruNVczZiDHEjkip3nbRhJP_Zhkt5H0n3dBo9GNVDn2GjpXvh7OD6DT00xXqMv-1nalL2g_bgsE_Vfp77tx-PiBqG_Iip5r4z__vEg8NlP4g6xzbfV-pQ-99MzdL29Y3YYIE_WPrvvetS7XHi9Ls0mrJCckjulNC9jZcqXkBLYkAAMiaNF3OQ=w1125-h1947-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;まずTestFlightを入れ、その上で「テストを開始」からベータ版のインストールが可能です。&lt;/p&gt;
&lt;p&gt;これまではいちいちユーザーのメールアドレスを教えてもらって入力していたことを考えると、かなり楽になりそうです。&lt;/p&gt;</description></item><item><title>メモリ使用量を抑えられるSlackクライアントSblack。複数チームにログインする方法もあります。</title><link>https://blog.piyo.tech/posts/2018-12-11-sblack-slack-client/</link><pubDate>Tue, 11 Dec 2018 06:57:32 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-12-11-sblack-slack-client/</guid><description>&lt;p&gt;Twitterで見つけたSlackクライアントが良さそうだったので使い始めています。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p lang="ja" dir="ltr"&gt;Sblack を使い始めてみてるんだけどすごく良い。 Slack との違いがほとんどわからないけどメモリ使用量は90%近くダウン。&lt;a href="https://t.co/s3ntKNvfAr"&gt;https://t.co/s3ntKNvfAr&lt;/a&gt;&lt;/p&gt;&amp;mdash; Mitsuhiro Setoguchi (@setomits) &lt;a href="https://twitter.com/setomits/status/1070179788885618688?ref_src=twsrc%5Etfw"&gt;December 5, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;Electronを使わない実装のためメモリ使用量も少なく抑えられるようです。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is not an Electron app, so its size is 20 MB instead of 180 MB. It also launches faster than the official client.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;いろんなElectron製のアプリを動かしていてメモリが常に足りないので、嬉しくてすぐに飛びつきました。&lt;/p&gt;
&lt;p&gt;ダウンロードはここから。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://www.sblack.online/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;www.sblack.online →&lt;/span&gt;&lt;span&gt;https://www.sblack.online/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;実際にSlackの公式クライアントと両方起動してメモリ使用量を比較してみました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;まずはSlack&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/J1JknKVF2CrV-h2q75CCVGSzQQiyExaMPGe8VH7EyHjzrw-OOh-WxgK4r66La3a0RsOVfSL5ReH_NzD7Jx6seg7G7lUYbLdrUYo-Jx33mO-jkO3XijNp_HZkLMy-lSU4d7A57sSzAmMwhN8AeqMye7pDpWDNPkfAhHVxyuMp4OhDwqtPq6TktL4KHgaDM1-QQt2UWSO0LaXUcb22YApt7_RPFyLBWLtnKdVbnbiT4QqQZ2KTk2JvqY_Muvd_3nGmsrc0tniE-hbDMlBT8lM62PNS0tLnBvoONN7cVlS7Pcy_FvFR86fcuCvnm9B53_brrNz_yQrc9HhRlCOU4BLCL9Jun9ESjtWIzE_ko68sDFRlXQkqzNdNFev9D1H90vJdWrW8Df7S9aVOpYmRnjDmHxGlgb8xZyF1bb_-a2ChFs1PMufRBVr6OBrAGGqaecCsNCLdHb7P-uD9kKG81qiLffazrWUf8jHKaiZYiYzTCGuIbhXTmU9uo1z5lXkTg7_As-JSDydGs18Z21HY1oSBdGdk_n6n6NuH-av67H6iIJAzB3nEHNX4fz4AGqaGE82VM2opp-ujqO6DZBM2wKRf69oqKSs9DQuPKspmN5ohIbEwGW9cCTKzH-qvKj4SxM6ncE6nyqaVQwqm6MEZLe4Wmqi97n_lndOZ_ox-mixebQjETnC59WPR095Dj351H8796aGPw0pm-4Att_Jkujk=w1102-h206-no"&gt;&lt;img src="https://lh3.googleusercontent.com/J1JknKVF2CrV-h2q75CCVGSzQQiyExaMPGe8VH7EyHjzrw-OOh-WxgK4r66La3a0RsOVfSL5ReH_NzD7Jx6seg7G7lUYbLdrUYo-Jx33mO-jkO3XijNp_HZkLMy-lSU4d7A57sSzAmMwhN8AeqMye7pDpWDNPkfAhHVxyuMp4OhDwqtPq6TktL4KHgaDM1-QQt2UWSO0LaXUcb22YApt7_RPFyLBWLtnKdVbnbiT4QqQZ2KTk2JvqY_Muvd_3nGmsrc0tniE-hbDMlBT8lM62PNS0tLnBvoONN7cVlS7Pcy_FvFR86fcuCvnm9B53_brrNz_yQrc9HhRlCOU4BLCL9Jun9ESjtWIzE_ko68sDFRlXQkqzNdNFev9D1H90vJdWrW8Df7S9aVOpYmRnjDmHxGlgb8xZyF1bb_-a2ChFs1PMufRBVr6OBrAGGqaecCsNCLdHb7P-uD9kKG81qiLffazrWUf8jHKaiZYiYzTCGuIbhXTmU9uo1z5lXkTg7_As-JSDydGs18Z21HY1oSBdGdk_n6n6NuH-av67H6iIJAzB3nEHNX4fz4AGqaGE82VM2opp-ujqO6DZBM2wKRf69oqKSs9DQuPKspmN5ohIbEwGW9cCTKzH-qvKj4SxM6ncE6nyqaVQwqm6MEZLe4Wmqi97n_lndOZ_ox-mixebQjETnC59WPR095Dj351H8796aGPw0pm-4Att_Jkujk=w1102-h206-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Helperプロセスなども合わせると500MB近くのメモリ使用があります。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;続いてSblack&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/3ZjBOGfioQESmsyHU1u4wotvOtbIdaMFssX9u5OFMhBpBRdTOwfqtcH49Cx9FJWvn-BlTw-ojbMfN937ZCs6KPcz9Xod6nuKngFwy6_fqZj-vWWj4yVa6hhrTjTqwOhYxJhh5uOUhoxO2LkYg2fAN4N2GFJuUnAfgb-ord6fiv_ZlkPl1G6RRZxTbQ9__Ep9wwjJT7rMcKCHTNcHCjK7-0cpTHexbJTh9lIRMNHLqHYyOd37FPZAzlkjOS7Qze_LtfKlivGL_nbBe1aBvlWBaaaUj2C3kw0j7TGSqTuRJ6nZZad7ybGb21iOWYktbBRK-Ha88v3coa-_MoN-409MzJQXOHJpDUfQbL_34AIogp_lUdSNaaaaVWjfOssXd0HQOVoMD9Sl54LrjkBKLJ9rIvzHpC2YSsqGvCNMEJGNDFjbLBZH-mkHQOFfdiziu9FmUsLp69fzKnBZrLG4IdKAoC9mCJFMMcRPpEr4KYyVMnZ8yzShcIOA3yM2g2noyzXx9t1j_I1zLtHvrQZabeM61oC2w4ZlLFdcBGOZxq2lXxQJ9b4LJicu-Ro5VWWaMOl-V3b8OXsKb1DIO0jOkh2bysqvCDRyYbmeS3Dny9cyMIdBxk-sVoD7I-7xDpsWaKveezoiXl-l-sVZXJeujMZeo1Rjls7IhiahpMeuy3-aeKE5S3BZaXhn9hOIEaGq2urvCVS9EhxcYkavzCHGlwE=w1102-h162-no"&gt;&lt;img src="https://lh3.googleusercontent.com/3ZjBOGfioQESmsyHU1u4wotvOtbIdaMFssX9u5OFMhBpBRdTOwfqtcH49Cx9FJWvn-BlTw-ojbMfN937ZCs6KPcz9Xod6nuKngFwy6_fqZj-vWWj4yVa6hhrTjTqwOhYxJhh5uOUhoxO2LkYg2fAN4N2GFJuUnAfgb-ord6fiv_ZlkPl1G6RRZxTbQ9__Ep9wwjJT7rMcKCHTNcHCjK7-0cpTHexbJTh9lIRMNHLqHYyOd37FPZAzlkjOS7Qze_LtfKlivGL_nbBe1aBvlWBaaaUj2C3kw0j7TGSqTuRJ6nZZad7ybGb21iOWYktbBRK-Ha88v3coa-_MoN-409MzJQXOHJpDUfQbL_34AIogp_lUdSNaaaaVWjfOssXd0HQOVoMD9Sl54LrjkBKLJ9rIvzHpC2YSsqGvCNMEJGNDFjbLBZH-mkHQOFfdiziu9FmUsLp69fzKnBZrLG4IdKAoC9mCJFMMcRPpEr4KYyVMnZ8yzShcIOA3yM2g2noyzXx9t1j_I1zLtHvrQZabeM61oC2w4ZlLFdcBGOZxq2lXxQJ9b4LJicu-Ro5VWWaMOl-V3b8OXsKb1DIO0jOkh2bysqvCDRyYbmeS3Dny9cyMIdBxk-sVoD7I-7xDpsWaKveezoiXl-l-sVZXJeujMZeo1Rjls7IhiahpMeuy3-aeKE5S3BZaXhn9hOIEaGq2urvCVS9EhxcYkavzCHGlwE=w1102-h162-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Sblackこちらは127MBほど。メモリはSlack公式クライアントアプリの約4分の1しか使っていません。&lt;/p&gt;
&lt;p&gt;すごい！&lt;/p&gt;
&lt;p&gt;肝心の使い勝手ですが、Slack本体のチャット部分はおそらくWebView的に埋め込んであるため、公式クライアントやWebブラウザ版とほぼ変わりません。ちゃんと通知も来るしメモリ食わないし、快適です。&lt;/p&gt;
&lt;h1 id="複数チームへの参加方法"&gt;複数チームへの参加方法&lt;/h1&gt;
&lt;p&gt;ただし、Sblackチームへの参加や切り替えを行うための一番左のバーがありません。そこだけ少々使い勝手が変わります。&lt;/p&gt;
&lt;p&gt;一番左のバーがないのせいで複数のチーム（ワークスペース）への参加方法に戸惑いました。&lt;/p&gt;
&lt;p&gt;そのための方法はメニューバーに隠されていました。隠したわけじゃないとは思うけど、気づきにくかった。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/zEBqiiijKsw0X4eBzKGs0yf6AVbVmoiefNPHFHJcY4o6KNV43Y78nHkDveJs-9kBW2ayXfxntl2-awrhQk4Qhgy3_5BWZ0MdE4JVgajrnL5XJBbo6DjdAjIJ7xBXqjkqR3aAMPcWY_0Cq4yLsaCKzT9YgbzZ1eUOnCmV5r1X-zWoVtvzsSaXeGWcAMCxK5xERuP1XQme0Q_4MOHLeAQApl_kjtFn4hZrVQKZEFD-4l-LSmwon1kVpQIgcYETlUoaKKpH3ic5yGzuYKhp9rfdoTznxpmEyM4_CufV5Eztiwho0WgU10WoWnVv0vi2xNs1rBeuruptx5qndOhk8WeYNzSqeFyoPEOjpLxcfSPYv6sFwTXo3-MNqTfrAuPQDMGKQA1rLKFb5-9HkyS7yhg9WUWTpKnpZ6pQyrox7yNu8OSoWkljZe-9DKhFb6VQTKJndUvamafW0UuI8uq_9gl5Ysbrkr6K2mHTL9eletyX1Y-T5m-O63dfkjiHsBS3bjT8bWYSXtHk1hB0BuICvHFtMqjsZEWKlKxADtWINYcKcdSGYyCOm51CcDF5WApJsr2ZFeIGvlGu0zHm_0-_wsP2vCapyPQeQKHjdcyzW6T4EbTMjaUGlV1J7rve4UKvMk0xheaE1d8wBLMGrFDiDjM-lJVU0yFfMxYFf_2FcTqIX96TT5mB9PqpvLqmrCP3nZ45CqkDAVN5ygLAGvXXuvA=w938-h189-no"&gt;&lt;img src="https://lh3.googleusercontent.com/zEBqiiijKsw0X4eBzKGs0yf6AVbVmoiefNPHFHJcY4o6KNV43Y78nHkDveJs-9kBW2ayXfxntl2-awrhQk4Qhgy3_5BWZ0MdE4JVgajrnL5XJBbo6DjdAjIJ7xBXqjkqR3aAMPcWY_0Cq4yLsaCKzT9YgbzZ1eUOnCmV5r1X-zWoVtvzsSaXeGWcAMCxK5xERuP1XQme0Q_4MOHLeAQApl_kjtFn4hZrVQKZEFD-4l-LSmwon1kVpQIgcYETlUoaKKpH3ic5yGzuYKhp9rfdoTznxpmEyM4_CufV5Eztiwho0WgU10WoWnVv0vi2xNs1rBeuruptx5qndOhk8WeYNzSqeFyoPEOjpLxcfSPYv6sFwTXo3-MNqTfrAuPQDMGKQA1rLKFb5-9HkyS7yhg9WUWTpKnpZ6pQyrox7yNu8OSoWkljZe-9DKhFb6VQTKJndUvamafW0UuI8uq_9gl5Ysbrkr6K2mHTL9eletyX1Y-T5m-O63dfkjiHsBS3bjT8bWYSXtHk1hB0BuICvHFtMqjsZEWKlKxADtWINYcKcdSGYyCOm51CcDF5WApJsr2ZFeIGvlGu0zHm_0-_wsP2vCapyPQeQKHjdcyzW6T4EbTMjaUGlV1J7rve4UKvMk0xheaE1d8wBLMGrFDiDjM-lJVU0yFfMxYFf_2FcTqIX96TT5mB9PqpvLqmrCP3nZ45CqkDAVN5ygLAGvXXuvA=w938-h189-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;「Teams」メニューの中に「Sign in&amp;hellip;」メニューがあります。これを押すとウィンドウがワークスペースのサインイン画面へ遷移してくれます。&lt;/p&gt;
&lt;p&gt;これでプライベート用と仕事用のチームに問題なく参加することができました。&lt;/p&gt;</description></item><item><title>スプレッドシートからMarkdown形式のテーブルにしてくれるサイト</title><link>https://blog.piyo.tech/posts/2018-12-08-markdown-table/</link><pubDate>Sat, 08 Dec 2018 06:06:57 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-12-08-markdown-table/</guid><description>&lt;p&gt;Markdownのテーブル形式を自分で組み立てるのは面倒なんで、これ使ってます。便利ですよ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.tablesgenerator.com/markdown_tables"&gt;https://www.tablesgenerator.com/markdown_tables&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Webサイト上のテーブルとかExcelとかGoogleのスプレッドシートとかで必要な範囲を選択してコピーして、このサイトのFileメニューの「paste table data」に貼り付けます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/9uMwXoYzRutAlDgmiLwV57IluF3Wl42HweiOl5HX7TYB-DMFZIhFCDAbRsdAh0IpW8XU7uqXwo9UqNQ4POjfJCzfjwJpGDunK6XKj0FYz7dL67whIrraqc_EYVJjDzhh87i84LWads1jNu4j-riw4VG2fg5mmNQnvNH3gf6n3xVl_8ptdlU6FaDb9gzPOOOxZwM-3Ebo723VusN_QV9YNxw_yMlo3Hdu7ge9Ebdo0_RPB4Y3gKAPsBsxdYTGZ3Wxzm8bqAtthv8fB6Cyg28vyEimge_LgLFpUr_1MmranXBXQcPbkAGD_s8WV7gVTWnMbYpjCSySpdqrqO8JGLphYb531wt86_XoO_3gTWvwn5R0hLGucQVqtwm0mGdNmcwVyIFq0EJIHStkijpwDBVc-4n9VrzYjx6AnH6Si12p8CElhj5nFF3iy-dSURwLmgLa-3-flKPiLPJR19qa9PqxTsPUD5gjZvmeoONHov_sErl8Xc445f9RcGi4hDuvlv3ljO8sfJFbbrLWFdgxiwBPvc1nEEp_VzZqi9o3su75csAwuamL54aU9oaBQmK7PS_0MdNnFPWLxQlaKh21D7ujUdSSxJhOX4IepfD8vDONIDfsezoQN5rM0lbBzzcuXUoKGpqddEtc2XJ6CVml2-FCqa2VsL1usPxYewKfFq9FNNI4Vm2fhrmgkoxezbqwQIgT-GopNy3MiEBLQbQqO0I=w1040-h664-no"&gt;&lt;img src="https://lh3.googleusercontent.com/9uMwXoYzRutAlDgmiLwV57IluF3Wl42HweiOl5HX7TYB-DMFZIhFCDAbRsdAh0IpW8XU7uqXwo9UqNQ4POjfJCzfjwJpGDunK6XKj0FYz7dL67whIrraqc_EYVJjDzhh87i84LWads1jNu4j-riw4VG2fg5mmNQnvNH3gf6n3xVl_8ptdlU6FaDb9gzPOOOxZwM-3Ebo723VusN_QV9YNxw_yMlo3Hdu7ge9Ebdo0_RPB4Y3gKAPsBsxdYTGZ3Wxzm8bqAtthv8fB6Cyg28vyEimge_LgLFpUr_1MmranXBXQcPbkAGD_s8WV7gVTWnMbYpjCSySpdqrqO8JGLphYb531wt86_XoO_3gTWvwn5R0hLGucQVqtwm0mGdNmcwVyIFq0EJIHStkijpwDBVc-4n9VrzYjx6AnH6Si12p8CElhj5nFF3iy-dSURwLmgLa-3-flKPiLPJR19qa9PqxTsPUD5gjZvmeoONHov_sErl8Xc445f9RcGi4hDuvlv3ljO8sfJFbbrLWFdgxiwBPvc1nEEp_VzZqi9o3su75csAwuamL54aU9oaBQmK7PS_0MdNnFPWLxQlaKh21D7ujUdSSxJhOX4IepfD8vDONIDfsezoQN5rM0lbBzzcuXUoKGpqddEtc2XJ6CVml2-FCqa2VsL1usPxYewKfFq9FNNI4Vm2fhrmgkoxezbqwQIgT-GopNy3MiEBLQbQqO0I=w1040-h664-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;すると、こんな感じになります。これ先日のビジャのときに貼った表ですね。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/BP3_D3X8itB8hBnxJELye4P0hqSTiOFGvmMTXGTHsDeKsBR6Kb_DBDJgcP4oiFzA3eBqUP9KqYr8E3wIHoj1kGG3UQMvbI1vtuxSLuVyPtoILlgb8GRoYgEphI1gAIAFtKhQoGLCeMxOm-s1QrxgKcjcSgMs7xtL38m0ctVCVyWAiQPxis57rtYf0iZeOYVqFbB8GUpatCD40VYqXUH0oXjPJHMxSxTSi-2DOsUmzTHL1B2HR4ojt-rtW3YWLhp5XLhiZ1N_v4j_2ycIRbgza5xWj2eclv-wyZmtWtLa0KPc0wq_VUvKv_jjMLdkf5a666qGFNbugJxPwh18RORPsAHASNaKtXab1-bxRAAplxq_J04WohKHENmBj4Ogyar6hUa6U2oQcEMV2XYu_cSGoEre0ldP3eSjW69FrJGQNcgaMYXXPQrfAsQO6gbizDciaKgWilOjd7YeuVIAHI3Xw6lkXMv7xb4ccCroxToUZsXVmdVxlyop3zCTGO3HyTl64oPecIC7aL2yqo3kzOpeJGtzcBperzM6CC8eyruPRidva7Zqj04XJb9GTH8AlEyB7wI1uuTarSbodKCSjLhvPMQ3uYcwYPDXmIeNgWgDs-K_yMKJ_E6eoDt4ej7ePCFa5MQbSipcUQv1csRTxrAChZAP40cQF9wecQAPPRfxUWgAULcraKbIZGovyU5cMFAKwF0opMLRgln41lntrs0=w1618-h1458-no"&gt;&lt;img src="https://lh3.googleusercontent.com/BP3_D3X8itB8hBnxJELye4P0hqSTiOFGvmMTXGTHsDeKsBR6Kb_DBDJgcP4oiFzA3eBqUP9KqYr8E3wIHoj1kGG3UQMvbI1vtuxSLuVyPtoILlgb8GRoYgEphI1gAIAFtKhQoGLCeMxOm-s1QrxgKcjcSgMs7xtL38m0ctVCVyWAiQPxis57rtYf0iZeOYVqFbB8GUpatCD40VYqXUH0oXjPJHMxSxTSi-2DOsUmzTHL1B2HR4ojt-rtW3YWLhp5XLhiZ1N_v4j_2ycIRbgza5xWj2eclv-wyZmtWtLa0KPc0wq_VUvKv_jjMLdkf5a666qGFNbugJxPwh18RORPsAHASNaKtXab1-bxRAAplxq_J04WohKHENmBj4Ogyar6hUa6U2oQcEMV2XYu_cSGoEre0ldP3eSjW69FrJGQNcgaMYXXPQrfAsQO6gbizDciaKgWilOjd7YeuVIAHI3Xw6lkXMv7xb4ccCroxToUZsXVmdVxlyop3zCTGO3HyTl64oPecIC7aL2yqo3kzOpeJGtzcBperzM6CC8eyruPRidva7Zqj04XJb9GTH8AlEyB7wI1uuTarSbodKCSjLhvPMQ3uYcwYPDXmIeNgWgDs-K_yMKJ_E6eoDt4ej7ePCFa5MQbSipcUQv1csRTxrAChZAP40cQF9wecQAPPRfxUWgAULcraKbIZGovyU5cMFAKwF0opMLRgln41lntrs0=w1618-h1458-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;下の方にMarkdown形式のフォーマットが出てるのでそれをコピーしたらあとは好きに使ってください。ちょっと崩れてるけどどうせMarkdownがきれいにしてくれるし、気にしない。&lt;/p&gt;</description></item><item><title>Bootstrap4のspacing用のクラスみたいなのをReact Nativeでも使いたい</title><link>https://blog.piyo.tech/posts/2018-12-02-utility-styles-for-react-native/</link><pubDate>Sun, 02 Dec 2018 15:39:22 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-12-02-utility-styles-for-react-native/</guid><description>&lt;p&gt;Bootstrap4のmarginとかpadding用のユーティリティクラスが手軽でつい使ってしまいます。&lt;/p&gt;
&lt;p&gt;これね。&lt;code&gt;mt-3&lt;/code&gt;みたいなやつ。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://getbootstrap.com/docs/4.1/utilities/spacing/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://getbootstrap.com/docs/4.1/assets/brand/bootstrap-social.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Spacing&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Bootstrap includes a wide range of shorthand responsive margin and padding utility classes to modify an element’s appearance.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://getbootstrap.com/docs/4.1/assets/img/favicons/favicon-32x32.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;getbootstrap.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Webの場合メリットとデメリットがあるのはわかります。スタイル直書きと対して変わらないし意味を持たないのでもしかしたらデメリットが多いかも。&lt;/p&gt;
&lt;p&gt;んで、似たようなアプローチをReact Nativeで使いたいなーとふと思いました。&lt;/p&gt;
&lt;p&gt;React Nativeでのレイアウトは基本的にはstyleに直書きするか、（コンポーネント間で）共通で用意したスタイル用のオブジェクトを渡すして共通化ぐらいしかできません。&lt;/p&gt;
&lt;p&gt;だとしたら後者の共通オブジェクトなアプローチでmarginとpaddingのユーティリティを実現できるんじゃないかと思った次第です。&lt;/p&gt;
&lt;p&gt;すでに誰がやってそうなもんだけど、ちょっと考えてみます。&lt;/p&gt;
&lt;h1 id="使い方のイメージ"&gt;使い方のイメージ&lt;/h1&gt;
&lt;p&gt;元々こうだったコードを、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;View&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ &lt;span style="color:#a6e22e"&gt;padding&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;marginTop&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;backgroundColor&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;white&amp;#39;&lt;/span&gt; }} &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こうする感じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;p_4&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;padding&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;mt_1&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;marginTop&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;View&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ ...&lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;p_4&lt;/span&gt;, ...&lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;mt_1&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;backgroundColor&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;white&amp;#39;&lt;/span&gt; }} &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;stylesのところをちゃんとコードで生成してあげたら良い感じになるのではないかと思います。&lt;/p&gt;
&lt;h1 id="ユーティリティ用オブジェクトを生成する"&gt;ユーティリティ用オブジェクトを生成する&lt;/h1&gt;
&lt;p&gt;ループを回して作ってしまいます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// お好みで変える感じに
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;forEach&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`m_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;margin&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`mt_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;marginTop&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`mb_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;marginBottom&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`ml_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;marginLeft&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`mr_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;marginRight&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`mx_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;marginHorizontal&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`my_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;marginVertical&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`p_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;padding&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`pt_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;paddingTop&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`pb_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;paddingBottom&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`pl_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;paddingLeft&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`pr_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;paddingRight&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`px_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;paddingHorizontal&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;`py_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;paddingVertical&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;spacer&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こうしてできたのが、これです。ちょっと長いですが、ちゃんとできていそうです。&lt;/p&gt;
&lt;p&gt;使うときは指定に矛盾が出ないように気をつけて使う必要があるとは思いますが、矛盾が出てしまう場合はReact Nativeの仕様に従って決まるはず。paddingとpaddingTopだったらpaddingTopが優先されるとかだった気がします。違ったらすいません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;m_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;margin&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mt_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mb_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 10&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ml_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 13&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mr_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 16&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mx_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 19&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;my_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 22&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;p_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;padding&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 25&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pt_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 28&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 29&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pb_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 31&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 32&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pl_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 34&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 35&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pr_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 36&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 37&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 38&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;px_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 39&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 40&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 41&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;py_1&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 42&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 43&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 44&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;m_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 45&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;margin&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 46&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 47&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mt_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 48&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 49&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 50&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mb_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 51&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 52&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 53&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ml_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 54&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 55&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 56&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mr_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 57&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 58&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 59&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mx_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 60&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 61&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 62&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;my_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 63&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 64&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 65&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;p_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 66&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;padding&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 67&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 68&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pt_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 69&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 70&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 71&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pb_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 72&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 73&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 74&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pl_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 75&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 76&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 77&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pr_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 78&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 79&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 80&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;px_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 81&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 82&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 83&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;py_2&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 84&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 85&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 86&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;m_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 87&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;margin&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 88&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 89&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mt_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 90&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 91&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 92&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mb_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 93&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 94&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 95&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ml_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 96&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 97&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 98&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mr_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 99&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;100&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;101&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mx_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;102&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;103&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;104&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;my_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;105&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;106&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;107&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;p_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;108&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;padding&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;109&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;110&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pt_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;111&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;112&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;113&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pb_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;114&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;115&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;116&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pl_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;117&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;118&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;119&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pr_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;120&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;121&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;122&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;px_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;123&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;124&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;125&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;py_3&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;126&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;127&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;128&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;m_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;129&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;margin&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;130&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;131&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mt_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;132&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;133&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;134&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mb_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;135&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;136&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;137&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ml_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;138&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;139&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;140&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mr_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;141&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;142&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;143&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mx_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;144&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;145&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;146&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;my_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;147&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;148&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;149&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;p_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;150&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;padding&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;151&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;152&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pt_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;153&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;154&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;155&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pb_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;156&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;157&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;158&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pl_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;159&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;160&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;161&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pr_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;162&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;163&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;164&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;px_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;165&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;166&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;167&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;py_4&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;168&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;169&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;170&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;m_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;171&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;margin&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;172&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;173&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mt_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;174&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;175&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;176&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mb_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;177&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;178&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;179&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ml_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;180&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;181&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;182&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mr_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;183&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;184&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;185&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mx_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;186&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;187&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;188&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;my_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;189&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;190&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;191&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;p_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;192&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;padding&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;193&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;194&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pt_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;195&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;196&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;197&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pb_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;198&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;199&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;200&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pl_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;201&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;202&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;203&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pr_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;204&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;205&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;206&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;px_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;207&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;208&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;209&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;py_5&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;210&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;211&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;212&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;m_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;213&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;margin&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;214&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;215&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mt_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;216&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;217&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;218&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mb_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;219&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;220&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;221&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ml_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;222&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;223&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;224&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mr_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;225&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;226&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;227&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mx_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;228&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;229&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;230&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;my_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;231&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;232&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;233&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;p_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;234&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;padding&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;235&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;236&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pt_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;237&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;238&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;239&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pb_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;240&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;241&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;242&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pl_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;243&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;244&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;245&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pr_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;246&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;247&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;248&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;px_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;249&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;250&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;251&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;py_6&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;252&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;253&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;254&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;m_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;255&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;margin&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;256&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;257&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mt_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;258&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;259&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;260&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mb_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;261&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;262&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;263&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ml_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;264&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;265&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;266&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mr_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;267&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;268&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;269&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mx_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;270&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;271&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;272&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;my_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;273&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;274&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;275&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;p_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;276&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;padding&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;277&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;278&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pt_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;279&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;280&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;281&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pb_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;282&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;283&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;284&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pl_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;285&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;286&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;287&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pr_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;288&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;289&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;290&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;px_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;291&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;292&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;293&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;py_7&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;294&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;295&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;296&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;m_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;297&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;margin&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;298&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;299&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mt_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;300&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;301&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;302&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mb_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;303&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;304&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;305&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ml_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;306&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;307&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;308&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mr_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;309&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;310&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;311&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mx_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;312&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;313&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;314&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;my_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;315&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;316&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;317&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;p_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;318&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;padding&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;319&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;320&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pt_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;321&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;322&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;323&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pb_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;324&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;325&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;326&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pl_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;327&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;328&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;329&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pr_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;330&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;331&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;332&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;px_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;333&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;334&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;335&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;py_8&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;336&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;337&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;338&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;m_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;339&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;margin&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;340&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;341&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mt_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;342&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;343&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;344&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mb_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;345&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;346&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;347&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ml_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;348&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;349&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;350&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mr_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;351&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;352&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;353&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mx_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;354&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;355&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;356&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;my_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;357&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;marginVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;358&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;359&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;p_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;360&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;padding&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;361&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;362&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pt_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;363&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingTop&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;364&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;365&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pb_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;366&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingBottom&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;367&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;368&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pl_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;369&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingLeft&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;370&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;371&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pr_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;372&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingRight&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;373&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;374&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;px_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;375&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingHorizontal&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;376&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;377&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;py_9&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;378&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;paddingVertical&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;379&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;380&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Railsで指定したID列順にorderするには</title><link>https://blog.piyo.tech/posts/2018-11-27-order-as-specified/</link><pubDate>Tue, 27 Nov 2018 06:55:17 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-27-order-as-specified/</guid><description>&lt;p&gt;複数のIDの配列でwhereしたあと、そのIDの配列の順番の通りにorderしたいという場合がたまーにあります。2年に1回ぐらいあります。&lt;/p&gt;
&lt;p&gt;実際に必要になったときの機能要件はうまく伝えられないんですが、こんな感じの意味です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;ids &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;items &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Item&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(id: ids)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;order(&lt;span style="color:#e6db74"&gt;&amp;#34;3,1,5の順に並べたい...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;自力で頑張るとしたらSQLでCASE式でインデックスにマッピングさせるようにして、3のときは0、1のときは1、5のときは2のようにして、マッピング結果をORDERする感じになるかと思います。&lt;/p&gt;
&lt;p&gt;それをgem化してくれてるのがこれ。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/panorama-ed/order_as_specified" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/f96327f89ed66fd566ea56d911ec8a5652679e0d5ceb574e34b3627a3a1eaeda/panorama-ed/order_as_specified" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - panorama-ed/order_as_specified: Add arbitrary ordering to ActiveRecord queries.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Add arbitrary ordering to ActiveRecord queries. Contribute to panorama-ed/order_as_specified development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;SQL組み立て部分を抜粋するとこんな感じ。CASE式でSQLを組み立てています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;when_queries &lt;span style="color:#f92672"&gt;=&lt;/span&gt; conditions&lt;span style="color:#f92672"&gt;.&lt;/span&gt;map&lt;span style="color:#f92672"&gt;.&lt;/span&gt;with_index &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;cond, index&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;WHEN &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;cond&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; THEN &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;index&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;case_query &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;CASE &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;when_queries&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(&lt;span style="color:#e6db74"&gt;&amp;#39; &amp;#39;&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; ELSE &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;conditions&lt;span style="color:#f92672"&gt;.&lt;/span&gt;size&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; END&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;scope &lt;span style="color:#f92672"&gt;=&lt;/span&gt; order(&lt;span style="color:#66d9ef"&gt;Arel&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sql(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;case_query&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; ASC&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;というわけで、order_as_specifiedを使えば最初の要件を満たせます。&lt;/p&gt;
&lt;p&gt;最初の例は&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;ids &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;items &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Item&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(id: ids)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;order_as_specified(id: ids)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;と書けます。&lt;/p&gt;
&lt;p&gt;もちろんIDだけじゃなくて、ステータスごとに並び替えるみたいなことにも使えます。&lt;/p&gt;
&lt;p&gt;条件が増えると動的に組み立てられるSQL分のCASEの分岐が増えるので、順番に並べたいIDなどがあまりに多いときには使わないほうがよさそうでした。うろ覚えですが、数百件ぐらいでも遅くなったような。。&lt;/p&gt;
&lt;p&gt;2年後ぐらいにRailsしてたらまた同じようなことを調べると思うので、自分のために残しておこう。&lt;/p&gt;</description></item><item><title>React NativeでのMarkdownライブラリまとめをアップデート</title><link>https://blog.piyo.tech/posts/2018-11-25-react-native-render-html/</link><pubDate>Sun, 25 Nov 2018 06:57:29 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-25-react-native-render-html/</guid><description>&lt;p&gt;以前React NativeのMarkdown用ライブラリを比較しました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-07-12-markdown-on-react-native/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/dg5kuof-kzw7HdFJYfiUsC99GtY0CeoWryN1Wmt38qxYQGQVQLwvYRPXzHNuURrrw0qUa9RHxzPK0IVndJjVsPBG1A05dlqKA70h5VmhUSJ_YJgZKmu9CZb7z1EnI-NWVrGp8kneSBtUg96ZkvWQoon6dFuISSEQYvYgZ7YUGKJLrAKxH5hFRtL8sbVS6qZHUv8OLWNfJJTic2eR8MjxkeoqFCEmMscpaY5Zj9c3A0BhbwfU9gFqXIuB5IT9gEpDQJv2Q_UHTepSr1viIU4Q2LfXsVNdBvPZK8qOK2O8-cLwadKnS2BXY9Np3z52ydh7VMSJfc-yspvlS9jZJIuC9Smtse6z8zPiHMYguqm8-WZP9M6Kdeqv6whpmq64px_IZq4x_ITd7cbLhFGHMiqyWbCGAQ2wBKgGVHNeZmVB1jZJ8D0ZNF6qjAznMCR7zusvEPYIiXwkAJztaxGB3QxJLr_8UAJUotMOS6wY3o6UeWqRvLKavxZG_dzl1sTn4Mq8hKjn2mSdUrRpOXxIhBz0FuZu9tKgNPsJYZ7u7lUpyPgXZix-PMh7b8X-WxRpouMkfwBDEz15wAzXP0RaYPJ_ab0ox3XXJO2ZV0QVg-JGgX5Lk5PqygSAMxr3jwKdzmznsLGDdNRmh_wB7vVMXTkjvEyoIU-pMM4gSg=w785-h412-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;React NativeでMarkdownを表示する方法をいくつか比較してみた - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;GitHubのようにMarkdownが書けるようなサイトが増えています。僕の働いているソニックガーデンが使っているオフィスツールRemottyでもMarkdownのような記法を一部サポートしています。 WebでMarkdownを扱うにはMarkdown形式の文字列をサーバーサイドなりクライアントサイドでHTML化して表示するだけなのでとても簡単です。また、ただのHTMLなのでCSSにより見た目もかなり柔軟に変えることができます。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;そのときに見落としていて試してなかったライブラリがなかなか良さそうでしたので、こちらのサンプルアプリにいれてみました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/pi-chan/ReactNativeMarkdownSample" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/02ed2161748a3df9c4f5f8c431dc55aa193e91030a848a322a94c9432e6f09ae/pi-chan/ReactNativeMarkdownSample" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - pi-chan/ReactNativeMarkdownSample&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Contribute to pi-chan/ReactNativeMarkdownSample development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="react-native-render-html"&gt;react-native-render-html&lt;/h1&gt;
&lt;p&gt;新しく使ってみたのはこのライブラリです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/meliorence/react-native-render-html" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://repository-images.githubusercontent.com/75072058/6be08600-d165-11ea-8765-f4434acb2de0" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - meliorence/react-native-render-html: iOS/Android pure javascript react-native component that renders your HTML into 100% native views&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;iOS/Android pure javascript react-native component that renders your HTML into 100% native views - meliorence/react-native-render-html&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;サンプルアプリではこんな感じになりました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/tXF3aO7yidofuDECIMuiyDLJpN5l7SqU6_Ab0I9Qwg-brRNidH1POV0b760Oez_rqTPXM55XdVpEJfK5yl42o8nQnnnbjkK-MQ0Epg8-ph66gpmKinl24XtSiRaf0cCsjjW3E6CuAOIRGG07Ti5Y3GUF8ARDHy-cdfpw0nw85Ms0BOPw5f2F219EEqOsbB9j09Ty_3Mg97hvXdHUxaU08f7VzrkXHj9RU0AjEAsyatDuK3yJwdiehsfPyKdSn-3nvGYKHO80VXd8rOonDlixTeMjHl5CHGK7p7b9waGGvIxFDlmVazlRoVxHlAwHE4oLE5SPd97T1BDJawlb7e1lIIFkdIiG2Iic3XVdXE5SaKPxBUlSRRhdFYocVrmagSXXKZeA2HL6z-rtwqPrWf6CMpM6RVweIIM9DJSm6UE22BkypjeLMAH2aWMgh259I9PGMc7TuH61FcipuMGT8YE30bT1NDRI7m8MxYKEmqQT8W5ZuPXlTlliMa53a37bgzGQgWmysCwBpBZ9LtM10idy8XSJHlrfbjhS9ca3m7TicEmlYJ9vh8ZrMsuE45b2tMeuIq4U-Oq5qKox5UYBG1elMK4HOkXYDWpwZ5DgM_KtGDCr3xx7GAoHGbc9jl6we0FwSNIIXn3J-DtxquxMqOO0FRfYmIpH6eYo711B9XOfMLx0UrV8-QeL6e8M2c-O9j2plRv7hf0hGHWf2eM1tBM=w706-h1526-no"&gt;&lt;img src="https://lh3.googleusercontent.com/tXF3aO7yidofuDECIMuiyDLJpN5l7SqU6_Ab0I9Qwg-brRNidH1POV0b760Oez_rqTPXM55XdVpEJfK5yl42o8nQnnnbjkK-MQ0Epg8-ph66gpmKinl24XtSiRaf0cCsjjW3E6CuAOIRGG07Ti5Y3GUF8ARDHy-cdfpw0nw85Ms0BOPw5f2F219EEqOsbB9j09Ty_3Mg97hvXdHUxaU08f7VzrkXHj9RU0AjEAsyatDuK3yJwdiehsfPyKdSn-3nvGYKHO80VXd8rOonDlixTeMjHl5CHGK7p7b9waGGvIxFDlmVazlRoVxHlAwHE4oLE5SPd97T1BDJawlb7e1lIIFkdIiG2Iic3XVdXE5SaKPxBUlSRRhdFYocVrmagSXXKZeA2HL6z-rtwqPrWf6CMpM6RVweIIM9DJSm6UE22BkypjeLMAH2aWMgh259I9PGMc7TuH61FcipuMGT8YE30bT1NDRI7m8MxYKEmqQT8W5ZuPXlTlliMa53a37bgzGQgWmysCwBpBZ9LtM10idy8XSJHlrfbjhS9ca3m7TicEmlYJ9vh8ZrMsuE45b2tMeuIq4U-Oq5qKox5UYBG1elMK4HOkXYDWpwZ5DgM_KtGDCr3xx7GAoHGbc9jl6we0FwSNIIXn3J-DtxquxMqOO0FRfYmIpH6eYo711B9XOfMLx0UrV8-QeL6e8M2c-O9j2plRv7hf0hGHWf2eM1tBM=w706-h1526-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;なかなか良さそう。&lt;/p&gt;
&lt;h1 id="react-native-htmlview"&gt;react-native-htmlview&lt;/h1&gt;
&lt;p&gt;ちなみに、よく引き合いに出す&lt;code&gt;react-native-htmlview&lt;/code&gt;はこんな感じ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/2m0R3-CtHHHRSb7vVpCv8TkIlSUyl7mNz-M-r3erYCaVwtP5S2bRzf-rdEuAiKXNYhgCB76qoyxzOeta05sH-Sg62mxAGxDp1-tk0RFaNLKOJo6TtvDg2BY14PEKLmOZsmsDPy1v7FMRfx2ACEEsqsI9IK1EjOn0x6WjYIM2bQDgUd67UA_2nrh3znivtH74T2RMLV6Lt70p9Z0Xr2diWIY_Pem-UPDeXaOlz_GKNgqiUVhDz1Vy92c_KC_k5LdLBzUzUolQ0FBW94wl6Q-4WdyGUovojn83qz2SQOFrj_cCEPSXd-GNqXDTT7Vr3xg7vpBrbLgxizuk9hKBx3WetrzWlk60Z5FFRWC-14iLnoI6RcqL9ZVNFRx8CxnBXas25lnBgQ9uQVVfSFNRPn7HXVRS1LlDXR1vr8JT-3GnLXSnDBd48efbF2NHfv4BPHlXh3wacWc1Gr3m2lrHR2QUdmA8Tw8JD1NtiATDIMfmkD7FVVBONRZr04gykKtZtyQG1iGBI55Lt8MlV4KX9cYWiD3cC6RteOxLmEKiTgx17ZX5OpUAbpKQ2VqPiG-nJ_1rI07OeuejVJlxl9X16SrBVYTmBg6FVuCaQywtLrwZlnYIKmCt0RiTEHN3rO4NRPbM7rqMr9lRuuqX9ttOy71ZjlCicDW200napMSiZZs6H2IOpPAgYR_wVOdWZIjEcGAD6iG3DA4QlcJrDLl5Cco=w706-h1526-no"&gt;&lt;img src="https://lh3.googleusercontent.com/2m0R3-CtHHHRSb7vVpCv8TkIlSUyl7mNz-M-r3erYCaVwtP5S2bRzf-rdEuAiKXNYhgCB76qoyxzOeta05sH-Sg62mxAGxDp1-tk0RFaNLKOJo6TtvDg2BY14PEKLmOZsmsDPy1v7FMRfx2ACEEsqsI9IK1EjOn0x6WjYIM2bQDgUd67UA_2nrh3znivtH74T2RMLV6Lt70p9Z0Xr2diWIY_Pem-UPDeXaOlz_GKNgqiUVhDz1Vy92c_KC_k5LdLBzUzUolQ0FBW94wl6Q-4WdyGUovojn83qz2SQOFrj_cCEPSXd-GNqXDTT7Vr3xg7vpBrbLgxizuk9hKBx3WetrzWlk60Z5FFRWC-14iLnoI6RcqL9ZVNFRx8CxnBXas25lnBgQ9uQVVfSFNRPn7HXVRS1LlDXR1vr8JT-3GnLXSnDBd48efbF2NHfv4BPHlXh3wacWc1Gr3m2lrHR2QUdmA8Tw8JD1NtiATDIMfmkD7FVVBONRZr04gykKtZtyQG1iGBI55Lt8MlV4KX9cYWiD3cC6RteOxLmEKiTgx17ZX5OpUAbpKQ2VqPiG-nJ_1rI07OeuejVJlxl9X16SrBVYTmBg6FVuCaQywtLrwZlnYIKmCt0RiTEHN3rO4NRPbM7rqMr9lRuuqX9ttOy71ZjlCicDW200napMSiZZs6H2IOpPAgYR_wVOdWZIjEcGAD6iG3DA4QlcJrDLl5Cco=w706-h1526-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今回の差分です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/ReactNativeMarkdownSample/commit/56ed99c4dd45f81d82aa6b0d0682867d3701d83d"&gt;https://github.com/pi-chan/ReactNativeMarkdownSample/commit/56ed99c4dd45f81d82aa6b0d0682867d3701d83d&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;使い方部分だけ抜粋すると↓こんな感じでした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt;, { &lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;Dimensions&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ScrollView&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Linking&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react-native&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;HTML&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react-native-render-html&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;width&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Dimensions&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;window&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RenderHtmlScreen&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;navigationOptions&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react-native-render-html&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;navigation&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getParam&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;html&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;ScrollView&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{&lt;span style="color:#a6e22e"&gt;padding&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;}}&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;HTML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;imagesMaxWidth&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;width&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.9&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;onLinkPress&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{(&lt;span style="color:#a6e22e"&gt;evt&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;) =&amp;gt; { &lt;span style="color:#a6e22e"&gt;Linking&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;openURL&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/ScrollView&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>React NativeアプリのデバッグでParallelsのChromeが開いてしまう</title><link>https://blog.piyo.tech/posts/2018-11-23-react-native-debugger-tab-on-chrome/</link><pubDate>Fri, 23 Nov 2018 06:27:28 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-23-react-native-debugger-tab-on-chrome/</guid><description>&lt;p&gt;React Nativeアプリの開発中のRemote DebugにはReact Native Debuggerというのを使います。しかし、うっかりそいつを起動せずにデバッグを始めるとChromeでデバッグ用のタブが開いてしまい少し面倒なことになります。&lt;/p&gt;
&lt;p&gt;それが最近はParallels DesktopのWindowsに入れてあるChromeが起動するようになってしまいました。これが起こってしまうとParallelsの起動を待ってから止めるために時間がかかってしまうし、その間もCPUやメモリ消費がとんでもないことになって合計5分ほどロスしてしまいます。&lt;/p&gt;
&lt;p&gt;調べてみると普通にissueがあるし、回避方法も載っていたのでその対策を実施しました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/facebook/react-native/issues/11480" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/aa0f110520db1d4c47418242fe1c734b2df9976db69b193851e606c91e5a8a42/facebook/react-native/issues/11480" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Debug JS remotely opens Chrome in Parallels Desktop before Chrome.app on macOS · Issue #11480 · facebook/react-native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Description Enabling Debug JS Remotely on a macOS computer that has Parallels Desktop installed with Chrome on Windows as well as the macOS version of Chrome opens the Parallels Desktop Windows vir...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ParallelsのゲストOSの設定のオプション設定の中に、アプリケーションというメニューがあります。その中に「WindowsアプリケーションをMacと共有する」というチェックボックスがあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/KirKHb0AfBwEVij56NL-U8zNXK0w2Q9R-wuUPHaLDXf4QL4Lrip5HMQk0rWxfjI1wx9qkEbJf2Tobp7rduL-hlNPqBedYpwK-6q3OajIA2k4wHc38Eay76CfRF9srwBe7E_1LLqcUByJgzDYp1wx-bM_gMtQEtvl5miNlx57BiaihefZ8gykUWJFIUKSaPD7btU0VJjcWkmUE25OFm5MNVC5ClSx5YkI-YsCzTcLv1suiUEWCDpUR8Wv-A71svQmDx_KtZ7Z_0cKtjAyRWPMGz_rpi_S_IYcSRh8scoGbPw_K0FRRjUcyDLVH6D3BrozqWObuFO0oePXk-Seg7NZS3W-_3h0DBTId2AzxMmUgGrsGymkRiogFnpfBy2kqoBZYyHzTFHeI2sNlW0jBT7sDM6exEWRjY7g4l_4xTl7hl34ulwqsUbrX6EIPO2Cz91S4OFOn4yTp4UJCZngmpS4DTOe5e0Okvp1Dp3vloHD0kIRlU4OLO5tkb8WpnYYA8ediVMuBH4UJA0wtq6M0srWeYgs9sr1w4_1VfWSzOwwfXuRxYg-GNkICD64sBXVVXU8c02AKPyhZl7d704zsO5uUOR-VHzAN9POkNbAVNYTpQ6-AmpRIRs3KNW_CbpmuXGabl2sU9dsLwFI_SwD_zkdyvqFhGwy5uFyjUlBNvnM0FUcYVeVoqXjpRY_oVBCcRyZlmIzA70uuCifO1GwOuU=w1624-h1464-no"&gt;&lt;img src="https://lh3.googleusercontent.com/KirKHb0AfBwEVij56NL-U8zNXK0w2Q9R-wuUPHaLDXf4QL4Lrip5HMQk0rWxfjI1wx9qkEbJf2Tobp7rduL-hlNPqBedYpwK-6q3OajIA2k4wHc38Eay76CfRF9srwBe7E_1LLqcUByJgzDYp1wx-bM_gMtQEtvl5miNlx57BiaihefZ8gykUWJFIUKSaPD7btU0VJjcWkmUE25OFm5MNVC5ClSx5YkI-YsCzTcLv1suiUEWCDpUR8Wv-A71svQmDx_KtZ7Z_0cKtjAyRWPMGz_rpi_S_IYcSRh8scoGbPw_K0FRRjUcyDLVH6D3BrozqWObuFO0oePXk-Seg7NZS3W-_3h0DBTId2AzxMmUgGrsGymkRiogFnpfBy2kqoBZYyHzTFHeI2sNlW0jBT7sDM6exEWRjY7g4l_4xTl7hl34ulwqsUbrX6EIPO2Cz91S4OFOn4yTp4UJCZngmpS4DTOe5e0Okvp1Dp3vloHD0kIRlU4OLO5tkb8WpnYYA8ediVMuBH4UJA0wtq6M0srWeYgs9sr1w4_1VfWSzOwwfXuRxYg-GNkICD64sBXVVXU8c02AKPyhZl7d704zsO5uUOR-VHzAN9POkNbAVNYTpQ6-AmpRIRs3KNW_CbpmuXGabl2sU9dsLwFI_SwD_zkdyvqFhGwy5uFyjUlBNvnM0FUcYVeVoqXjpRY_oVBCcRyZlmIzA70uuCifO1GwOuU=w1624-h1464-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これを起動しておくとMac側からWindowsへのファイル連携が楽らしいですが、特に使っていませんのでオフにします。&lt;/p&gt;
&lt;p&gt;こうするとParallelsのChromeは立ち上がらず、Mac側のChromeでタブが開くようになります。&lt;/p&gt;</description></item><item><title>Pryの出力で&lt;page break&gt;とかいうのが出て困った</title><link>https://blog.piyo.tech/posts/2018-11-21-pry-page-break/</link><pubDate>Wed, 21 Nov 2018 11:59:20 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-21-pry-page-break/</guid><description>&lt;p&gt;RubyではPry愛用者なのですが、バージョンアップのタイミングか何かで画面に収まらない出力が出たときのPagerがおかしくなって（Pagerが変わった？）、使いづらくなってしまいました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;page break&amp;gt; --- Press enter to continue ( q&amp;lt;enter&amp;gt; to break ) --- &amp;lt;page break&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;該当箇所がバージョン&lt;code&gt;0.12.1&lt;/code&gt;に含まれるこちらのコミットで変更されているようでした。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/pry/pry/commit/bd07d11c1bf40c9381cd6ab6e26c421c17fa2226" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/22265b7bc6ff5a2e9a0a4d270edfc94c60a45aa0afdb7780d7bf0a67298576b7/pry/pry/commit/bd07d11c1bf40c9381cd6ab6e26c421c17fa2226" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;pager.rb: fix Helpers constant invocation · pry/pry@bd07d11&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Since the top class is Pry::Pager and not Pry, the cref constant static lookup only look for constants under Pry::Pager (or at the top level). Since Helpers refers to Pry::Helpers, it won&amp;amp;#39;t be...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;手元のバージョンが&lt;code&gt;0.12.0&lt;/code&gt;だったため、&lt;code&gt;bundle update pry&lt;/code&gt;してバージョンを&lt;code&gt;0.12.2&lt;/code&gt;に変えたら直りました。&lt;/p&gt;
&lt;p&gt;ちょうどバグを引いたみたいです。&lt;/p&gt;
&lt;p&gt;よかったー。&lt;/p&gt;</description></item><item><title>ブログ画像にGoogle Photosを使ってるけど…</title><link>https://blog.piyo.tech/posts/2018-11-19-blog-images-google-photos/</link><pubDate>Mon, 19 Nov 2018 06:03:34 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-19-blog-images-google-photos/</guid><description>&lt;p&gt;このブログに置いてる画像は全部Google Photosに置いてます。&lt;/p&gt;
&lt;p&gt;画像を記事中に挿入する手順は、&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;スクショなどで画像を用意する&lt;/li&gt;
&lt;li&gt;Google Photosの公開アルバムにアップロードする&lt;/li&gt;
&lt;li&gt;画像へのリンクを取得&lt;/li&gt;
&lt;li&gt;Dashのスニペットを使ってMarkdown記法で記事中に挿入&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;です。それなりに面倒です。&lt;/p&gt;
&lt;p&gt;それに、たまに画像が見えなくなっちゃってることがあるらしいし、もっといい方法ないかなと思っております。&lt;/p&gt;
&lt;p&gt;Hugoはスタティックサイトを生成するだけなので&lt;code&gt;public/images&lt;/code&gt;とかに置いて参照すれば使えますが、でもそれで面倒そうだなーと思ってます。
ダブらないように名前をつけるのが面倒だし、じゃあ被らないようにとランダムにしてしまうと画像を紛失しそうです。&lt;/p&gt;
&lt;p&gt;何かツールを作るといいのかも。そのツールに画像をドラッグアンドドロップすると適切なパスに画像を置いてくれて、かつ画像へのリンクをコピーした状態にしてくれてるみたいな。&lt;/p&gt;
&lt;p&gt;あ、これいいな。書きながら思いつきました。&lt;/p&gt;</description></item><item><title>Hydraを使ってSwiftでPromiseする</title><link>https://blog.piyo.tech/posts/2018-11-18-swift-promise-hydra/</link><pubDate>Sun, 18 Nov 2018 06:49:45 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-18-swift-promise-hydra/</guid><description>&lt;p&gt;これまでは問題なかったんですが、機能の追加でAPIリクエストを全部待ってから次の処理をしたくなりました。なのでPromise系のライブラリを導入して、きちんと待機することにしました。&lt;/p&gt;
&lt;p&gt;Promise系のライブラリはいくつかあるようです。&lt;/p&gt;
&lt;p&gt;代表格はスター数、10,000越えの&lt;code&gt;PromiseKit&lt;/code&gt;か。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/mxcl/PromiseKit" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/5219541a2d9791373c85ab20460b37e2dfa2884b6cc77e40da77aa93cea1c434/mxcl/PromiseKit" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - mxcl/PromiseKit: Promises for Swift &amp;amp; ObjC.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Promises for Swift &amp;amp; ObjC. Contribute to mxcl/PromiseKit development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;でもREADMEを読んでしっくり来たのはこっちだったので、&lt;code&gt;Hydra&lt;/code&gt;というのを使いました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/malcommac/Hydra" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/0855be493d977390d999055ee0e8fd28156218c98b9c1ee2a713fa9688aa3eb4/malcommac/Hydra" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - malcommac/Hydra: ⚡️ Lightweight full-featured Promises, Async &amp;amp; Await Library in Swift&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;⚡️ Lightweight full-featured Promises, Async &amp;amp; Await Library in Swift - malcommac/Hydra&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="まず既存コード"&gt;まず既存コード&lt;/h1&gt;
&lt;p&gt;かなりメタ化しちゃってますが、既存コードはこんな感じでした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reload&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; API.getData1() { data1 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; data = data1 {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; Data.setData1(data)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; API.getData2() { data2 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; data = data2 {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; Data.setData2(data)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;元々はこれで問題ありませんでした。ですが、全てのAPIが返ってきたあと次のページへ遷移するケースが発生しました。&lt;/p&gt;
&lt;p&gt;きちんと全API呼び出しを待たないと、データが半端な状態でページ遷移をしてしまうことになります。Promiseの出番です。&lt;/p&gt;
&lt;h1 id="hydraを導入する"&gt;Hydraを導入する&lt;/h1&gt;
&lt;p&gt;cocoapodsで導入しました。プロジェクトがSwift3系だったので、&lt;code&gt;pod 'HydraAsync', '~&amp;gt; 1.0.2'&lt;/code&gt;して導入します。&lt;/p&gt;
&lt;h2 id="api呼び出しを書き換える"&gt;API呼び出しを書き換える&lt;/h2&gt;
&lt;p&gt;元々のコードを次のように分離します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Hydra&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reload&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; promise1 = getData1()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; promise2 = getData2()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getData1&lt;/span&gt;() -&amp;gt; Promise&amp;lt;Void&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; Promise&amp;lt;Void&amp;gt;(&lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;: .background, token: &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;) { (resolve, reject, &lt;span style="color:#66d9ef"&gt;_&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; API.getData1() { data1 &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; data = data1 {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; Data.setData1(data)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; resolve()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; reject(&lt;span style="color:#e6db74"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getData2&lt;/span&gt;() -&amp;gt; Promise&amp;lt;Void&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 略...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Promise&amp;lt;Void&amp;gt;&lt;/code&gt;の最初の引数はiOSのDispatchQueue関連に対応するenumです。多くは&lt;code&gt;.background&lt;/code&gt;になるんじゃないかな。&lt;/p&gt;
&lt;p&gt;2番目はInvalidationTokenでキャンセルするときに使うっぽい。今回は要らないから使ってなくて、よくわかってない。今回は&lt;code&gt;nil&lt;/code&gt;にしてます。&lt;/p&gt;
&lt;p&gt;最後のBlockがPromiseの実装を書くところ。&lt;/p&gt;
&lt;p&gt;READMEの&lt;a href="https://github.com/malcommac/Hydra#create-a-promise"&gt;Create a Promise&lt;/a&gt;を参考に、元々のAPI呼び出しを移植して&lt;code&gt;resolve&lt;/code&gt;と&lt;code&gt;reject&lt;/code&gt;を入れました。&lt;/p&gt;
&lt;p&gt;今回はこの箇所でのみPromiseを使いたかっただけなので、API呼び出し自体をPromiseを返す実装に変更してしまうのはやめました。他の箇所への影響を考えてのことです。&lt;/p&gt;
&lt;p&gt;逆にいうとAPI呼び出ししてPromiseを返す関数を1個挟むだけで使えるようになるので、小さく試すには便利。&lt;/p&gt;
&lt;h2 id="完了を待つ"&gt;完了を待つ&lt;/h2&gt;
&lt;p&gt;これはドキュメントの&lt;code&gt;all&lt;/code&gt;の項目のとおり。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/malcommac/Hydra#all"&gt;Hydra#all&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;さっきの例だと、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reload&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; promises = [getData1(), getData2()]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; all(promises).then { &lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.doSomething()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; }.&lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt; { err &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こうなります。すっきり書けました。&lt;/p&gt;</description></item><item><title>iOSでデバッグ実行できないときにプリントデバッグする方法</title><link>https://blog.piyo.tech/posts/2018-11-17-ios-debug-log-server/</link><pubDate>Sat, 17 Nov 2018 06:44:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-17-ios-debug-log-server/</guid><description>&lt;p&gt;iOSアプリの開発において、デバッガーをアタッチできないときのデバッグは骨が折れます。その最たる例がPush通知から起動するときだと個人的には思います。&lt;/p&gt;
&lt;p&gt;アプリが起動していない状況から起動するときに挙動を検証する際には、そもそもアプリが起動しておらずプロセスが存在しないためデバッガーをアタッチすることもできません。&lt;/p&gt;
&lt;p&gt;そこでせめてもの抵抗でprintデバッグをしようと組み込みのprint関数でログを出してみるのですが、実機ログをみると色々なログがごちゃまぜになっていて必要なログだけに絞り込むのがなかなか難しいです。&lt;/p&gt;
&lt;p&gt;この際作っちゃろかと一瞬思ったんですが、ちょっと調べたらすぐに見つかったんでそれを使いました。&lt;/p&gt;
&lt;p&gt;ログを記録するクライアントライブラリと、それを受け取るサーバーをセットで使います。&lt;/p&gt;
&lt;p&gt;自分のローカル環境だけ、しかも一時的に使えれば良いという前提で今日の話をします。&lt;/p&gt;
&lt;h1 id="ログを受け取って標準出力に出すサーバー"&gt;ログを受け取って標準出力に出すサーバー&lt;/h1&gt;
&lt;p&gt;rubyで書かれた、&lt;code&gt;rack-http-logger&lt;/code&gt;なるものを使えます。後述するiOS側のクライアントアプリと同じ人が書いてて、すぐ使えます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/mattt/rack-http-logger" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/4e360b6c5c0cc2efadb605fd4c6bc925a17993e26626f10a13312801ac3bebcc/mattt/rack-http-logger" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - mattt/rack-http-logger: Log metrics from HTTP request parameters according to l2met conventions&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Log metrics from HTTP request parameters according to l2met conventions - mattt/rack-http-logger&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% git clone https://github.com/mattt/rack-http-logger
% cd rack-http-logger/example
% bundle install
% thin start
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これでlocalhost:3000にサーバーが立ち上がります。&lt;/p&gt;
&lt;h1 id="ログを記録するためのクライアントライブラリ"&gt;ログを記録するためのクライアントライブラリ&lt;/h1&gt;
&lt;p&gt;Antennaというライブラリを使います。cocoapodsで導入可能。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/mattt/Antenna" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/7825ab91ab0b05751d0b3f756219c63f06f5a8db6c40dcad0756de3c0ae9cf4b/mattt/Antenna" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - mattt/Antenna: Extensible Remote Logging for iOS&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Extensible Remote Logging for iOS. Contribute to mattt/Antenna development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;すごく古いですがちゃんと使えます。&lt;/p&gt;
&lt;p&gt;Podfileに&lt;code&gt;pod &amp;quot;Antenna&amp;quot;&lt;/code&gt;と書いて&lt;code&gt;pod install&lt;/code&gt;します。&lt;/p&gt;
&lt;p&gt;で、&lt;code&gt;AppDelegate.swift&lt;/code&gt;に初期化処理を書いておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;application&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -&amp;gt; Bool {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// さきほどのサーバーを指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; Antenna.sharedLogger()?.addChannel(with: URL(string: &lt;span style="color:#e6db74"&gt;&amp;#34;http://localhost:3000&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;!&lt;/span&gt;, method: &lt;span style="color:#e6db74"&gt;&amp;#34;LOG&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;初期化後は必要な箇所でメッセージを渡して呼び出せばOK。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;Antenna.sharedLogger()?.log(&lt;span style="color:#e6db74"&gt;&amp;#34;記録したいメッセージ&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;さっき&lt;code&gt;thin start&lt;/code&gt;したコンソールに次のようなログが出ているかと思います。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;source=rack-http-logger locale=ja_US message=記録したいメッセージ uuid=xxxxxxxxxxx
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;実際こんな感じで流れてきます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/5pjtWkqmNAXJkdhcYIFr1MnqFCq3wtWEoVxjI4GZs29oSOEbRsncgNCv9tSwLNz82LoCsGCY6RJpLS0Zqo-DEuVWn35B7ovWpAo6-pkxrkGPvxY2PbbkIE67CY4FoPR8POxyAEA-YA_8jy2gGX3F9pGxX7P55AISECWLVC2bYlo3RwRGnBtLInm7zZ1a7IbY_kZ2vtjMjmzA38LPllLPttvcfyz3rl02KSUDOxLLonK7RvVPDvpWtVnoxvWAkeKwMgCA6cglFUaxf10O-bUqIFvUuBOG0YHs5LNCFjOacDif3mcw57Fjlykij1xdLUOOSz9sBDIuP0H8FZOYAFBMgYsP8vj09zUbq5TYCY0A8ZPeDmSX_bkGjg8n28M3FyvFWRB9N4M9MZa9la7grjSeQ0jFVocpnsjNm70BtdHzE1QbozVQeZ_Xq-BvUH3yJootFlbSpg0cZUirrmJHqxSE6G0Z11_xgEsYTcXevRqoGyx988NZa5d7zwtkYhGj-4W3NPDlTZCkUbxHG4II6mb0W1S7IM4utES8HHieEUw-OzoEmoNRMG4e1u1L2P3Ok-jBkLydcZBS0VHZjSC_xkoIZj8cWftGh9EpbR5j-1ZQneyABVCHhqy6mXeZGSu2NDqxwfuFLhEBxPYaMnz1_Jpmx9XKI4u6iI9undbuiOmqsarEfTRTbq1KWJQsGRJoPGlQEBn_56l7Q8dwH-qVlRE=w1180-h162-no"&gt;&lt;img src="https://lh3.googleusercontent.com/5pjtWkqmNAXJkdhcYIFr1MnqFCq3wtWEoVxjI4GZs29oSOEbRsncgNCv9tSwLNz82LoCsGCY6RJpLS0Zqo-DEuVWn35B7ovWpAo6-pkxrkGPvxY2PbbkIE67CY4FoPR8POxyAEA-YA_8jy2gGX3F9pGxX7P55AISECWLVC2bYlo3RwRGnBtLInm7zZ1a7IbY_kZ2vtjMjmzA38LPllLPttvcfyz3rl02KSUDOxLLonK7RvVPDvpWtVnoxvWAkeKwMgCA6cglFUaxf10O-bUqIFvUuBOG0YHs5LNCFjOacDif3mcw57Fjlykij1xdLUOOSz9sBDIuP0H8FZOYAFBMgYsP8vj09zUbq5TYCY0A8ZPeDmSX_bkGjg8n28M3FyvFWRB9N4M9MZa9la7grjSeQ0jFVocpnsjNm70BtdHzE1QbozVQeZ_Xq-BvUH3yJootFlbSpg0cZUirrmJHqxSE6G0Z11_xgEsYTcXevRqoGyx988NZa5d7zwtkYhGj-4W3NPDlTZCkUbxHG4II6mb0W1S7IM4utES8HHieEUw-OzoEmoNRMG4e1u1L2P3Ok-jBkLydcZBS0VHZjSC_xkoIZj8cWftGh9EpbR5j-1ZQneyABVCHhqy6mXeZGSu2NDqxwfuFLhEBxPYaMnz1_Jpmx9XKI4u6iI9undbuiOmqsarEfTRTbq1KWJQsGRJoPGlQEBn_56l7Q8dwH-qVlRE=w1180-h162-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これらを使えばデバッガーをつなぐことができなくても、変数をある程度確認したり、想定通りのコードを通るかどうかを確認したりできるわけです。&lt;/p&gt;
&lt;p&gt;だいぶ古いツール郡なので新しいのがありそうだと思うのと、これだけシンプルな使い方しかしないならもっと簡単に作れてもいいんじゃないかと思ったりしています。&lt;/p&gt;</description></item><item><title>プレビュー.appでPDFに文字を書き込んだら文字が枠からはみ出て困った</title><link>https://blog.piyo.tech/posts/2018-11-16-edit-pdf-previewapp/</link><pubDate>Fri, 16 Nov 2018 06:19:50 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-16-edit-pdf-previewapp/</guid><description>&lt;p&gt;会社が用意してくれた年末調整用のPDFをダウンロードしてMacプレビュー.appで文字を入れようとしたら、狭い入力エリアだと文字がはみ出てしまいPDFとして成り立ってない感じになっちゃいました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/RU75TBNOD-x-poOIEC18LvRRVWP86J2-5W6TGmfEvXuDdDIfbzLtcblqsSJV8gsHUr0zhYSbiSssjCL0z0K_SVv-yEQBLcUI6eiM3lHveL_Q9oYz1Trmunx6bP6up6ceDdgXEyvWGWL_QxXnGRajuN2Tw5h7gzD84xbNVmIdLnBUNltIKPtT54poQA7NQSk4gYeJ0K_MrTXIsUxm4rbYofuAT9sk4ElCw6EvO_12E5FE1RsBcOcg0oAdq_gopWj2eSk55moY7kQjqs3fECDJdDYwCiJ6wHl7qpGmg-MOYZ5pZ_kFmy-OneowvZyUdBVXUdkYiLOMbjNtPhw8tsGg_-GY90yqTaAVbD0p_90Erox6uIsuz3PC-vylvdZYme6XGtlv0UDAtvom2zOHgRjMYMNJNgxjkYHHta5MDj4uxGgWSxlZb_idqE_susUzkz2psH3n9HFnnXpfkfFRm6Tkj_nTGBLswaRgDRbLJcv-G06YE89BaQVpsciwUtIlvf7Mx3Mpf23NP_P7eXPv8iMINRlidx9H8Cag6MAaqaHO4nkYNQEtURuj_kevsU4FziYd1xb5qn9jmQI5_6M5LnDaDZc242OQyhFDE4gtNFLcRtdWuOQnGAnRYpvTsOsyFAeNSHKKcB1X9ufFI1MEE1DCAnCMTJgEgtb7bJNyIsjb1oMKQOMvF1gyMLkQ9x6kgFUMnuTcFCr7psH9hb9-J6g=w1074-h342-no"&gt;&lt;img src="https://lh3.googleusercontent.com/RU75TBNOD-x-poOIEC18LvRRVWP86J2-5W6TGmfEvXuDdDIfbzLtcblqsSJV8gsHUr0zhYSbiSssjCL0z0K_SVv-yEQBLcUI6eiM3lHveL_Q9oYz1Trmunx6bP6up6ceDdgXEyvWGWL_QxXnGRajuN2Tw5h7gzD84xbNVmIdLnBUNltIKPtT54poQA7NQSk4gYeJ0K_MrTXIsUxm4rbYofuAT9sk4ElCw6EvO_12E5FE1RsBcOcg0oAdq_gopWj2eSk55moY7kQjqs3fECDJdDYwCiJ6wHl7qpGmg-MOYZ5pZ_kFmy-OneowvZyUdBVXUdkYiLOMbjNtPhw8tsGg_-GY90yqTaAVbD0p_90Erox6uIsuz3PC-vylvdZYme6XGtlv0UDAtvom2zOHgRjMYMNJNgxjkYHHta5MDj4uxGgWSxlZb_idqE_susUzkz2psH3n9HFnnXpfkfFRm6Tkj_nTGBLswaRgDRbLJcv-G06YE89BaQVpsciwUtIlvf7Mx3Mpf23NP_P7eXPv8iMINRlidx9H8Cag6MAaqaHO4nkYNQEtURuj_kevsU4FziYd1xb5qn9jmQI5_6M5LnDaDZc242OQyhFDE4gtNFLcRtdWuOQnGAnRYpvTsOsyFAeNSHKKcB1X9ufFI1MEE1DCAnCMTJgEgtb7bJNyIsjb1oMKQOMvF1gyMLkQ9x6kgFUMnuTcFCr7psH9hb9-J6g=w1074-h342-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Adobe Acrobat Reader DCだとうまくいくよ、という情報を同僚から得たのでやってみると、、&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/w3nD0ET__6-AOjXx0ILInyVAAXNJEhOLNNqA1rVYUYaVwyCXrTEYeGmegJsxNX9NwU4n7oEEnbTTKNtt5EnFgdpCRn3KIKJGo9YQC0FCUCs1vvtqFKSyUEZ0u9FPplKHy8aHoAMAdG_hif5HEH4sV1ThAQkSiBeMfi7st6qf1fPWiSsfqDuU0o2YUY6z6RoPvcTEitPuQcc5NH-4_4DN8pIap5zE7doMDY4mlN2bLGILFOU4DghWntD3pjgMdaJmGAO5If9TeKDwc6XoymhC2rT_T6Mx_EPGlJwFzegr72WPbyzryt4CWOvnApWXTFLrkGzVc5ayIXGHb5bY1K_YlLGoVXtnd0xpPULqeZRAIDilGd3OnAmASdW6aWKkf4M33mWX5vl6iTe5EexMnU2_j43FpX8jA7IygjSiWilerdEeZ8a_kYTu7jk0gSuh3gJ-a_jryUpyDpCGxso4k7K2gduQnW9U0FQRy9DwvwSRVB2BU7KMcygo0N8kgoKvUqOeAbBAMh00j2xFgICWAGtXlkwAZlnn5HXi0onBrCzO_w_-ALOJ1__EyWInRe7mbw-nKwoexf1L9sIunb-cnfNGH67S4deSTf_6o8xQZl2ux5aEzCIj7GzoFjoYdErwTrpSTBofmxKQFo4YBAs4VyruXHa3Bhk7IX8Y6KGfQKTvI_4VXzoA5q8JMXfZbzK1COoeiDk6dg0DnNrfFUoTVTs=w1116-h348-no"&gt;&lt;img src="https://lh3.googleusercontent.com/w3nD0ET__6-AOjXx0ILInyVAAXNJEhOLNNqA1rVYUYaVwyCXrTEYeGmegJsxNX9NwU4n7oEEnbTTKNtt5EnFgdpCRn3KIKJGo9YQC0FCUCs1vvtqFKSyUEZ0u9FPplKHy8aHoAMAdG_hif5HEH4sV1ThAQkSiBeMfi7st6qf1fPWiSsfqDuU0o2YUY6z6RoPvcTEitPuQcc5NH-4_4DN8pIap5zE7doMDY4mlN2bLGILFOU4DghWntD3pjgMdaJmGAO5If9TeKDwc6XoymhC2rT_T6Mx_EPGlJwFzegr72WPbyzryt4CWOvnApWXTFLrkGzVc5ayIXGHb5bY1K_YlLGoVXtnd0xpPULqeZRAIDilGd3OnAmASdW6aWKkf4M33mWX5vl6iTe5EexMnU2_j43FpX8jA7IygjSiWilerdEeZ8a_kYTu7jk0gSuh3gJ-a_jryUpyDpCGxso4k7K2gduQnW9U0FQRy9DwvwSRVB2BU7KMcygo0N8kgoKvUqOeAbBAMh00j2xFgICWAGtXlkwAZlnn5HXi0onBrCzO_w_-ALOJ1__EyWInRe7mbw-nKwoexf1L9sIunb-cnfNGH67S4deSTf_6o8xQZl2ux5aEzCIj7GzoFjoYdErwTrpSTBofmxKQFo4YBAs4VyruXHa3Bhk7IX8Y6KGfQKTvI_4VXzoA5q8JMXfZbzK1COoeiDk6dg0DnNrfFUoTVTs=w1116-h348-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;確かに大丈夫！しかも入力可能な欄に色がついていて見やすい！&lt;/p&gt;
&lt;p&gt;もともとPDFがAcrobatとかで作られたんですかね。&lt;/p&gt;
&lt;p&gt;Adobe Acrobat Reader DCはここ↓から入れられました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://acrobat.adobe.com/jp/ja/acrobat/pdf-reader.html"&gt;https://acrobat.adobe.com/jp/ja/acrobat/pdf-reader.html&lt;/a&gt;&lt;/p&gt;</description></item><item><title>SwiftでJSのsetTimeoutみたいなことをする</title><link>https://blog.piyo.tech/posts/2018-11-15-swift-delay/</link><pubDate>Thu, 15 Nov 2018 06:07:08 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-15-swift-delay/</guid><description>&lt;p&gt;iOSで仕方なく少し待ってから処理を実行するてのを時々やりたくなるんですが、毎度書き方を忘れるので、自分用にメソッドを定義して使っています。&lt;/p&gt;
&lt;p&gt;どこかグローバルなところに定義しとくとアプリ全体で使えるので、&lt;code&gt;AppDelegate.swift&lt;/code&gt;の一番下あたりに定義を書いておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;delay&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; delay: Double, closure: @escaping ()-&amp;gt;()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; DispatchQueue.main.asyncAfter(deadline: .now() &lt;span style="color:#f92672"&gt;+&lt;/span&gt; delay) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; closure()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;で使うときはこんな感じ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;delay(&lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// do something&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.performSegue(...) &lt;span style="color:#960050;background-color:#1e0010"&gt;みたいな&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最悪SDKのAPIが変わったとしても&lt;code&gt;delay&lt;/code&gt;内部だけ書き換えればいいので楽。&lt;/p&gt;</description></item><item><title>Apnoticを利用中のRailsプロジェクトでHTTP2::Error::ProtocolError</title><link>https://blog.piyo.tech/posts/2018-11-14-apnotic-protocol-error/</link><pubDate>Wed, 14 Nov 2018 06:55:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-14-apnotic-protocol-error/</guid><description>&lt;p&gt;久しぶりにメンテすることになったプロジェクトでiOSのPush通知を送ろうしたら&lt;code&gt;HTTP2::Error::ProtocolError&lt;/code&gt;っていうざっくりしたエラーがでてしまい困りました。&lt;/p&gt;
&lt;p&gt;サーバーはRails、Push通知はApnoticというgemを使って送信しています。&lt;/p&gt;
&lt;p&gt;Apnoticのissueを調べてみるとずいぶん前に報告されているissueがあり、それに該当しそうでした。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/ostinelli/apnotic/issues/42" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/61ff5ab3d381a01944fdad9d4e7e7573d42ec175e4af69aeb6f80a6e7bb990dc/ostinelli/apnotic/issues/42" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Rails app crashing when using integer value for header · Issue #42 · ostinelli/apnotic&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Hi! I had notifiaction.apns_collapse_id = order.id and app was crashing with HTTP2::Error::ProtocolError (HTTP2::Error::ProtocolError) and no backtrace. Sometimes exception was rescued with message...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;依存ライブラリのバージョンアップで直るとのことだったのでApnotic自体のバージョンをあげてしまい、不具合を回避できました。&lt;/p&gt;
&lt;p&gt;今回のアップデートで1.3.0 → 1.4.1となりました。&lt;/p&gt;
&lt;p&gt;1.3.0、↑のissueより新しいから直っていてもよさそうなもんですが、なんだったんでしょうねー。という感じ。&lt;/p&gt;</description></item><item><title>Dash.appのスニペットでクリップボードの文字列に特定文字列があると正しく貼り付けられない</title><link>https://blog.piyo.tech/posts/2018-11-13-dash-placeholder-delimiter/</link><pubDate>Tue, 13 Nov 2018 06:21:21 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-13-dash-placeholder-delimiter/</guid><description>&lt;p&gt;Dash.appのスニペットをよく使うという話をこないだ書きました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-11-07-dash-snippet/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/sDBKW6QKWTS0jqSIBhAGneiDu8L2-c6ZJjAVQ0CZ19uLFhwdcPctGQuD_8WYWY6pVFGcHGUTVlxciXM2PSSGLgSivsXSF--7FGKg0I9pLXbNhOO_7Li9p1fYrvl9-RxrkoJPO3cUz2_AbJwijazPId2OHtmW-m4I92uYMiRQ65zu-kiXR1N8i_1fkQj3BWIq45jZL-WE-5MTcninKaycXVMMLvm8sUaVzsE2uxK9AWIFwFdOWnIn1_-KjoV26_c3MhqnMTG-xQynhYCieZBemGgVzWJrObnTeIjJhOpCL5Fgb56zwoEGIcuzOc7PqD7p9QvgjdjzRw3YSY9ygzhWhp16FedRCb0eKmMe94P4xJhfrSMYTIGfNk3RDmvO9CRM5rKPHKaStcNsLhE7FlK1QwoTdLIyq8qKukiM-u7Bc7sz2DwSZQxxDwXKUGzfsTjWd3sN-7aGYPAZ6IuWPVcpSFm2-8TVp2Di9tahHtknRIKW_BwZltqmP_5Xplc19awb2sJoBuo7xyDD6CLZLtPUvvCwvLDuwHLxT5bMl51XRoS3VwS3SdrhC65B3BrrIDGpvkvN0vhgO0PEnncQhmoG6Sen0-muuB56Y4sgsbIxtf6Jh8SfxwStaY3d4Xyh1GeCE23Gw07G3m4ewsEOgAqM6Qeb1eena1k_UYXmQ7RQb-U1k2rYk0WzFF7ZUgEZ6ddDIbvBckY5PYYve6foFW8=w1200-h600-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Dash.appへのスニペット登録例を紹介 - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;ドキュメントツールのDashですが、スニペット機能もありますよね。Dashが出た当初はむしろスニペット機能のために使っていました。 普段からスニペットを便利に使ってるので活用例を紹介してみようかと。 スニペット展開キーワードのPrefix スニペットの省略表記としては普段の入力に差し支えないPrefixがあったほうが良いです。僕は ; 始まりのキーワードを登録しています。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;この中で紹介している、クリップボード文字列を含めて展開するスニペットの一部がGooglePhotoの画像のURLよっては動かない場合がありストレスに思っていたので調べてみました。&lt;/p&gt;
&lt;h1 id="こんな現象がおきました"&gt;こんな現象がおきました&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;;asin&lt;/code&gt;というスニペットの例で紹介します。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;;asin&lt;/code&gt;はamazonへのリンクをはるためのスニペットで、このようにHugoのショートコードに展開されます。XXXXXのところはコピー済の文字列です。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;{ {&amp;lt; amazon asin=&amp;#34;XXXXXXXX&amp;#34; &amp;gt;}}
(↑本来はスペース要らないですが、ショートコードに解釈されちゃうので空けてます。以下同じです。)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;（本来ASINとして正しい値ではないですが、）&lt;code&gt;abcde&lt;/code&gt;という文字列をコピーした状態で&lt;code&gt;;asin&lt;/code&gt;とタイプします。&lt;/p&gt;
&lt;p&gt;すると、次のように展開されます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;{ {&amp;lt; amazon asin=&amp;#34;abcde&amp;#34; &amp;gt;}}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これが想定通りの動き。&lt;/p&gt;
&lt;p&gt;次に、&lt;code&gt;abcde__fgh__ijk&lt;/code&gt;という文字列をコピーして&lt;code&gt;;asin&lt;/code&gt;とタイプすると、次のようになります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Znn8eb0xm_JnBFKDq_qEFPSplT50XajCyIcMQbYxFUrfJi9CzF3eeDY5K9IHxgRHrZ27r9UFKuURObmPO2WJM-n2zt9zD8715aBNcjHR_SEG-KCDh3Tk7cGTM4n6c-KIbxxyyUwvD9efsan8dCwKbwkbwfc1PCzPQn6Fk72WR3dmOwZOxGZP3AydvjZ9nS1SHVfyHTcpxJ7WU16xgGSiRYonc7iBnPaF-R3ClV3YDqIeNcrNpTqR96ME4h6w4J9asi3WB2mY6fbH7smJLK6c5kloo2fUo08tFLynEGyRyHboZLMe3gYgDyncYrgep2sS27oIcpEGTEVUi0xmxi1frxI_10GYLV4ZPir_7-EWSNVVzOZ_SG6trlKQOg2wfonHGTfMXcCNSkFmU8WeZ3leuaHGTEJeswubGBXB8kk5WJm4Eqiwt7O4vKiMyOo2BKkExHqaSI9EevXBcf3bwSfGlUqFeVfJ5wHu6RAMkt4a6xnAIMr2b1jxwASfmilSjzJIH9Tug2wZSpgur9LbSJqm7fZ7U0SrpLvVqLVS-qISUJ2XvtmiWQftGr5ZyeCMN0JpkvpM_VVklryI4An7zfZYAKNbBcTYK-UiKlUWVZWxQ9Z8Wnuzr4oc60gglzVNsTintiwDA78nm44zsv4m5tsGmpfSgzICc7XiHFTA79qeQEpSQeZWRMK0PuapEIKhlNgAzhZmAmiWV6w0ZxazZKRqZqE44sF-q3sMp54_SOY=w593-h229-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Znn8eb0xm_JnBFKDq_qEFPSplT50XajCyIcMQbYxFUrfJi9CzF3eeDY5K9IHxgRHrZ27r9UFKuURObmPO2WJM-n2zt9zD8715aBNcjHR_SEG-KCDh3Tk7cGTM4n6c-KIbxxyyUwvD9efsan8dCwKbwkbwfc1PCzPQn6Fk72WR3dmOwZOxGZP3AydvjZ9nS1SHVfyHTcpxJ7WU16xgGSiRYonc7iBnPaF-R3ClV3YDqIeNcrNpTqR96ME4h6w4J9asi3WB2mY6fbH7smJLK6c5kloo2fUo08tFLynEGyRyHboZLMe3gYgDyncYrgep2sS27oIcpEGTEVUi0xmxi1frxI_10GYLV4ZPir_7-EWSNVVzOZ_SG6trlKQOg2wfonHGTfMXcCNSkFmU8WeZ3leuaHGTEJeswubGBXB8kk5WJm4Eqiwt7O4vKiMyOo2BKkExHqaSI9EevXBcf3bwSfGlUqFeVfJ5wHu6RAMkt4a6xnAIMr2b1jxwASfmilSjzJIH9Tug2wZSpgur9LbSJqm7fZ7U0SrpLvVqLVS-qISUJ2XvtmiWQftGr5ZyeCMN0JpkvpM_VVklryI4An7zfZYAKNbBcTYK-UiKlUWVZWxQ9Z8Wnuzr4oc60gglzVNsTintiwDA78nm44zsv4m5tsGmpfSgzICc7XiHFTA79qeQEpSQeZWRMK0PuapEIKhlNgAzhZmAmiWV6w0ZxazZKRqZqE44sF-q3sMp54_SOY=w593-h229-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;こんな感じのウィンドウが出てきて、そのまま決定すると次のようになってしまいます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;{ {&amp;lt; amazon asin=&amp;#34;abcdefghijk&amp;#34; &amp;gt;}}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;アンダーススコアの部分がなくなってしまいました。&lt;/p&gt;
&lt;p&gt;このとき出るウィンドウはDash.appのプレースホルダーを使ったスニペットをトリガーしたときに現れるウィンドウと同じです。&lt;/p&gt;
&lt;h1 id="dashappのプレースホルダー"&gt;Dash.appのプレースホルダー&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;名前: __name__
メールアドレス: __email__
もう一回名前: __name__
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;みたいなスニペットがあったときに、アンダースコア2つで囲んだ部分を変数としておいて、スニペット展開じに入力できる仕組みです。このとき同じ変数には同じ値を入れることができます。&lt;/p&gt;
&lt;p&gt;実際に↑のスニペットを展開して名前部分を変更すると二箇所同時にプレビューされていくのがわかります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/iRMdnZAImC8_bziXoOsEnuswoPc334D3ZHUbenvXLaiAjjvoUp5P0CrhVR5rfBoXmbS8wnco9HOvEJpudBsZBQv8IQ7gAaHajQALRlysOcOPra762LPBTinZhgVDdRtIFKliWos_puZC6MV4Cg2hDHx6lJ8DQ9-CbcxZM9uTiCA9l5Y9ho3dXn1QVzcPQYj8hhunxmeM577GKRfiYm7GyYAdAFno_14t-iIKZuLkUhiTFQvJuPDOvvHk4VDuHtdpc1aOu8MCkVySuZHNUPbNcLzot8MP7u4xb9YeI-PM6-o5QX_1C8tkOgSZwx2vn8uvU_9E7kM9jjbndlek7rensP71l1ggx3uSZjcSeV9WE0h2qTL99SWXzUKt3rTchEinoQ5035aIdjHklN7pLfAQcrSh36l0L_h51Dpp27p7EgaqaHfeX5owq-6QJ901wuenBWbsSPJd9oAP8zBvIBHBffLj0Tbbpvagy52N9X2zlaiD6z-yJf9zfPCmeVpYpVRfNfKSjZefUgjbwn8xJtehVVkiUqTfsxV74T1qfOImthXtOnOLMKoXxGKzEwYHcDWt0iIvLAKbgm05bRBuB-MOIl56f4VIzNu33RieYWQsW7jG8F2fKdp0oyaX7HBp-1nV4yVKh8yqt2VDAwfcXWG3f7XrLLnB1PZa4LH1b7_6f9n37kC3NqwWsxjj0WVPKbu5uMOvUUoxo2KeR6q_OmpfzNgKdDAvjKHZArnmxOI=w598-h238-no"&gt;&lt;img src="https://lh3.googleusercontent.com/iRMdnZAImC8_bziXoOsEnuswoPc334D3ZHUbenvXLaiAjjvoUp5P0CrhVR5rfBoXmbS8wnco9HOvEJpudBsZBQv8IQ7gAaHajQALRlysOcOPra762LPBTinZhgVDdRtIFKliWos_puZC6MV4Cg2hDHx6lJ8DQ9-CbcxZM9uTiCA9l5Y9ho3dXn1QVzcPQYj8hhunxmeM577GKRfiYm7GyYAdAFno_14t-iIKZuLkUhiTFQvJuPDOvvHk4VDuHtdpc1aOu8MCkVySuZHNUPbNcLzot8MP7u4xb9YeI-PM6-o5QX_1C8tkOgSZwx2vn8uvU_9E7kM9jjbndlek7rensP71l1ggx3uSZjcSeV9WE0h2qTL99SWXzUKt3rTchEinoQ5035aIdjHklN7pLfAQcrSh36l0L_h51Dpp27p7EgaqaHfeX5owq-6QJ901wuenBWbsSPJd9oAP8zBvIBHBffLj0Tbbpvagy52N9X2zlaiD6z-yJf9zfPCmeVpYpVRfNfKSjZefUgjbwn8xJtehVVkiUqTfsxV74T1qfOImthXtOnOLMKoXxGKzEwYHcDWt0iIvLAKbgm05bRBuB-MOIl56f4VIzNu33RieYWQsW7jG8F2fKdp0oyaX7HBp-1nV4yVKh8yqt2VDAwfcXWG3f7XrLLnB1PZa4LH1b7_6f9n37kC3NqwWsxjj0WVPKbu5uMOvUUoxo2KeR6q_OmpfzNgKdDAvjKHZArnmxOI=w598-h238-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;さきほどの&lt;code&gt;abcde__fgh__ijk&lt;/code&gt;という文字列の場合、アンダースコア2つ囲みの文字列がプレースホルダー変数として解釈されてまったのが原因だったようです。&lt;/p&gt;
&lt;h1 id="回避策"&gt;回避策&lt;/h1&gt;
&lt;p&gt;今回はアンダースコア2つで囲まれた部分が問題となりました。&lt;/p&gt;
&lt;p&gt;幸いDashには設定箇所があるので、自分の用途では発生しにくい文字列をプレースホルダーとして判別するための条件としておけば回避可能です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Ruht53PszUrFI5H2YUGWXMFMERj9zYOoIRYPKwwMTEHoFSPZTkytV8d7P6D6v5Hs3SOhLyPvQybIm8qhOQt4vu40QZU89p6Bhy-DC4cvHJI-HKlyUmOVfk8_IBibdzREbfA1FNLtQVd-o9w7qk3iZ1af7B0ftK2N1z9qJxRSKhKsFVJDEcLUTWKsqZwffprfJ3BMLYJCFmk6xPbuD74Yo_vQHEa19zBAFsQoEQTu1kshOtrCc7vYM75J4jSN-GSeS7Xy9FhKoJmH-jO51aU28sG9vnnzh4Sz-hL2-CoixgP0Hy4oBPfGptrNwmDWNT-wahUft3GjsBZzvghoLE74dmtdUUDe5i9Fb_t_edkZ8IxYj1pKprFpZ88GC-i6YX2Q4_gCchWKEDT7xMUnav6-yc0_8vNyVG1IepqoPCbk0miajU1VzPn0jInFM1FMDbcyI_2q-VJ9Uo1DueYX_bF0vFAPl8GECPI8DVV1IQhVIKulyix06QjXwP3FjOehtg9FDZamjBytGRLS6SFM2N3P_RVsAJsuN-KDlcEXz_B6qWi2djo1E_fhMY69ZjWozFTBjo78SRCJrJJtQgAGycZyM7ZoZ1-KZBxxeXF6Ad48VTrhaPF2huYnvDGwf9cgpcn-Hu7DoD7KNz-iKvq7ixjAP3e_tJHJEgMObjNsFp6eFV0wHlO30C0NdbAq2gJUI3NAs9bH2GpY13xNDDXw5lkKpRZCAZD09CwipFt_NCU=w1640-h910-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Ruht53PszUrFI5H2YUGWXMFMERj9zYOoIRYPKwwMTEHoFSPZTkytV8d7P6D6v5Hs3SOhLyPvQybIm8qhOQt4vu40QZU89p6Bhy-DC4cvHJI-HKlyUmOVfk8_IBibdzREbfA1FNLtQVd-o9w7qk3iZ1af7B0ftK2N1z9qJxRSKhKsFVJDEcLUTWKsqZwffprfJ3BMLYJCFmk6xPbuD74Yo_vQHEa19zBAFsQoEQTu1kshOtrCc7vYM75J4jSN-GSeS7Xy9FhKoJmH-jO51aU28sG9vnnzh4Sz-hL2-CoixgP0Hy4oBPfGptrNwmDWNT-wahUft3GjsBZzvghoLE74dmtdUUDe5i9Fb_t_edkZ8IxYj1pKprFpZ88GC-i6YX2Q4_gCchWKEDT7xMUnav6-yc0_8vNyVG1IepqoPCbk0miajU1VzPn0jInFM1FMDbcyI_2q-VJ9Uo1DueYX_bF0vFAPl8GECPI8DVV1IQhVIKulyix06QjXwP3FjOehtg9FDZamjBytGRLS6SFM2N3P_RVsAJsuN-KDlcEXz_B6qWi2djo1E_fhMY69ZjWozFTBjo78SRCJrJJtQgAGycZyM7ZoZ1-KZBxxeXF6Ad48VTrhaPF2huYnvDGwf9cgpcn-Hu7DoD7KNz-iKvq7ixjAP3e_tJHJEgMObjNsFp6eFV0wHlO30C0NdbAq2gJUI3NAs9bH2GpY13xNDDXw5lkKpRZCAZD09CwipFt_NCU=w1640-h910-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Google PhotosのURLには&lt;code&gt;__&lt;/code&gt;はあっても、&lt;code&gt;____&lt;/code&gt;（アンダースコア4つ）に囲まれている文字列はほぼ含まれないので、そのように変えておきました。&lt;/p&gt;</description></item><item><title>React NativeでHTMLを表示するHTMLViewに対しての理解が進んだ</title><link>https://blog.piyo.tech/posts/2018-11-10-react-native-htmlview/</link><pubDate>Sat, 10 Nov 2018 06:58:05 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-10-react-native-htmlview/</guid><description>&lt;p&gt;以前こちらの記事でMarkdownをHTML化して表示するための方法をいくつか紹介しました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-07-12-markdown-on-react-native/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/dg5kuof-kzw7HdFJYfiUsC99GtY0CeoWryN1Wmt38qxYQGQVQLwvYRPXzHNuURrrw0qUa9RHxzPK0IVndJjVsPBG1A05dlqKA70h5VmhUSJ_YJgZKmu9CZb7z1EnI-NWVrGp8kneSBtUg96ZkvWQoon6dFuISSEQYvYgZ7YUGKJLrAKxH5hFRtL8sbVS6qZHUv8OLWNfJJTic2eR8MjxkeoqFCEmMscpaY5Zj9c3A0BhbwfU9gFqXIuB5IT9gEpDQJv2Q_UHTepSr1viIU4Q2LfXsVNdBvPZK8qOK2O8-cLwadKnS2BXY9Np3z52ydh7VMSJfc-yspvlS9jZJIuC9Smtse6z8zPiHMYguqm8-WZP9M6Kdeqv6whpmq64px_IZq4x_ITd7cbLhFGHMiqyWbCGAQ2wBKgGVHNeZmVB1jZJ8D0ZNF6qjAznMCR7zusvEPYIiXwkAJztaxGB3QxJLr_8UAJUotMOS6wY3o6UeWqRvLKavxZG_dzl1sTn4Mq8hKjn2mSdUrRpOXxIhBz0FuZu9tKgNPsJYZ7u7lUpyPgXZix-PMh7b8X-WxRpouMkfwBDEz15wAzXP0RaYPJ_ab0ox3XXJO2ZV0QVg-JGgX5Lk5PqygSAMxr3jwKdzmznsLGDdNRmh_wB7vVMXTkjvEyoIU-pMM4gSg=w785-h412-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;React NativeでMarkdownを表示する方法をいくつか比較してみた - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;GitHubのようにMarkdownが書けるようなサイトが増えています。僕の働いているソニックガーデンが使っているオフィスツールRemottyでもMarkdownのような記法を一部サポートしています。 WebでMarkdownを扱うにはMarkdown形式の文字列をサーバーサイドなりクライアントサイドでHTML化して表示するだけなのでとても簡単です。また、ただのHTMLなのでCSSにより見た目もかなり柔軟に変えることができます。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;その中で開発中のアプリで使っているHTMLViewはいけてないですね、という話を書きました。&lt;/p&gt;
&lt;p&gt;が、色々調べているうちに、ちょっと使い方が間違っていたのではということに気がついたのでアップデートしておきます。&lt;/p&gt;
&lt;h1 id="valueの渡しかた"&gt;valueの渡しかた&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;HTMLView&lt;/code&gt;は&lt;code&gt;value&lt;/code&gt;プロパティを受け取ります。なのでこれまではMarkdownから生成されたHTMLをそのまま渡していました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;HTMLView&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;} /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;公式READMEのサンプルコードをみてもこうなっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;htmlContent&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`&amp;lt;p&amp;gt;&amp;lt;a href=&amp;#34;http://jsdf.co&amp;#34;&amp;gt;&amp;amp;hearts; nice job!&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;`&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;HTMLView&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;htmlContent&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;stylesheet&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;でもこれだと妙に行間が広かったりとか画像が見えなかったりとかして、質が悪い感じがしていました。
うまくスタイルも効かせることができずに困っていました。&lt;/p&gt;
&lt;p&gt;あるときIssueか何かを見ていてコード例が載っていたんですが、それを真似てHTMLを&lt;code&gt;html&lt;/code&gt;タグと&lt;code&gt;body&lt;/code&gt;タグで囲んでみたら妙に広い行間や画像が見えない件が解決しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;HTMLView&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;`&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;`&lt;/span&gt;} /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コードを見た感じでは&lt;code&gt;html&lt;/code&gt;タグや&lt;code&gt;body&lt;/code&gt;タグを扱っているようには見えなかったので、なぜ？という気がしますが、変更後のほうが良さそうに見えるのでこちらを使うように修正したいと考えています。&lt;/p&gt;
&lt;p&gt;こちらのサンプルにおけるbefore afterの画像を載せておきます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/pi-chan/ReactNativeMarkdownSample" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/02ed2161748a3df9c4f5f8c431dc55aa193e91030a848a322a94c9432e6f09ae/pi-chan/ReactNativeMarkdownSample" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - pi-chan/ReactNativeMarkdownSample&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Contribute to pi-chan/ReactNativeMarkdownSample development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="before"&gt;before&lt;/h2&gt;
&lt;p&gt;&lt;a href=""&gt;&lt;img src="https://lh3.googleusercontent.com/JB9UgFZOs-VigubIf5pNdXkuoW58jBY8BqjnxsDt0F6d4OfuFNV4PLkGZ7j28KFvcV_qC9stkAvWYUN6r_y_2U57cZ15n9hWQ0whQFTiLesNWqDPQpU0nNRWm8FDHZfxgUG3RrelhSeKI57dFqAG5DbGyYzUHB-pMIbfxk4TuPn7kD8VQUaGNnJj3mxNHiN8Fq__MPRhplrcJTjBnm1Q7cjIWbqltrzjYJ01oxkryIavzvIbVDUEQlLbj0A9mksF8RejX18oHPFKFObsPppNEFfV4lH0pVQINftZeIDvVB4z3NVY1t6-uvzY5o_01ew7Vh7_Y5Fye26ZzGRW8LMDz-jRKO4kwed6RQRmAry6JLnoJMM2-ZfuL9yTy2STyjTLsc81nQiAE1augQyPmVhcCpAxsk-qLW0RFoNAsjfPfZeL9D5wvVRraxaAT3GQPKaFAxA6pzEBgCLf5ZJZh0W0jgBQTQvKf_HBIUSDQzCvwiOsR8wiDkhh4S9UfbGnNO0xKLfMdPNkycxN6-JXHusyHoQOBo6qCILcjmox1d5M2a9Z0Gbme75eUZt3aa1kFcbtTbLBpbeYbq0u1Uaofv6qbtiJM8xdl6lX-OF-KIvvvN29t4V6BX0zdjoCdEFR0rmFF5BeHAorSX2uiVMypAojeKxZuosSW5YCtaW2A9Q595zcTLLB3Oth4GXv9HVwcKaArSbrqu1ldKWgmDyKShs1e5n1wWeTLEWMJ70_qeA=w1505-h1334-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="after"&gt;After&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/v5kyfxMs9JRlx1gUoIcqXyZUhfgf56K18hljyVdM2FlN4LECPJvzL-NQH1rOBvjivOAq4xlFMC5c309qOyaYg-6IDa4W8xpBmQfMC-SXfF8wXCPLQ5xuOaKLqXkZhz3m9m49XsPHNYv-x5mGsTv9UvsJEW2SoKcGrCVSUTU-oQsImeEVTCjdx-mILRkJX48ECXYFf0otuoCdpZQ18J_yt_6HY7X_8hKfca9oj2BuEfv5fWXViR91eYIr0YP_JlYgps8RDyWe_8UGtnFAIzSCXAXNKsXqp4z2oytSFr_Wmp12opgao7bXDKbQMifr6MYukV15ZAu17rciHEmZQpTVPhkWMafGeMVbAYHtnXDo0jv21xDxXfjn3L8v9EGAgZjXERMsAIhnXrk8UvhjERgOQdUtBiEpKTNrU_lMK879Ho7OtTEUfWpFz45szLU-GOgIhiuITI1fuvn5jegnFexCY2iHl0iVmsqMxxh3ABbTvDuJGPNBldGI9_zamTWLri2OU4vpASqYGzuuT8aB8EvXjMA3NaT4Yp4gvr9R74tgCKVbQPLzaM0_dYXVPDqjM8slI_l_A5Y6CO9bdKpG_gbSSZze4C5EAhBZ6c1bO7li94pdNYIm7YdPesH9zLLGDHJMS03f0zZGVcBIfXZ4cm6wTHzT2sV6WgB3yyyWk70UqxKfPswN7H9UiH3D6N0Q7ZnlbWqm9rIShNlsKVf81WK8lNPxQY1SFLT39SmDFX8=w750-h1334-no"&gt;&lt;img src="https://lh3.googleusercontent.com/v5kyfxMs9JRlx1gUoIcqXyZUhfgf56K18hljyVdM2FlN4LECPJvzL-NQH1rOBvjivOAq4xlFMC5c309qOyaYg-6IDa4W8xpBmQfMC-SXfF8wXCPLQ5xuOaKLqXkZhz3m9m49XsPHNYv-x5mGsTv9UvsJEW2SoKcGrCVSUTU-oQsImeEVTCjdx-mILRkJX48ECXYFf0otuoCdpZQ18J_yt_6HY7X_8hKfca9oj2BuEfv5fWXViR91eYIr0YP_JlYgps8RDyWe_8UGtnFAIzSCXAXNKsXqp4z2oytSFr_Wmp12opgao7bXDKbQMifr6MYukV15ZAu17rciHEmZQpTVPhkWMafGeMVbAYHtnXDo0jv21xDxXfjn3L8v9EGAgZjXERMsAIhnXrk8UvhjERgOQdUtBiEpKTNrU_lMK879Ho7OtTEUfWpFz45szLU-GOgIhiuITI1fuvn5jegnFexCY2iHl0iVmsqMxxh3ABbTvDuJGPNBldGI9_zamTWLri2OU4vpASqYGzuuT8aB8EvXjMA3NaT4Yp4gvr9R74tgCKVbQPLzaM0_dYXVPDqjM8slI_l_A5Y6CO9bdKpG_gbSSZze4C5EAhBZ6c1bO7li94pdNYIm7YdPesH9zLLGDHJMS03f0zZGVcBIfXZ4cm6wTHzT2sV6WgB3yyyWk70UqxKfPswN7H9UiH3D6N0Q7ZnlbWqm9rIShNlsKVf81WK8lNPxQY1SFLT39SmDFX8=w750-h1334-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;残念ながら入れ子の&lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;はうまくいきません。中のコードを見ても考慮されていないので対応するにはライブラリ本体に手を入れる必要があるかと。&lt;/p&gt;
&lt;h1 id="rendernodeで各domをカスタマイズ"&gt;renderNodeで各DOMをカスタマイズ&lt;/h1&gt;
&lt;p&gt;先程の例のAfterを見ると画像の横幅がはみ出ています。これを直すために&lt;code&gt;renderNode&lt;/code&gt;関数を渡して、表示するコンポーネントをカスタマイズできるようです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;renderNode&lt;/code&gt;に関してはREADMEに載ってるので完全に僕がサボってたわけですが、便利ですね。&lt;code&gt;renderNode&lt;/code&gt;必須かもな、という気がしています。&lt;/p&gt;
&lt;p&gt;先程の例のような画像はみだしの場合は、横幅を限定するようなstyleをあてた&lt;code&gt;Image&lt;/code&gt;コンポーネントを使ってやれば解決します。&lt;/p&gt;
&lt;p&gt;もともとこうだったのを&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;HTMLView&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;`&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;`&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こっちにします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;HTMLView&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;`&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;`&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;renderNode&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;renderNode&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;)}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;this.renderNode&lt;/code&gt;の実装は例えばこんな感じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;width&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Dimensions&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;window&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;renderNode&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;node&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;index&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;siblings&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;parent&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;node&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;img&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;node&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;attribs&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;index&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ &lt;span style="color:#a6e22e"&gt;width&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;width&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.9&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;height&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;source&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;resizeMode&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;contain&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;img&lt;/code&gt;タグの場合には、幅をデバイスの90%に、高さを適当な値に固定した&lt;code&gt;Image&lt;/code&gt;コンポーネントを表示してねというのを書いておきます。&lt;/p&gt;
&lt;p&gt;そしたらこうなります。横幅がちゃんと画面に収まりました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/3CFnkhXS8kdlcGRrtwn43Bn3ITV-7lgA8pQ3cleZ-YhYvAlYufobaueGwr_Brp_38TL2uiWjoC2tPWZVvHCsuUqwYQaTlkXiQaHCpJ_uu5Zev8nrEK0Y2cIAthNGswStLqvqwCGxcixHwJ0F2HzkpZLpXOK4xcKAgQGOmsORPUpcQO5ZIpfhWNhgek1l8Zs7CW4jkGjd0jmAqzU2XkiPf0gj3P_X5zJMIkPjJ_GE2_NBz-6zMektkcDmYi06xI9-H0mITmNh-Tv1sW32E_sdvQzZ4r3QM8wY0QZqv_xElGPFSa8roQ4MgaOoknWWZXenS05bBdjgSMp-WgdJUXyVpOdolLz7o4t_FK3sdct7Y55RCp7sOsWEMiV28HgUweF7XmC3oiRLpbqyivwpiNPjv0dIoCRLYe_53R_ySK5AHV9o5hCIGWF1JGHWxn_-FRL1RwAdq7Rt2qjUfxj-5gsXiXr23JbP5wy3nr4YznTbn3oOY5CqhhRtK5DVM8KPjxC3UZI2vedYR30FojsPM8FJ6l9Ga9lzBqA2avTCKEyYk-A7ZhI9nfXpbLwXpbaCNimFoAlM-r5583ILmFJDt_yjTv5UY5_QLIG5PqsEyHIeuuTNGipCcaMvhQdNTqvt53-2bKC4UMsLqzLC0DqsIw81SqhfeYyJcGnzyfrWDZRjGM8lxu013Qrty8-wteqkzNKct-wxNMqcDAmUwAvKc4TP_WMniZ6gpNy_rgXx-ZU=w750-h1334-no"&gt;&lt;img src="https://lh3.googleusercontent.com/3CFnkhXS8kdlcGRrtwn43Bn3ITV-7lgA8pQ3cleZ-YhYvAlYufobaueGwr_Brp_38TL2uiWjoC2tPWZVvHCsuUqwYQaTlkXiQaHCpJ_uu5Zev8nrEK0Y2cIAthNGswStLqvqwCGxcixHwJ0F2HzkpZLpXOK4xcKAgQGOmsORPUpcQO5ZIpfhWNhgek1l8Zs7CW4jkGjd0jmAqzU2XkiPf0gj3P_X5zJMIkPjJ_GE2_NBz-6zMektkcDmYi06xI9-H0mITmNh-Tv1sW32E_sdvQzZ4r3QM8wY0QZqv_xElGPFSa8roQ4MgaOoknWWZXenS05bBdjgSMp-WgdJUXyVpOdolLz7o4t_FK3sdct7Y55RCp7sOsWEMiV28HgUweF7XmC3oiRLpbqyivwpiNPjv0dIoCRLYe_53R_ySK5AHV9o5hCIGWF1JGHWxn_-FRL1RwAdq7Rt2qjUfxj-5gsXiXr23JbP5wy3nr4YznTbn3oOY5CqhhRtK5DVM8KPjxC3UZI2vedYR30FojsPM8FJ6l9Ga9lzBqA2avTCKEyYk-A7ZhI9nfXpbLwXpbaCNimFoAlM-r5583ILmFJDt_yjTv5UY5_QLIG5PqsEyHIeuuTNGipCcaMvhQdNTqvt53-2bKC4UMsLqzLC0DqsIw81SqhfeYyJcGnzyfrWDZRjGM8lxu013Qrty8-wteqkzNKct-wxNMqcDAmUwAvKc4TP_WMniZ6gpNy_rgXx-ZU=w750-h1334-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;が惜しいですが、いい感じになってきました。&lt;/p&gt;
&lt;p&gt;実際のプロジェクトでは同じような設定で使うことが多い気がするので、renderNodeなどを共通してやってくれるコンポーネントを1つ挟むことで利用するのが良さそうです。&lt;/p&gt;</description></item><item><title>Webサイトに使われている技術を調べられるサービス</title><link>https://blog.piyo.tech/posts/2018-11-08-built-with/</link><pubDate>Thu, 08 Nov 2018 06:28:54 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-08-built-with/</guid><description>&lt;p&gt;Built Withってやつが面白かったので紹介。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://builtwith.com/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://builtwith.com/img/logo/logoSquare.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;BuiltWith&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Find out what websites are BuiltWith&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://builtwith.com/img/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;builtwith.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;調べたいWebサイトのURLを入れるとそのサイトに使われている技術を一覧にしてくれます。&lt;/p&gt;
&lt;p&gt;ということで、僕のブログを解析してみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://builtwith.com/?https%3a%2f%2fblog.piyo.tech"&gt;→結果ページ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;HTMLやレスポンスヘッダーを解析して調べているんだと思いますが、結構色々わかりますね。&lt;/p&gt;
&lt;p&gt;Google Analyticsが使われているとか、Bootstrapが入っているだとか。さらにはHugoで生成されたページだってことまでわかります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/JeFmXWkvL9Nx6PzYfWXSWivDR3aTb6cSjflqYJX2GSUVdWltTDXk7FzDysa49OmXuPN011ClaJ2jkewa5I94kRLM5MB0rA5vtpL90-1sx_4r__qewptgJhmRb0aOcb48Vi8ZFcn0AJqmRTcBKtXnIidyUoDxjcH0xblQm-onaqja3b5RwzFZHKm_yMYj5pmXvq68qp68j9CZiMTWiDY7RvzcmVWKYoZFzS7EtPbKBAUAwp-z8XDz9CXh7R5octrBbpBg6ktxfTy2UkMz0WYAwAba6Tjwbe3KiiLEUNMvwdjMU0efQ9gNX29n62ZfINe7oHOHbqaPD2iqY3R4Ho5dNcYA-Zz-kBaUgX_VVvyEmnLOkrvl2EoIsY_UOHRabD15WMlrz5LhSNNIGH2Ja3sdzxyzVLnughYYrOb33MjM-p6aKHpPd2L9mCK4sF6y5JTzuaCsDKL9w2dNs1MuCwno668-FeEaSpE_bQgXZD2SJvUwgfo6dWC1Ctq7vw3rdfIkeR0D1vT-XpOeeR-0udloz7zwb-ecB_YUelboJU1W-28QSStIJw5z4iyKOHBJfRh6Flhd48gx_bIW9QZuRTPQ1EUbusU8NVLFbMAe1rfjqUoJ244qBlptrhYR6uGpOzSRFIQPZnzD-SEpH-gK8PohP_sYq8B1wn9hOi3cKNVoVR8nj6KhMIw5ynv4Ga83HtN8rw1AbvH3I-NDEN6ZhWKBBhJC5dleUq56v0KTz4k=w1560-h1206-no"&gt;&lt;img src="https://lh3.googleusercontent.com/JeFmXWkvL9Nx6PzYfWXSWivDR3aTb6cSjflqYJX2GSUVdWltTDXk7FzDysa49OmXuPN011ClaJ2jkewa5I94kRLM5MB0rA5vtpL90-1sx_4r__qewptgJhmRb0aOcb48Vi8ZFcn0AJqmRTcBKtXnIidyUoDxjcH0xblQm-onaqja3b5RwzFZHKm_yMYj5pmXvq68qp68j9CZiMTWiDY7RvzcmVWKYoZFzS7EtPbKBAUAwp-z8XDz9CXh7R5octrBbpBg6ktxfTy2UkMz0WYAwAba6Tjwbe3KiiLEUNMvwdjMU0efQ9gNX29n62ZfINe7oHOHbqaPD2iqY3R4Ho5dNcYA-Zz-kBaUgX_VVvyEmnLOkrvl2EoIsY_UOHRabD15WMlrz5LhSNNIGH2Ja3sdzxyzVLnughYYrOb33MjM-p6aKHpPd2L9mCK4sF6y5JTzuaCsDKL9w2dNs1MuCwno668-FeEaSpE_bQgXZD2SJvUwgfo6dWC1Ctq7vw3rdfIkeR0D1vT-XpOeeR-0udloz7zwb-ecB_YUelboJU1W-28QSStIJw5z4iyKOHBJfRh6Flhd48gx_bIW9QZuRTPQ1EUbusU8NVLFbMAe1rfjqUoJ244qBlptrhYR6uGpOzSRFIQPZnzD-SEpH-gK8PohP_sYq8B1wn9hOi3cKNVoVR8nj6KhMIw5ynv4Ga83HtN8rw1AbvH3I-NDEN6ZhWKBBhJC5dleUq56v0KTz4k=w1560-h1206-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Chrome拡張機能を入れておくと気になったページですぐに調べられます。
調べて遊んでみると楽しいかも。&lt;/p&gt;</description></item><item><title>Dash.appへのスニペット登録例を紹介</title><link>https://blog.piyo.tech/posts/2018-11-07-dash-snippet/</link><pubDate>Wed, 07 Nov 2018 06:22:52 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-07-dash-snippet/</guid><description>&lt;p&gt;ドキュメントツールのDashですが、スニペット機能もありますよね。Dashが出た当初はむしろスニペット機能のために使っていました。&lt;/p&gt;
&lt;p&gt;普段からスニペットを便利に使ってるので活用例を紹介してみようかと。&lt;/p&gt;
&lt;h1 id="スニペット展開キーワードのprefix"&gt;スニペット展開キーワードのPrefix&lt;/h1&gt;
&lt;p&gt;スニペットの省略表記としては普段の入力に差し支えないPrefixがあったほうが良いです。僕は&lt;code&gt;;&lt;/code&gt;始まりのキーワードを登録しています。&lt;/p&gt;
&lt;h1 id="メールアドレス"&gt;メールアドレス&lt;/h1&gt;
&lt;p&gt;メインのgmailのアドレスと会社のアドレスをそれぞれ登録しています。&lt;/p&gt;
&lt;p&gt;たとえば&lt;code&gt;;ml&lt;/code&gt;と打つとメインのメールアドレスに変わるようにしています（mailのイメージ）。&lt;/p&gt;
&lt;h1 id="hugoブログ用のショートコード"&gt;Hugo（ブログ）用のショートコード&lt;/h1&gt;
&lt;p&gt;amazonのリンクを置くときや、別ページへのリンクカードを挿入するときなどのためにショートコード用のスニペットを用意しています。&lt;/p&gt;
&lt;p&gt;例えば、amazonへの商品リンクを表示するために、Hugoへの入力として以下のようなテキストを入れておくようにしています。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;{ {&amp;lt; amazon asin=&amp;#34;XXXXXXXX&amp;#34; &amp;gt;}}
(↑本来はスペース要らないですが、ショートコードに解釈されちゃうので空けてます。以下同じです。)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;いちいち入力するのが面倒なので、AmazonのページからASINをコピーしておいた上で&lt;code&gt;;asin&lt;/code&gt;と入力するとコピーしておいた内容を&lt;code&gt;asin=&amp;quot;&amp;quot;&lt;/code&gt;の部分に展開した状態のテキストを挿入できるようにしています。&lt;/p&gt;
&lt;p&gt;スニペットの定義は↓。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;{ {&amp;lt; amazon asin=&amp;#34;@clipboard&amp;#34; &amp;gt;}}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;別ページのリンクカードは↓のような感じで、これも同じくコピー中の内容を展開したものを挿入してくれます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;{ {&amp;lt; screenshot url=&amp;#34;サイトのURL&amp;#34; &amp;gt;}}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="rubyプログラムのデバッグ"&gt;Rubyプログラムのデバッグ&lt;/h1&gt;
&lt;p&gt;Rubyのプログラムのデバッグには&lt;code&gt;Pry&lt;/code&gt;を使う派です。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;binding.pry&lt;/code&gt;と打つことが多いので、&lt;code&gt;;pry&lt;/code&gt;とすると&lt;code&gt;binding.pry&lt;/code&gt;に展開されるようにしています。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;debugger&lt;/code&gt;は何故か手打ちしちゃうんだよな。&lt;/p&gt;
&lt;h1 id="チェックボックスを入力する"&gt;チェックボックス✅を入力する&lt;/h1&gt;
&lt;p&gt;ただのテキストのリストにチェックボックスの絵文字を挿入してDoneの感じを出すことが個人的には多いです。&lt;/p&gt;
&lt;p&gt;いちいち変換するのが大変なので、&lt;code&gt;;ch&lt;/code&gt;で絵文字が出るようにしています。&lt;/p&gt;
&lt;h1 id="前にも似たようなの書いてたｗｗ"&gt;前にも似たようなの書いてたｗｗ&lt;/h1&gt;
&lt;p&gt;なんと4年半ぐらい前にも似たようなの書いてた。忘れてた。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2014-05-02-195202/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://blog.piyo.tech/images/default.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Dashのスニペットに入れておくと便利なやつ教えて - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Dashのスニペットに入れておくと便利なやつ教えて&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>Webサイト用のアイコンをまとめて生成するサイト</title><link>https://blog.piyo.tech/posts/2018-11-06-favicon-generator/</link><pubDate>Tue, 06 Nov 2018 06:07:07 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-06-favicon-generator/</guid><description>&lt;p&gt;アプリ用アイコンを生成するサイトは前に紹介しました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-09-24-make-mobile-app-icon/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/CMtg_FH0EIr9ZHcRK3mjcH-L9ZdWbXCYxFaBiVBmSKYx4sdFyne2Ihf19EJ76TxbXAg66q22DRRIy5Twd6jjpn7invwksfppCKPaFa_4DKICUGMAwu1IU38XPXXHEuPzD9zFAgd-JD9D_hnLK7NoYlsaUVGriyTUE2g1gskzBG5OQ0LITbahecOM_-vh0jL6m43w2aBy6_WUXoVDSfd535b4ub4zXs1P_b838AFU7AP9NIvr54_8KOH4rTZxwUaTY92FODuVRQat5nt1isqOZfmKDM0f-vRpi-8LvUF1Cjqoze32cgOjxVQWaXjEpd0T8261FfJB0d46A1BjTI4thm9h0IYgxLtNyK-62vmNhTWKAGCOV4g3DdeVonBqyXB3KmpQXa2H9quyzm_-p_oEm3o0aZENYSNIG-uHGqoCnoYin-Kl-Hh6bjvbpFL3eo8j7dOY8UK8Zvrkqf-4NvB54EcHl-5x4_LQzht939l4mn44b5wZyzEO8o9noaUzH-90L5bivrA9NV7sRnUhUghR8VVUgF7AlFqC6Pkzzs2LVnWjI_4pfcq1y-_srCW1-OLushHwVsDTeJUhDvGB4l1vEdst9HRGhSYOrced9RsCLfS1HmTFGUpPpawbGp7f5ywiScYCcxV1OqJ0sYob8a_U-XXigov-_d6f" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;モバイルアプリ用の全アイコンサイズを1枚の画像から書き出せるサイト - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;モバイルアプリのアイコンを全部用意するの面倒ですよね。毎度必要なサイズが変わるし。 僕は大きめの正方形画像を用意して、それを元に一括で縮小して生成してくれるサイトを使っています。ちゃんと調べていないので他にもあるのかもしれないですけど、僕はここを使ってます。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="web用のアイコンを一括生成する"&gt;Web用のアイコンを一括生成する&lt;/h1&gt;
&lt;p&gt;Webでも似たようなサイトを使ってまとめてガッと作っちゃうことができます。&lt;/p&gt;
&lt;p&gt;色々ありそうですが僕はこれを使うかな。最初に見つけたので。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.favicon-generator.org/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Favicon &amp;amp; App Icon Generator&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Convert PNG to ICO, JPG to ICO, GIF to ICO. Create favicon.ico and iOS / Android App Icons. Edit a favicon to fit your needs, or search our gallery.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://dpidudyah7i0b.cloudfront.net/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;www.favicon-generator.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="ファイルをアップロードする"&gt;ファイルをアップロードする&lt;/h1&gt;
&lt;p&gt;ベースとなるアイコンを選択し、少し設定をいじって「Create Favicon」を押せばOK。&lt;/p&gt;
&lt;p&gt;しばらくすると完了ページへ遷移します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/DXJYkLG7xGggvOt5zECcGq2i2wQkNpc8DSMdlh_CmFiYwcNt3I34YGB93XG58qHAyEr74VeS9f__dmsyyUwFAw7O0XoxQqUqAE8hD9XkTfaIPWutGaDnBl4EmgtO9Adzs3icBZiSHL3BsD0-iiV7SKHVDyjR8L7CHGtPOSiIdu868ISFqbAu9TusprSJO1Sh0rHTdAVHKJo-9VK0rRTkqKOVcu-3VfYonidLHGczpkZDD_ff8sl8E0SrYYm4m0abY_zpsTOTsm7Q_wMmoI2usRj8K4ZoHrZLh3UPg45UYwYxidNMTRQXuIat9JESVqflAGi_Lj-L8Om6BadHYMnxMCTjHtcImZKlt-CAiWyI5hy4tr7FF25qQSnP5PTlt4afG5iGOtnzZURdJPsvDGG_BVlWt_fx94266H95V9mG2UacKZ7wLY5tlRmY23oPLNXsWuywPnqvnahPVTSquCmXEk6TFhlF1F9NGGLuiRSjbg9OJq0VDuPO7wlvEk0FdniTei5Oeyu-eeLL0vus5oEFrptkPkG6vU0kl2o1wq2jY7aSmGHUUjtJbxj4c7OK7eMYONzkeDp0n5SLjb6wwJxPqLCLqtmgKeKqSAo-xv7VwFdH4vfRpa5srOv8nFBuVRaaStpBAYsWKPSL_WLs07rPHBttXXZQRYK5BYLMOaj1JE3-vvwSoUKzI4S9JcXrwIYJRZp1WzgPLsQ7qqgj5Tk=w1030-h313-no"&gt;&lt;img src="https://lh3.googleusercontent.com/DXJYkLG7xGggvOt5zECcGq2i2wQkNpc8DSMdlh_CmFiYwcNt3I34YGB93XG58qHAyEr74VeS9f__dmsyyUwFAw7O0XoxQqUqAE8hD9XkTfaIPWutGaDnBl4EmgtO9Adzs3icBZiSHL3BsD0-iiV7SKHVDyjR8L7CHGtPOSiIdu868ISFqbAu9TusprSJO1Sh0rHTdAVHKJo-9VK0rRTkqKOVcu-3VfYonidLHGczpkZDD_ff8sl8E0SrYYm4m0abY_zpsTOTsm7Q_wMmoI2usRj8K4ZoHrZLh3UPg45UYwYxidNMTRQXuIat9JESVqflAGi_Lj-L8Om6BadHYMnxMCTjHtcImZKlt-CAiWyI5hy4tr7FF25qQSnP5PTlt4afG5iGOtnzZURdJPsvDGG_BVlWt_fx94266H95V9mG2UacKZ7wLY5tlRmY23oPLNXsWuywPnqvnahPVTSquCmXEk6TFhlF1F9NGGLuiRSjbg9OJq0VDuPO7wlvEk0FdniTei5Oeyu-eeLL0vus5oEFrptkPkG6vU0kl2o1wq2jY7aSmGHUUjtJbxj4c7OK7eMYONzkeDp0n5SLjb6wwJxPqLCLqtmgKeKqSAo-xv7VwFdH4vfRpa5srOv8nFBuVRaaStpBAYsWKPSL_WLs07rPHBttXXZQRYK5BYLMOaj1JE3-vvwSoUKzI4S9JcXrwIYJRZp1WzgPLsQ7qqgj5Tk=w1030-h313-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;一番下のチェックが入ってると公開ギャラリーに含まれちゃうみたいなので外すのが無難です。&lt;/p&gt;
&lt;h1 id="ファイルをダウンロードタグ設置"&gt;ファイルをダウンロード&amp;amp;タグ設置&lt;/h1&gt;
&lt;p&gt;完了ページにあるダウンロードリンクを押すと全ファイルをダウンロードできます。&lt;/p&gt;
&lt;p&gt;ダウンロードされるファイルは↓の通り。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% tree .
.
├── android-icon-144x144.png
├── android-icon-192x192.png
├── android-icon-36x36.png
├── android-icon-48x48.png
├── android-icon-72x72.png
├── android-icon-96x96.png
├── apple-icon-114x114.png
├── apple-icon-120x120.png
├── apple-icon-144x144.png
├── apple-icon-152x152.png
├── apple-icon-180x180.png
├── apple-icon-57x57.png
├── apple-icon-60x60.png
├── apple-icon-72x72.png
├── apple-icon-76x76.png
├── apple-icon-precomposed.png
├── apple-icon.png
├── browserconfig.xml
├── favicon-16x16.png
├── favicon-32x32.png
├── favicon-96x96.png
├── favicon.ico
├── manifest.json
├── ms-icon-144x144.png
├── ms-icon-150x150.png
├── ms-icon-310x310.png
└── ms-icon-70x70.png
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;実際にはfaviconだけあれば良いケースが多い気もしてますが、が、iOSでホーム画面に追加するときには&lt;code&gt;apple-icon-*&lt;/code&gt;が使われるので僕は自サイトには一応入れています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/a1dWGkBS3T8bzVmLzgANV3WFEgqjAJgqIq2wHhIEMtW1pwK60hMfwokJHu3Xne0JCD4njO4QsVBWZth2zCZPcVp0LSKAFVa6oqr8ahm8Q0XmXrjmaauaXc-i9Tb7hrDFXc4AP1iZyqlWVJ8RBsvkhT19kBFEOA-k2v3HHIOFmO1iAjSEh7iepKFz8bPDlUu5FxhS5UH6oayQJhO36ZuUevp6MjfcOHoVOeFkVcFd2CZAvlnwjfDriArgGvwjbVO9rjCU_ZlIZwfTnsudL3K80vMPQdHfzx9vugFbLDpsKqtQQJ-Anl8NY48gqigKVWyu3BgjEZyy1_jTMlAC4HwY54zk1Hmt1MlyyxxHK8NnnLofmAXfgKyQwDzN5oqTT16rgWGWCK85B9iB_bk0PzbKixLPo6Zze9ssVFFJhFDi-PJXqFU5auzpaIwagY0YsfgHmFEBcc7IV645RD6DTXiJzEK-gsvJHGTAmma6O-RLu-W982d9RBoWlKuZI0liaD4T5jyNlIRf7L_vqK2jhHbi3ZKDINZdJjFqXcSMWD7Ns5nykmdtrNnoLT7mT7-S9YH79ASqoxheCYOHDeSC__JtHsc2TNHqKnnWBtkggbuQ8Z5LgG_EhSZ6UCoBsoWVDp05CDTNmBXwFBrtPPp7SPw6UCA641-aN4MnjfSYtogAYwrlW5_jAxyORxoCyGmjCPumFb5bUxRDJOZ7XxdFDUw=w1392-h1216-no"&gt;&lt;img src="https://lh3.googleusercontent.com/a1dWGkBS3T8bzVmLzgANV3WFEgqjAJgqIq2wHhIEMtW1pwK60hMfwokJHu3Xne0JCD4njO4QsVBWZth2zCZPcVp0LSKAFVa6oqr8ahm8Q0XmXrjmaauaXc-i9Tb7hrDFXc4AP1iZyqlWVJ8RBsvkhT19kBFEOA-k2v3HHIOFmO1iAjSEh7iepKFz8bPDlUu5FxhS5UH6oayQJhO36ZuUevp6MjfcOHoVOeFkVcFd2CZAvlnwjfDriArgGvwjbVO9rjCU_ZlIZwfTnsudL3K80vMPQdHfzx9vugFbLDpsKqtQQJ-Anl8NY48gqigKVWyu3BgjEZyy1_jTMlAC4HwY54zk1Hmt1MlyyxxHK8NnnLofmAXfgKyQwDzN5oqTT16rgWGWCK85B9iB_bk0PzbKixLPo6Zze9ssVFFJhFDi-PJXqFU5auzpaIwagY0YsfgHmFEBcc7IV645RD6DTXiJzEK-gsvJHGTAmma6O-RLu-W982d9RBoWlKuZI0liaD4T5jyNlIRf7L_vqK2jhHbi3ZKDINZdJjFqXcSMWD7Ns5nykmdtrNnoLT7mT7-S9YH79ASqoxheCYOHDeSC__JtHsc2TNHqKnnWBtkggbuQ8Z5LgG_EhSZ6UCoBsoWVDp05CDTNmBXwFBrtPPp7SPw6UCA641-aN4MnjfSYtogAYwrlW5_jAxyORxoCyGmjCPumFb5bUxRDJOZ7XxdFDUw=w1392-h1216-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;またこのページには、HTMLのコードが載っています。これは&lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;内に挿入するためのコードで、パスさえ気をつければほぼそのまま使えます。&lt;/p&gt;
&lt;p&gt;このタグを思い出して書くのが面倒だからこのサイトを使っていると言っても過言ではないです。&lt;/p&gt;</description></item><item><title>real-world-railsでOSSのRailsアプリケーションを探す</title><link>https://blog.piyo.tech/posts/2018-11-05-real-world-rails/</link><pubDate>Mon, 05 Nov 2018 06:53:34 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-05-real-world-rails/</guid><description>&lt;p&gt;real-world-railsっていうリポジトリにOSSのRailsアプリケーションがまとめられています。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/eliotsykes/real-world-rails" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/353952399ef5fe0697dc52a1336783f9b1c475331825716891acf3d1b34449c0/eliotsykes/real-world-rails" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - eliotsykes/real-world-rails: Real World Rails applications and their open source codebases for developers to learn from&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Real World Rails applications and their open source codebases for developers to learn from - eliotsykes/real-world-rails&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;リンク集じゃなくて全部サブモジュールになってて一気にクローンできちゃいます。やる必要ないけど。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/cjdzmMW6hclTrrpO2kRQs7oapW7p0z0LP0oyInbmB2X8FaeMpG_X6M6jXqVuBZDQfaIeTroP80tQpKIlyBj_NglkDKUViIoCCohO5Cv97SuPW2W1tCWGOoVM9k4ImJGcbgXmTk0TTS0UnACp1aBcCEEYiPI6wTz04hWTfFNlA3m66NvItILoDQa9XD1J3pmxnV-qdfMp6lFkeuajDa71aD3YXRa_Be9bMK3Do-FVSEr2LsExCiPe-FvnRAyvI_en7Hx0rsZhm8yxfctcmAst4uqtp7WwXIWksYtLJGlYWOyb2xRWg2IlDgPM4XO659wRVxcXlDbl1MGlnMMuZJw0LAlfgD5BGlSPfeS27T8BL6COvfY_2HbtpWT-YQACMcvnx4mqIunttCCssOtNLxg9vPPNmcpjZqMCEgJaqaGb8KHUQTEIfOjf5hTiixmO2GWOKzcyk-ZJYxzZorjQr8FOkIKKeeetKMk09eNECJyOPNC7kRES1QAcMh27mG17Bk0-d194Vd_KP9n5Mi1x-P_2gvSfbFhVV-O1m1h2LjkFrAKGZ8wgJMGpxxPw2jxznPuX8s1lQsEp4TmZPu3dobvrLU_enUqbmcckqYAd2XWPxI98JQpBleIizaqUVPIZpUpUN31qXNemDxuiI8ZvqBZ8U4o7M0ii6D_C6COy6zmGtFocZUD5AX-t4V879ECSLNIdoSBubCITM1O-VMi-2zQ=w2082-h956-no"&gt;&lt;img src="https://lh3.googleusercontent.com/cjdzmMW6hclTrrpO2kRQs7oapW7p0z0LP0oyInbmB2X8FaeMpG_X6M6jXqVuBZDQfaIeTroP80tQpKIlyBj_NglkDKUViIoCCohO5Cv97SuPW2W1tCWGOoVM9k4ImJGcbgXmTk0TTS0UnACp1aBcCEEYiPI6wTz04hWTfFNlA3m66NvItILoDQa9XD1J3pmxnV-qdfMp6lFkeuajDa71aD3YXRa_Be9bMK3Do-FVSEr2LsExCiPe-FvnRAyvI_en7Hx0rsZhm8yxfctcmAst4uqtp7WwXIWksYtLJGlYWOyb2xRWg2IlDgPM4XO659wRVxcXlDbl1MGlnMMuZJw0LAlfgD5BGlSPfeS27T8BL6COvfY_2HbtpWT-YQACMcvnx4mqIunttCCssOtNLxg9vPPNmcpjZqMCEgJaqaGb8KHUQTEIfOjf5hTiixmO2GWOKzcyk-ZJYxzZorjQr8FOkIKKeeetKMk09eNECJyOPNC7kRES1QAcMh27mG17Bk0-d194Vd_KP9n5Mi1x-P_2gvSfbFhVV-O1m1h2LjkFrAKGZ8wgJMGpxxPw2jxznPuX8s1lQsEp4TmZPu3dobvrLU_enUqbmcckqYAd2XWPxI98JQpBleIizaqUVPIZpUpUN31qXNemDxuiI8ZvqBZ8U4o7M0ii6D_C6COy6zmGtFocZUD5AX-t4V879ECSLNIdoSBubCITM1O-VMi-2zQ=w2082-h956-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mastodon&lt;/code&gt;や&lt;code&gt;dev.to&lt;/code&gt;なんかも入っています。&lt;/p&gt;
&lt;p&gt;惜しいのは何がどんなアプリケーションなのかわからないことですね。&lt;/p&gt;
&lt;p&gt;実装の参考などに多少は役にたつかも。&lt;/p&gt;</description></item><item><title>awesome-vueでOSSのVueアプリケーションを探す</title><link>https://blog.piyo.tech/posts/2018-11-04-awesome-vue/</link><pubDate>Sun, 04 Nov 2018 06:45:44 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-04-awesome-vue/</guid><description>&lt;p&gt;ライブラリ探しに&lt;code&gt;awesome-xxxx&lt;/code&gt;みたいなリポジトリを参考にすること多いんですが、まとまってるのってライブラリだけじゃないんですねー。&lt;/p&gt;
&lt;p&gt;色々見てたら、&lt;code&gt;awesome-ios&lt;/code&gt;にはスタンフォード大学の授業（だと思われる）iTunes Uのリンクがあったりとか、&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/vsouza/awesome-ios" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/f8ff6be3f42470e688909d9c317c739087d5d333e64e9eb824c71a3261da9a6b/vsouza/awesome-ios" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - vsouza/awesome-ios: A curated list of awesome iOS ecosystem, including Objective-C and Swift Projects&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;A curated list of awesome iOS ecosystem, including Objective-C and Swift Projects - vsouza/awesome-ios&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;awesome-react-native&lt;/code&gt;にはWeb記事のまとめがあったりします。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/jondot/awesome-react-native" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/dc24926ebc2190585d51ef6a62769338a79bbb7e742b7cae007dd646a1b6ad51/jondot/awesome-react-native" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - jondot/awesome-react-native: Awesome React Native components, news, tools, and learning material!&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Awesome React Native components, news, tools, and learning material! - jondot/awesome-react-native&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Vueに至っては公式で用意されていて、記事や本などのがまとめられています。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/988cc5f5ad1ed6e067c3a6656b459d79c8ba00cfbdf2b2595ec2ec36c8d3be22/vuejs/awesome-vue" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - vuejs/awesome-vue: 🎉 A curated list of awesome things related to Vue.js&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;🎉 A curated list of awesome things related to Vue.js - vuejs/awesome-vue&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;その中の「Projects Using Vue.js」のところを見ると、実際にVueを使ってるOSSプロジェクトがまとまってます。&lt;/p&gt;
&lt;p&gt;これ、実装の参考になること間違いなしでは。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/vuejs/awesome-vue#projects-using-vuejs"&gt;https://github.com/vuejs/awesome-vue#projects-using-vuejs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;自分でも使いつつ、中身も覗けるといいよねーと思ったりします。&lt;/p&gt;
&lt;p&gt;実際どこまでコード見るかというとなんとも言えないけど…&lt;/p&gt;</description></item><item><title>外部ディスプレイとMacBookを縦にならべることで首への負担の軽減をはかる</title><link>https://blog.piyo.tech/posts/2018-11-03-change-display-layout/</link><pubDate>Sat, 03 Nov 2018 06:39:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-03-change-display-layout/</guid><description>&lt;p&gt;首こりからくる頭痛がひどいので自宅の仕事環境を色々変えてみようと試した記録です。&lt;/p&gt;
&lt;p&gt;写真を撮りたかったんですが、ごちゃっとしている配線を写すのもアレだったのでiPadで絵をかきました。&lt;/p&gt;
&lt;h1 id="元々は横ならびでした"&gt;元々は横ならびでした&lt;/h1&gt;
&lt;p&gt;デスクの上にディスプレイ2枚を配置し、MacBookは閉じた状態（いわゆるクラムシェルモード）にしておきます。&lt;/p&gt;
&lt;p&gt;自分は2枚のディスプレイのちょうど真ん中あたりにおり、常に右か左のどちらかを向いている状態です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/QizPso88MESymIa44MfjKaPrbvh7Ogm8aBCoGYm24D8aFSFBc-0_7bUmDw7dHHKl4tbmdTYmKF9ACRmMWpn5-n4LH-Ls82jI4rN0k1AG7Q5WtIlH3nSLPBgW-AQxdyLUJNIY7cdcjb1rzF4V198ZGTldWaHNbp4Evkc94ipRSbRNeMbaVbUs2BWbM_VXEgFeUSD7ftm052bkJ3z25GZGwmmO86meDO5-jwisfZjDYlHaDu-I37ZrF7kdyIEFfZavWWKv0qLeziS85tWmwWc8oWpMbBFBmY0oA2Yocoa06BHn2UZrBzvKZeDmqLWhrvgtHedilTj1LiiPc0AoINbIka_-ulp4a9eQrGXGndhoW88rUrpfgxGvwbj01MMU7nrGi0Xfm8o14McqhuhXP4N0mifntQmq3ADLQKQZWfWgy4bYZpAFcieRyIQ6WjB0uPz_177FsW-uH2bCi6zxccjKvXYKMG1m0ULX5WT3pcuHePzTraq9YrpulQipQONolMmN8amc8VIpN-2EGoo2U6UFW2lBHhNXbzpah8qpseGbIbLP0d4a7b-Utr-jafzzI1xcQxvdVVHiLjJ9gbNOaVrTcQnBmjY1VnmoasQxZaq8zbxtqF7ddFoaRJ1lG11KEw09NLe2qYgmbk2sVYFdhesn7coFy14BMNlmIUY1O1l_nwkmD6HSrbZfeeVsdJn09_zhoEL32EOemFarYYhYrC8=w2048-h1408-no"&gt;&lt;img src="https://lh3.googleusercontent.com/QizPso88MESymIa44MfjKaPrbvh7Ogm8aBCoGYm24D8aFSFBc-0_7bUmDw7dHHKl4tbmdTYmKF9ACRmMWpn5-n4LH-Ls82jI4rN0k1AG7Q5WtIlH3nSLPBgW-AQxdyLUJNIY7cdcjb1rzF4V198ZGTldWaHNbp4Evkc94ipRSbRNeMbaVbUs2BWbM_VXEgFeUSD7ftm052bkJ3z25GZGwmmO86meDO5-jwisfZjDYlHaDu-I37ZrF7kdyIEFfZavWWKv0qLeziS85tWmwWc8oWpMbBFBmY0oA2Yocoa06BHn2UZrBzvKZeDmqLWhrvgtHedilTj1LiiPc0AoINbIka_-ulp4a9eQrGXGndhoW88rUrpfgxGvwbj01MMU7nrGi0Xfm8o14McqhuhXP4N0mifntQmq3ADLQKQZWfWgy4bYZpAFcieRyIQ6WjB0uPz_177FsW-uH2bCi6zxccjKvXYKMG1m0ULX5WT3pcuHePzTraq9YrpulQipQONolMmN8amc8VIpN-2EGoo2U6UFW2lBHhNXbzpah8qpseGbIbLP0d4a7b-Utr-jafzzI1xcQxvdVVHiLjJ9gbNOaVrTcQnBmjY1VnmoasQxZaq8zbxtqF7ddFoaRJ1lG11KEw09NLe2qYgmbk2sVYFdhesn7coFy14BMNlmIUY1O1l_nwkmD6HSrbZfeeVsdJn09_zhoEL32EOemFarYYhYrC8=w2048-h1408-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この右か左のどちらかを向いている姿勢が首に負担をかけているのではないかと思ったわけです。&lt;/p&gt;
&lt;h1 id="縦ならびにした"&gt;縦ならびにした&lt;/h1&gt;
&lt;p&gt;今は小さいほうのディスプレイを撤廃して、外部ディスプレイ1枚とMacBook Proを上下に並ばせる形で使用しています。&lt;/p&gt;
&lt;p&gt;これだと左右を向く必要はなくなり、上下の動きが中心になります。&lt;/p&gt;
&lt;p&gt;目線をちょうど外部ディスプレイの上端と合うぐらいにしているので、見上げる動作はありません。人間見下ろすより見上げるほうが首への負担が大きい気がします。見下ろす姿勢も、ずっとしているとつらくなるので主に正面に置いた外部ディスプレイを中心に使っています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/BC_wamHbkt7vfLdC7vP_kPzOHxPcFM53lBY3QU6ObeuzkJmipqSFWa4cTjy0PVX-0zhMxTWcwo9M0UPH9Z87O4gE5UX3ePgOv7xlJE4hwz6khDgv7QdnpeHr3OsZfwbJeO6htDiRmOJVsXEvnkNPyAqM6n4UMrBvB1Ti8NO6OJbUhwXTiw2hzkNKkFiVBiqFQvk__g7UqXdbSeqUnyl-G2ot8XqEWLczCEQW5TjsfSL1vMcTp0N0-WjeczNrETaSNoYKbPhq0ostlU-bbO8-krNIM8s6ZjIMEpVeutBDHqU91IuGjvNpoGUs246D9a5yjtJErxKruS0p2Y152NOHbFTyvK3e0GwgV8DbXLr2QlhFvRI34L71mfBGinlTOaaIimhGctMBU4KTb-RHhmKVOp5uHTLQxhrTSoI5lI-EQfuaSL3dWJeofDPNdBYrI9ZlutYdZlyy3OtFPTQ4To-hzcSTpuWarNJvqVaogrW6jA60YxYxXcWPgMnN2sB8LSBbuMqv9dhC_kZOKG8h0FOoWL_QPLqV7MzAh7lhSac8dmA9kxre726hdTSDpsnW3MxP8DY2P0UGzurc0TbWvkf4gez8ViMR_3Hq08g63d0YL3C6yTQEbOiix-vmhFxkcg8QqG0BRhajH8ByWeHw7B5ta0fr6kg1bKNcPxItUqMdGTdKL08hFL2Id0e2txqyBIwtHUQC_qxdtvMqHuYHIhY=w2048-h1408-no"&gt;&lt;img src="https://lh3.googleusercontent.com/BC_wamHbkt7vfLdC7vP_kPzOHxPcFM53lBY3QU6ObeuzkJmipqSFWa4cTjy0PVX-0zhMxTWcwo9M0UPH9Z87O4gE5UX3ePgOv7xlJE4hwz6khDgv7QdnpeHr3OsZfwbJeO6htDiRmOJVsXEvnkNPyAqM6n4UMrBvB1Ti8NO6OJbUhwXTiw2hzkNKkFiVBiqFQvk__g7UqXdbSeqUnyl-G2ot8XqEWLczCEQW5TjsfSL1vMcTp0N0-WjeczNrETaSNoYKbPhq0ostlU-bbO8-krNIM8s6ZjIMEpVeutBDHqU91IuGjvNpoGUs246D9a5yjtJErxKruS0p2Y152NOHbFTyvK3e0GwgV8DbXLr2QlhFvRI34L71mfBGinlTOaaIimhGctMBU4KTb-RHhmKVOp5uHTLQxhrTSoI5lI-EQfuaSL3dWJeofDPNdBYrI9ZlutYdZlyy3OtFPTQ4To-hzcSTpuWarNJvqVaogrW6jA60YxYxXcWPgMnN2sB8LSBbuMqv9dhC_kZOKG8h0FOoWL_QPLqV7MzAh7lhSac8dmA9kxre726hdTSDpsnW3MxP8DY2P0UGzurc0TbWvkf4gez8ViMR_3Hq08g63d0YL3C6yTQEbOiix-vmhFxkcg8QqG0BRhajH8ByWeHw7B5ta0fr6kg1bKNcPxItUqMdGTdKL08hFL2Id0e2txqyBIwtHUQC_qxdtvMqHuYHIhY=w2048-h1408-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ちなみに、普通に外部ディスプレイを置くとMacBookのディスプレイ部分の裏側に隠れてしまう領域ができてしまい不便です。&lt;/p&gt;
&lt;p&gt;そこはアナログハックで回避。外部ディスプレイの下にiPadの化粧箱を置いて高さを稼ぎました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/q2QsP52t7g2SK4booVW8WYwWlumfEzu_MJWKprGb9DWKxU4KikylkbcPKuya2NpkBbfCiYo6QuWZ068dMnpPlzOpOfE7ksTCUtN6HBEixDclzgbEuvfKBrxkSrTIIj4DXtM4B3SiABE7PUGstXGB4gvh-ZVKPRYlcMm-pNnh1MBbxVjXC8X_t7potonR51djZL7IjPVLt0KjeqSH6OwEYtDA1zCUCRVLLmaqSV8m42Jrxo2JT5pELaBbNYzpznTm04Ox9URWT-rPhdmZTDcCpNcDPPM7RlLXMsD6NhdNCEPrKVrwYWP1x5j55_diAEHC9sgAJ93mxudP7foZewiYUo1sWOK9hjVB-rYcANeMFFZlec-fFsx-XVF2SZIV0QwbEMCpZ2-5ILPOZvbD05mFk2S7ku2G-x0bHIZfS3-V0PVq95R_ObOlfpaa5JnCN_kKss-67OZJnOVJYyiIWvjDRGcteDcEiwW7NR3ZXNOST-xdYNvrbDpvWoCaVO2DWnigyYMYTIHTht7ZMEFQqvvqdt4sunlEWyDK3Qx_UgRtuJhgbpqrkLzWhikRP0UZAgrSb_Ml-tVx3WISNu-02Gs-60PyF2wq0D6m7QDkGPwkZe7fcfD8NKbxmFTnyn-iELulQJQ-vEZXOSBWalBGqjnCKMhQ6-GmQapnjbu4KCiORuU8b2IkRTDbaZHShzHfvPAtNQtfcKbQRCmIdDQDhlA=w943-h1026-no"&gt;&lt;img src="https://lh3.googleusercontent.com/q2QsP52t7g2SK4booVW8WYwWlumfEzu_MJWKprGb9DWKxU4KikylkbcPKuya2NpkBbfCiYo6QuWZ068dMnpPlzOpOfE7ksTCUtN6HBEixDclzgbEuvfKBrxkSrTIIj4DXtM4B3SiABE7PUGstXGB4gvh-ZVKPRYlcMm-pNnh1MBbxVjXC8X_t7potonR51djZL7IjPVLt0KjeqSH6OwEYtDA1zCUCRVLLmaqSV8m42Jrxo2JT5pELaBbNYzpznTm04Ox9URWT-rPhdmZTDcCpNcDPPM7RlLXMsD6NhdNCEPrKVrwYWP1x5j55_diAEHC9sgAJ93mxudP7foZewiYUo1sWOK9hjVB-rYcANeMFFZlec-fFsx-XVF2SZIV0QwbEMCpZ2-5ILPOZvbD05mFk2S7ku2G-x0bHIZfS3-V0PVq95R_ObOlfpaa5JnCN_kKss-67OZJnOVJYyiIWvjDRGcteDcEiwW7NR3ZXNOST-xdYNvrbDpvWoCaVO2DWnigyYMYTIHTht7ZMEFQqvvqdt4sunlEWyDK3Qx_UgRtuJhgbpqrkLzWhikRP0UZAgrSb_Ml-tVx3WISNu-02Gs-60PyF2wq0D6m7QDkGPwkZe7fcfD8NKbxmFTnyn-iELulQJQ-vEZXOSBWalBGqjnCKMhQ6-GmQapnjbu4KCiORuU8b2IkRTDbaZHShzHfvPAtNQtfcKbQRCmIdDQDhlA=w943-h1026-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="首こりは解消したのか"&gt;首こりは解消したのか！？&lt;/h1&gt;
&lt;p&gt;左右のときよりもいいのか悪いのか、結局はよくわかっていません。&lt;/p&gt;
&lt;p&gt;副作用として、24インチのディスプレイは4Kディスプレイじゃなかったので少し見づらかったのが、27インチの4KディスプレイとMacBook Proの画面を使うようになって全部きれいに見えるようになりました。&lt;/p&gt;</description></item><item><title>トップページの表示がIEで壊れていたので直しました</title><link>https://blog.piyo.tech/posts/2018-11-02-fix-ie-layout/</link><pubDate>Fri, 02 Nov 2018 06:21:55 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-02-fix-ie-layout/</guid><description>&lt;p&gt;IEでのトップ画面の表示がこのザマでした。各記事のカードみたいなのが潰れちゃってます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/22HsRhNpbpJs5zZGo9bcc-qtoBnCLxTSaYoVYN9E8RdfSKqz2qT5PiGpFZtKGxGuVT1pAz3zJQQSFKyStBrt2m1RSrQms9ANbSYC5_dWAIGjDl_CyLFrjolTnU4V8aROpN2I1fMOyEDASsBuQb_2rnubtwP2kTW8Mlw4h9RH5haAnmg0QIas44IdFqun1OmSU8s7LtarLf096pz64HeqlOybnabZ8VZl-H15gfG7nnusH6hSeg4BBb8_uDKbqp1gUOUhh0VYk27pC0_TThXwNzXNvmMMvbSIZCr4nFq5Jfyyg20nh40yHi2_hgXlGE4ZBJsImH7g3uRyq6_ircBb5P7VizEgPybr-a9ghInVgIGYNA5Hk3IMGmVz-nyIkA-8XaFPgZ9eINfjVCEy_QQMopXvp5E5xoONBBAPjxVykYxyeE-pW4ffjENFR63I_dTcuV0aoKpCR98lpYj1_UiAQogQn3Ltpbh28bK0pRRhWedm-f9bKMEw3MDVncKril7z1oawBcU-Nyy7MTT-sFb10_eXZHsf5GF-0oxe5ufjvoj4JL4PjEHI-Y5hSOxb8cMj1pv8z9OpXB5Yl57wv1vjqQ6zQ4X_m6eNd-wLrIaXSZEFgDNvQcpXFbujQsZhO1TLbevE90nIWmXQWKHMDS70At9-sRLQSujDsTY-0Vt5cV91iF0C_v8uBvr-ODLCy40zLXAeBNy8PKVH92q5Qq8=w1369-h1358-no"&gt;&lt;img src="https://lh3.googleusercontent.com/22HsRhNpbpJs5zZGo9bcc-qtoBnCLxTSaYoVYN9E8RdfSKqz2qT5PiGpFZtKGxGuVT1pAz3zJQQSFKyStBrt2m1RSrQms9ANbSYC5_dWAIGjDl_CyLFrjolTnU4V8aROpN2I1fMOyEDASsBuQb_2rnubtwP2kTW8Mlw4h9RH5haAnmg0QIas44IdFqun1OmSU8s7LtarLf096pz64HeqlOybnabZ8VZl-H15gfG7nnusH6hSeg4BBb8_uDKbqp1gUOUhh0VYk27pC0_TThXwNzXNvmMMvbSIZCr4nFq5Jfyyg20nh40yHi2_hgXlGE4ZBJsImH7g3uRyq6_ircBb5P7VizEgPybr-a9ghInVgIGYNA5Hk3IMGmVz-nyIkA-8XaFPgZ9eINfjVCEy_QQMopXvp5E5xoONBBAPjxVykYxyeE-pW4ffjENFR63I_dTcuV0aoKpCR98lpYj1_UiAQogQn3Ltpbh28bK0pRRhWedm-f9bKMEw3MDVncKril7z1oawBcU-Nyy7MTT-sFb10_eXZHsf5GF-0oxe5ufjvoj4JL4PjEHI-Y5hSOxb8cMj1pv8z9OpXB5Yl57wv1vjqQ6zQ4X_m6eNd-wLrIaXSZEFgDNvQcpXFbujQsZhO1TLbevE90nIWmXQWKHMDS70At9-sRLQSujDsTY-0Vt5cV91iF0C_v8uBvr-ODLCy40zLXAeBNy8PKVH92q5Qq8=w1369-h1358-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Google Analyticsによると5%程度 IEからの閲覧があるようです。&lt;/p&gt;
&lt;p&gt;まあ直接個別記事へ来ることがほとんどでしょうからトップページは見てないかもしれませんが、気持ち悪いので直すことにしました。&lt;/p&gt;
&lt;p&gt;潰れている箇所のスタイルに&lt;code&gt;flex: 1;&lt;/code&gt;なる指定があったので、まあほぼこれだろうとあたりをつけました。&lt;/p&gt;
&lt;p&gt;IE11はflexboxに対応しているものの、挙動がおかしいことで有名です。先日も仕事のプロジェクトで遭遇して対応したことがあるのでなんとなくわかっていました。&lt;/p&gt;
&lt;p&gt;ちなみにそのとき参考にしたのはこちらのQiita記事です。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://qiita.com/hashrock/items/189db03021b0f565ae27" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkYwJTJGMzI1OTYlMkZwcm9maWxlLWltYWdlcyUyRjE1ODU3MjUyMjU_aXhsaWI9cmItNC4wLjAmYXI9MSUzQTEmZml0PWNyb3AmbWFzaz1lbGxpcHNlJmJnPUZGRkZGRiZmbT1wbmczMiZzPWIyOGI4Y2M2NDNlZjgzOTNiNjNlNGM5OWRlN2JmNjU4%26blend-x%3D120%26blend-y%3D467%26blend-w%3D82%26blend-h%3D82%26blend-mode%3Dnormal%26s%3D73097f905c5c65ddc8e4796da42c5b13?ixlib=rb-4.0.0&amp;amp;w=1200&amp;amp;fm=jpg&amp;amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9ZmxleGJveCVFMyU4MSVBRSVFMyU4MyU5MCVFMyU4MiVCMCVFMyU4MSVBQiVFNyVBQiU4QiVFMyU4MSVBMSVFNSU5MCU5MSVFMyU4MSU4QiVFMyU4MSU4NiVFRiVCQyU4OGZsZXhib3glRTMlODMlOTAlRTMlODIlQjAlRTMlODElQkUlRTMlODElQTglRTMlODIlODElRUYlQkMlODkmdHh0LWFsaWduPWxlZnQlMkN0b3AmdHh0LWNvbG9yPSUyMzFFMjEyMSZ0eHQtZm9udD1IaXJhZ2lubyUyMFNhbnMlMjBXNiZ0eHQtc2l6ZT01NiZ0eHQtcGFkPTAmcz1jZTkyYWVhN2U2ZmE3NmI5ZDVhZTg2NGJkMWY2MjgyYg&amp;amp;mark-x=120&amp;amp;mark-y=112&amp;amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDBoYXNocm9jayZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTM2JnR4dC1wYWQ9MCZzPTc1ZmFlNGI3M2JlZTJjODgxOTMyMDU0ZDg3OTIyYTk0&amp;amp;blend-x=242&amp;amp;blend-y=480&amp;amp;blend-w=838&amp;amp;blend-h=46&amp;amp;blend-fit=crop&amp;amp;blend-crop=left%2Cbottom&amp;amp;blend-mode=normal&amp;amp;s=f22d701d1b43ee974162b8549978e775" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;flexboxのバグに立ち向かう（flexboxバグまとめ） - Qiita&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;flexbox使ってますか？バグつらいですね。必死に組んだレイアウトがIE11で崩れる様を見て、膝から崩れ落ちたことは何度もあります。 Solved by Flexboxの作者でもある、philipwaltonさんのflexbugsという素晴らしいflexboxのバグまと...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;qiita.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;今回はこのページのこの項目に類似するものだったと思われます（多分）。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://qiita.com/hashrock/items/189db03021b0f565ae27#1-%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0%E6%BD%B0%E3%82%8C%E3%82%8B%E5%95%8F%E9%A1%8Csafari"&gt;アイテム潰れる問題（Safari）&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;flex&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#f92672"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;↓&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;flex&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#f92672"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;auto&lt;/span&gt;&lt;span style="color:#f92672"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とすることで修正できました。&lt;/p&gt;</description></item><item><title>Hugoの脚注の戻るリンクのテキストを変更する</title><link>https://blog.piyo.tech/posts/2018-11-01-hugo-footnote-return-link/</link><pubDate>Thu, 01 Nov 2018 06:56:13 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-11-01-hugo-footnote-return-link/</guid><description>&lt;p&gt;脚注を使う方法を書いたものの、&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-10-31-hugo-footnote/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/r0owED5cBmCrD0wSbGkZkndJpmBW1SzYJPnfeb4w6XtcRfmmAr7IEYeo2nsjt3cHb81HlpByTaF4-1_UIXqJrWCfj_m-EaPaoYEszOlNg5qSIgQPbKBiyLQVgylgohhqzlss39qtNC7C6PzmxN0t6i0tAlfN858y1NXR-p9zoGsNDD_ESSfy5xrMOqAyWcav-aqnKjggx4xOnbxK0zA7qw8zVdqztuAfysiwKZI1r39UZ13ina1SjA_TEeC3zdQ132HcK4UuGSyLFmB0W662oCOyZaCz4yaTVN4tcXQm8aGsNn1nyyp7S0MQiJk2Oy-zFHcwh4WAojtUMX9HJa9T_C34B6LNPrgoavxsVumFk76ZmCVguxzLstJ1GUg61u61j1f3g_Yd3f83cTz64mc5Tg3dn4EFrgrBRQ0ZudYx99jZDTC2vYPvlZBTxWzjkWNo0AFEwO2IcZtRf31y07Jqrp5LtXwAayPNEO138CoeS7Bhc88Llw3SM76R2KYu-gbVnbljhq1xYI_bgTT_zNNl561znfF96T9wX8bwfVYEziO8i5iVIK5vUl4l1d_JCi_9Ydy-bK8ooczLhq9hWaw0czTbT8X36HjU8NmfZLDrvZC7JaBhaki5JeMjvQEw0BlchpNVno0IHoZyEe2vv59ZJpu-_agRSarUKA=w1000-h667-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Hugoで脚注（footnote）を使用する方法 - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;脚注はHugoで使えないと勝手に思っていましたが、ちゃんと使えました。 1 たまに本題からそれたことを補足で書きたくなるから、そういうときに使いたかったんでした。 Hugoの脚注の仕組み 2 こういう文章を書くと、 あいうえお[^a]かきくけこ[^b][^b]: か行だよ[^a]: あ行だよ 次のようにレンダリングされます。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;脚注に飛んでまた戻るときのリンクのテキストが&lt;code&gt;[return]&lt;/code&gt;となっていて嫌な感じだったので直す方法を調べました。&lt;/p&gt;
&lt;p&gt;Markdownを処理するBlackfriday側のオプションなのかと思っていましたが、HugoではHugoのオプションとして&lt;code&gt;config.toml&lt;/code&gt;に書くことがわかりました。&lt;/p&gt;
&lt;p&gt;このドキュメントの&lt;code&gt;footnoteReturnLinkContents&lt;/code&gt;の項目がそれにあたります。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://gohugo.io/configuration/all/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://gohugo.io/opengraph/gohugoio-card-base-1_hu_1f56857900484a40.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;All settings&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;The complete list of Hugo configuration settings.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://gohugo.io/favicon-32x32.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;gohugo.io&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;config.toml&lt;/code&gt;のトップレベルに書くと有効になります。&lt;/p&gt;
&lt;p&gt;僕は矢印を使ってみました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;footnoteReturnLinkContents&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;↩&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Hugoで脚注（footnote）を使用する方法</title><link>https://blog.piyo.tech/posts/2018-10-31-hugo-footnote/</link><pubDate>Wed, 31 Oct 2018 06:33:29 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-31-hugo-footnote/</guid><description>&lt;p&gt;脚注はHugoで使えないと勝手に思っていましたが、ちゃんと使えました。&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;たまに本題からそれたことを補足で書きたくなるから、そういうときに使いたかったんでした。&lt;/p&gt;
&lt;h1 id="hugoの脚注の仕組み"&gt;Hugoの脚注の仕組み&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/h1&gt;
&lt;p&gt;こういう文章を書くと、&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;あいうえお[^a]
かきくけこ[^b]
[^b]: か行だよ
[^a]: あ行だよ
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;次のようにレンダリングされます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/lrG4MHgkw6BpnXfZJl084e-rmQpwDPpHVO4-rQFEjRTilvztTFM0d532hY0OEz33vGJjrcbzsPrBwWd9Uq2qpxNohHE0uAqgetai2losnL4ioU4oNcNhApYZmh01Nym0t8tqlaJy6aFv80xgItkxdgh_NvGUbZk0nUfS_qTN88T_Qn4j-gjb2KKzRZua47HwRTF_eGzkjnYowMra2xQpBk0ghWKdjVksrXpD6FJStiHJV2h4FU_Vo7hQYoCmIZRn332QJonzm3mE-uaxNIPVEcx5iNojDZkSguknfUOogM7y-7BFbg896ASC6zEMZD5i-m1iS8xXppM5TLmOxoeGTpPTSo8ImIibNT8hOj82_E7Sa1-VcjCWhuI26gc8TT52hMC2UVv4dmrMqJNocFBDtXA-of4VJvpw4vQOA6YpdIpbyEkq3MdJEzvxvD_WMcrobjaaw8WLyI6eEkgkTDtQ4gi230vN5jXIMfsOKoNDtAhCycSuF74dSG-n8VzqQH5FOpRDNtCO5XnLd8HJWyT_TMHGQfEqm7zUyzekB0vAIpUJcqxwwFS1DQpCRw7qoRaE5ivEZA1H_ae9M2r2Kt5Qma5VcmYw8FDiF7y96FOXWT3ZuCKdE4QvaqtWz6ljuJUT0EDMMSxqZWIxnwP5Fu7GC0f59AiOXdmzUuwMzzHGJOmc54pQUoeCcbJfMuknQtr84sMs9J3Ls9fsYKrAM6k=w502-h470-no"&gt;&lt;img src="https://lh3.googleusercontent.com/lrG4MHgkw6BpnXfZJl084e-rmQpwDPpHVO4-rQFEjRTilvztTFM0d532hY0OEz33vGJjrcbzsPrBwWd9Uq2qpxNohHE0uAqgetai2losnL4ioU4oNcNhApYZmh01Nym0t8tqlaJy6aFv80xgItkxdgh_NvGUbZk0nUfS_qTN88T_Qn4j-gjb2KKzRZua47HwRTF_eGzkjnYowMra2xQpBk0ghWKdjVksrXpD6FJStiHJV2h4FU_Vo7hQYoCmIZRn332QJonzm3mE-uaxNIPVEcx5iNojDZkSguknfUOogM7y-7BFbg896ASC6zEMZD5i-m1iS8xXppM5TLmOxoeGTpPTSo8ImIibNT8hOj82_E7Sa1-VcjCWhuI26gc8TT52hMC2UVv4dmrMqJNocFBDtXA-of4VJvpw4vQOA6YpdIpbyEkq3MdJEzvxvD_WMcrobjaaw8WLyI6eEkgkTDtQ4gi230vN5jXIMfsOKoNDtAhCycSuF74dSG-n8VzqQH5FOpRDNtCO5XnLd8HJWyT_TMHGQfEqm7zUyzekB0vAIpUJcqxwwFS1DQpCRw7qoRaE5ivEZA1H_ae9M2r2Kt5Qma5VcmYw8FDiF7y96FOXWT3ZuCKdE4QvaqtWz6ljuJUT0EDMMSxqZWIxnwP5Fu7GC0f59AiOXdmzUuwMzzHGJOmc54pQUoeCcbJfMuknQtr84sMs9J3Ls9fsYKrAM6k=w502-h470-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;脚注を対応付けるラベルは数字の連番である必要はなく、脚注の指定箇所と説明の箇所で対応したラベルがあればOKのようです。&lt;/p&gt;
&lt;p&gt;また、脚注の説明を書く場所と順番は特に重要ではなく、脚注指定箇所が文中に登場した順で本文末尾に挿入されるようです。&lt;/p&gt;
&lt;p&gt;こう書いても同じ結果になります。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;あいうえお[^a]
[^a]: あ行だよ
かきくけこ[^b]
[^b]: か行だよ
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;個人的には末尾にまとめて書いておいたほうが編集しやすくて良さそう。&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;脚注、こういうやつ。&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;Markdown全般がそうなのか、Hugo（Blackfriday）だけがそうなのかよくわかってないですが。&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>CodeSandboxっていうオンラインのJS環境がかなり強力だった</title><link>https://blog.piyo.tech/posts/2018-10-30-codesandbox-online-editor/</link><pubDate>Tue, 30 Oct 2018 06:40:21 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-30-codesandbox-online-editor/</guid><description>&lt;p&gt;VeeValidateを紹介するときに、CodePenというサービスを使ってサンプルコードを紹介しました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-10-28-vuejs-vee-validate/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/-05wdwcG65pz1bU75_pMTPs78iundt_k8bbJZFxjaRXeROIc0JKiO_ZUDKCXMuvwAaLRCztkE-q_yN_hisyTPA-E9gD537_oHmEDYbnEalXzalYfD4pu1LywkudgGIqD1R8EzdaW07fVABOTwVcHOmDs-GZT6JXGkIgzH4ZTYXkjC1E6xSRq1U90lB_ywwyj2MfYIef2lFEns_dHpX29x_VZrkVoC-r6cAe6CwwfLasozt4L5HtUGGHxrbFt41hAdDmeWFPzcWUfAPatKNaiT9ZbSBs9lNnnYoh-70AWYVt4n4TWkOMjtA6h71AiRl_HZp4HoSaybfBDANQ0vlPu4h2vqSrNZTgyqVIgWS-E8Xe87dUCyPbPu5ARVAOjGJjB-vgx79EAAacu2WLEQGhRDE_qjj0CghmJJlMPQVimDsSF34EzCQ5ykZkNtC8GAM8C-Q6xGvzCGjrUDbTvPAN2mjp9Z4OjNiFpuKTOaNe8w1wInSFRrSded-yspgmJ0ek4nSAaSYL0xIM_SKN2FnRfhSoa2Qs7fkiLSC6eZ6jqJtmaNATF_OwBsNQaGLWGb9iivddKYeWka2ZvHsJw-KMBWz3ing4gpv5A2b08Z5xr6xSe8hwE6wmv2icEp3gNW2CMClo7gSky4Xm31py7iLlc83LvPCciT-K9Ro4sT49aYdaSKXkBUBhiW47iOg=w1200-h500-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Vue.jsでのフォームバリデーションにVeeValidateを使ってみる - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;ちょこちょこVue.jsを使ってるんですが、まだ手に馴染みません。まだまだ馴染まない理由の1つにフォームがあります。 Railsをメインに使う生活をしているので、 form_for がないとフォームが書けません。というか、 simple_form gemばかり使っているのでさらになまっていて、たとえば bootstrap のフォームがどんな構造なのかを忘れているので、すごく手間がかかってしまいます。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;他にもJSFiddleやJSBinなど類似のサービスがいくつかあるのは知ってしましたが、Vueのサンプルを書くときにPreprocessorを選択したり、ライブラリをCDNから検索して簡単に追加したりといい感じだったのでCodePenを使ったんですよね。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/30tSEuThEEV7lhjEFVW2mHktPCd2gXB4mQPpbwJ4ghmDVsMyzPQQ_3mhyz0UXgjU6w38byBZJMjJ5yxeG9IyGiM166_wr_A4fwM_x0TrBeJ5N_S-G8qf91DzvbKfeKI3M3rzKztnWIzsZv-c3qDgiA9x048qMbG0tE0tBVwgjQmMPafoSogPCGTYFq2Z8JQ31Qi_qmASiZT9gIzOsyiaFqG97fxSWrh3oaeBxhpHGqXbYRYUnK5AhjDBY7K-Lmqmr40OiU4cpMgrCAHB5ZrOZuO0yyCjxnMIKsB5i_U3vFazdDWACqsPA-HV-asMxAUTkAAoGQO2QYcxU_lWPAJ9VIpsyOwn-kC9nCGaxwrBk56OWro4HLl7SMNH4YuriCVkndojJP92ENUQduak2c-LK5dvhzvd_NCDlgV9HnCVIrBXxB2af1Ff618_XNL3Rin2Po44ELvZ8e61luuJc5Ot-j82RD00aGbaDslSxysgemhLhHhhy2tegGPAiM_FQ7kLa0yNq3wsM7R_hluGS-6tymuhA02hPSTtLhPxWdIEwDSULzv9Dx2Qx9XGkChTkchv3Yodkf-UMkzTU3SCF3ZOZGtTBK662C5I6V7b8ka5fUgulox9xRAohqkTAmwmNSIy9gPGrxA9NJIRUyLCI1dJTDpBVWaC7tycQCWUPEgckvAmQWfaYO-JRHT49Nlx4xQWVFSDNYQldqJH_4DHiws=w1064-h718-no"&gt;&lt;img src="https://lh3.googleusercontent.com/30tSEuThEEV7lhjEFVW2mHktPCd2gXB4mQPpbwJ4ghmDVsMyzPQQ_3mhyz0UXgjU6w38byBZJMjJ5yxeG9IyGiM166_wr_A4fwM_x0TrBeJ5N_S-G8qf91DzvbKfeKI3M3rzKztnWIzsZv-c3qDgiA9x048qMbG0tE0tBVwgjQmMPafoSogPCGTYFq2Z8JQ31Qi_qmASiZT9gIzOsyiaFqG97fxSWrh3oaeBxhpHGqXbYRYUnK5AhjDBY7K-Lmqmr40OiU4cpMgrCAHB5ZrOZuO0yyCjxnMIKsB5i_U3vFazdDWACqsPA-HV-asMxAUTkAAoGQO2QYcxU_lWPAJ9VIpsyOwn-kC9nCGaxwrBk56OWro4HLl7SMNH4YuriCVkndojJP92ENUQduak2c-LK5dvhzvd_NCDlgV9HnCVIrBXxB2af1Ff618_XNL3Rin2Po44ELvZ8e61luuJc5Ot-j82RD00aGbaDslSxysgemhLhHhhy2tegGPAiM_FQ7kLa0yNq3wsM7R_hluGS-6tymuhA02hPSTtLhPxWdIEwDSULzv9Dx2Qx9XGkChTkchv3Yodkf-UMkzTU3SCF3ZOZGtTBK662C5I6V7b8ka5fUgulox9xRAohqkTAmwmNSIy9gPGrxA9NJIRUyLCI1dJTDpBVWaC7tycQCWUPEgckvAmQWfaYO-JRHT49Nlx4xQWVFSDNYQldqJH_4DHiws=w1064-h718-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="codesandbox"&gt;CodeSandbox&lt;/h1&gt;
&lt;p&gt;で、ここから本題なんですが、VeeValidateのExampleが用意されていたCodeSandboxというオンラインエディターサービスが非常に強力そうでした。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://codesandbox.io" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://codesandbox.io/new/images/og.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;CodeSandbox: Instant Cloud Development Environments&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;CodeSandbox is a cloud development platform that empowers developers to code, collaborate and ship projects of any size from any device in record time.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://codesandbox.io/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;codesandbox.io&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;JSFiddleやCodePenがPlayGroundなら、CodeSandboxはJavaScriptの実行環境付のIDEという雰囲気。画面はこんな感じです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/xsN0wfkITXndJUvurhn4EXfhXHMzZYfILqWY2YnSQ9UiXL2nBu6p9k9fllcKVmI7SYN3Rw5nuCCcfpIJmO9eZqMahJzINVaaHeCLeh72uedzWhNjvfTPl12dWaHSFhWKqyU8685zOe4uwubvQ1T3qaZfF1IF-xmi1sbFtydjcXAK9fCdKd1LCMrjpVjFHEj5lLycGa-Q7vNknpaRGqpgU_eXXynM3CwCy-G4NKIQ4XQbt-KHPClcY6jlhFgn4c_h9-K0O0v5M7VSpqEjmtKslJHvh_h58eikuH5XrD6Lyvh69-s2b3i5pPntY8T1Xa-JvlyKYHh8YWKK_86NUB8bFCe3w5uy8U9MEPOHWdYAGf1hyP-U5EGFfn4kD3nHhKpQLIKmbuHMdoygJ6-bgi6Dr2odvUqdkAAMDwvkJHMrudd-QWESys3m8v_5J89KZ2GmtOnKtz7jq8zisW3FUdDRqNcR7Y5kwtFK8vcTLUm9cHIGJNhh8wK_dgftReITvGyF8F5siJtk5tsXbWH7AL-WWmH_Xoq5qbulHsSmiZrbRz6vDEG4n5_7NkEYD4weOSUfwUtIPJzengRMZPoiIESSluEuAvP75zn4GGhEtOY1-aCytuv4tvTUQQJO4n_l_PlZBkkPw_1GdV15i3APQ2qVYvbCbz24HydQghiQmkOpP7Y7U5L5mMjR6kiG8KjozQMgBXbdV-6fMOnUEOX74cE=w2640-h1336-no"&gt;&lt;img src="https://lh3.googleusercontent.com/xsN0wfkITXndJUvurhn4EXfhXHMzZYfILqWY2YnSQ9UiXL2nBu6p9k9fllcKVmI7SYN3Rw5nuCCcfpIJmO9eZqMahJzINVaaHeCLeh72uedzWhNjvfTPl12dWaHSFhWKqyU8685zOe4uwubvQ1T3qaZfF1IF-xmi1sbFtydjcXAK9fCdKd1LCMrjpVjFHEj5lLycGa-Q7vNknpaRGqpgU_eXXynM3CwCy-G4NKIQ4XQbt-KHPClcY6jlhFgn4c_h9-K0O0v5M7VSpqEjmtKslJHvh_h58eikuH5XrD6Lyvh69-s2b3i5pPntY8T1Xa-JvlyKYHh8YWKK_86NUB8bFCe3w5uy8U9MEPOHWdYAGf1hyP-U5EGFfn4kD3nHhKpQLIKmbuHMdoygJ6-bgi6Dr2odvUqdkAAMDwvkJHMrudd-QWESys3m8v_5J89KZ2GmtOnKtz7jq8zisW3FUdDRqNcR7Y5kwtFK8vcTLUm9cHIGJNhh8wK_dgftReITvGyF8F5siJtk5tsXbWH7AL-WWmH_Xoq5qbulHsSmiZrbRz6vDEG4n5_7NkEYD4weOSUfwUtIPJzengRMZPoiIESSluEuAvP75zn4GGhEtOY1-aCytuv4tvTUQQJO4n_l_PlZBkkPw_1GdV15i3APQ2qVYvbCbz24HydQghiQmkOpP7Y7U5L5mMjR6kiG8KjozQMgBXbdV-6fMOnUEOX74cE=w2640-h1336-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;（ちなみにこれはvueのExampleをForkした状態です。）&lt;/p&gt;
&lt;p&gt;左側にプロジェクトツリーがあって、真ん中にエディターがあって、右側にはプレビューというか実行中のサイトをプレビューするための画面があります。&lt;/p&gt;
&lt;h2 id="プロジェクトツリー"&gt;プロジェクトツリー&lt;/h2&gt;
&lt;p&gt;「File Editor」と呼ばれているみたいです。&lt;/p&gt;
&lt;p&gt;ここではファイルの追加、移動、削除ができたり、依存ライブラリを追加したりできます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/1s4VJ4dekQgl0TTbnhKiEt7HFOAgfu00H9kCwZt5CtSWnBy2z02htzwfAsV5kASK0Q2u8EgE04FepuD1965jKe58IsYuaPCWLiJfYBG5M_HPJn7RfaR8L8uZuXkJFEIXZcYkt9ShlBMscrRAaQRTeQbtPxwxPqYtQ02_ppdWgnnp7hF-J7tw8MGcVUjr49mRlL8V4SGleuuK8npSwkswjao3zzOmA0hd90UHx6OqLdOcBOCc6zFTyYCHhkO_BsXJKnPTc43vkQQt8oeTd_7OEyBN70JLhoMp5D5XlYtq3IDQ6l8NAmMu8QkmXm4cuN3QTDmm29ih0cSs1SZBA6Cg5Dli582aFl1Sqq-SfDfRZewNcqK8SDfTgPFIN-hqcBYCw2FnxP9rywCv9XfbZrau32GNMaqp3fv_Q11NPz1GJHGsS1UeGLTGSth042RL9RVMro-TtnIdsQfyQ-DEsUymn-3abq_hh7CyceqEVkcEKQOaOnUO6yWB4_g-t9YjVDsePPlXbJqyBIOZ0Bs56uHRyCZ8NPOBzfyDhiVppAt4vB_PcXwotvwfx2pLsNy7C1BHR4aG-GNQyndMCz8YA4jb-Xh110iILmyq1bB4hPK46Tl8oGl4-uCEpYY6wUv3vDw7VsF8yOSN8UFc1PYUKkkqB_p1TktuOKw_fUi1-PguMsVqTA5QsJP7J_NmSbojpnU1S_u4i_9OvDJAZmE453Y=w652-h1290-no"&gt;&lt;img src="https://lh3.googleusercontent.com/1s4VJ4dekQgl0TTbnhKiEt7HFOAgfu00H9kCwZt5CtSWnBy2z02htzwfAsV5kASK0Q2u8EgE04FepuD1965jKe58IsYuaPCWLiJfYBG5M_HPJn7RfaR8L8uZuXkJFEIXZcYkt9ShlBMscrRAaQRTeQbtPxwxPqYtQ02_ppdWgnnp7hF-J7tw8MGcVUjr49mRlL8V4SGleuuK8npSwkswjao3zzOmA0hd90UHx6OqLdOcBOCc6zFTyYCHhkO_BsXJKnPTc43vkQQt8oeTd_7OEyBN70JLhoMp5D5XlYtq3IDQ6l8NAmMu8QkmXm4cuN3QTDmm29ih0cSs1SZBA6Cg5Dli582aFl1Sqq-SfDfRZewNcqK8SDfTgPFIN-hqcBYCw2FnxP9rywCv9XfbZrau32GNMaqp3fv_Q11NPz1GJHGsS1UeGLTGSth042RL9RVMro-TtnIdsQfyQ-DEsUymn-3abq_hh7CyceqEVkcEKQOaOnUO6yWB4_g-t9YjVDsePPlXbJqyBIOZ0Bs56uHRyCZ8NPOBzfyDhiVppAt4vB_PcXwotvwfx2pLsNy7C1BHR4aG-GNQyndMCz8YA4jb-Xh110iILmyq1bB4hPK46Tl8oGl4-uCEpYY6wUv3vDw7VsF8yOSN8UFc1PYUKkkqB_p1TktuOKw_fUi1-PguMsVqTA5QsJP7J_NmSbojpnU1S_u4i_9OvDJAZmE453Y=w652-h1290-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;依存関係は「Add Dependency」ボタンから、インクリメンタルに検索して追加できます。すごい。よくできてる。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/mLZIP52SJ_7ipbLZZfG0dCdcrWIHf1XcbVSfp8-olgK-KT4H20g_eL3gFUxbdtMJKIKpSXVs5R1Gss_JVR-LFcL5ryEqN1KDGLjI-MoyiCtG3dqpxPnrFTsBm9YZfC75y4IRT25VpFNzV08spp1NvdDxhv1AWR-TyzfvmnCBD8QvtsSF0CCSGv1N1rAm2uILidttJfHF0M6oeoaECx9z7SHKic4jCsGUaaK4VS2KU7FrqxKr8p0Nl5f_zP5BEe8yB_6t-6CtphUkmDXsK6iG5Ahnt3YyjCsS90cke9ZBsnBDPDzetb5lAzx5N7G2sfiDzuDrwtjUHMzP73J38qCLicIdKpl9L1oBpfVLxjtFBXu7b0-hRiyP4R0Odqm5tLScqYcsk5iKkXFZ1fzJTMhnVAO03ToPdLjkPZYxnXzJ3lSZlj2koqTq9t2EGQSf17M22ndx3KfTNF0g4RV1jBE2zGg-aBtzhxxfa6DOXtNDcpX2xz7zxt1VL33N2l7mZVEdgZU5uW0kfg7POrfePFDqJ67WZhO9MHnosXO5VL6HY5sm2_U_unb1LfzcW1z9U2g8LdUVcH9Cu7ydeokigXoMvCWnLH6v82M-I_jyLPMiHEchrGaf10Tk_37J5GAh3ty-G8cfReWr8GbaxuyGzK5K05vjUT5tSq6hCjfrXWoOZqPlE1pzw6Zglpp-nrS5G89cWFwTlz9rtf5HNSMUbCE=w1246-h1344-no"&gt;&lt;img src="https://lh3.googleusercontent.com/mLZIP52SJ_7ipbLZZfG0dCdcrWIHf1XcbVSfp8-olgK-KT4H20g_eL3gFUxbdtMJKIKpSXVs5R1Gss_JVR-LFcL5ryEqN1KDGLjI-MoyiCtG3dqpxPnrFTsBm9YZfC75y4IRT25VpFNzV08spp1NvdDxhv1AWR-TyzfvmnCBD8QvtsSF0CCSGv1N1rAm2uILidttJfHF0M6oeoaECx9z7SHKic4jCsGUaaK4VS2KU7FrqxKr8p0Nl5f_zP5BEe8yB_6t-6CtphUkmDXsK6iG5Ahnt3YyjCsS90cke9ZBsnBDPDzetb5lAzx5N7G2sfiDzuDrwtjUHMzP73J38qCLicIdKpl9L1oBpfVLxjtFBXu7b0-hRiyP4R0Odqm5tLScqYcsk5iKkXFZ1fzJTMhnVAO03ToPdLjkPZYxnXzJ3lSZlj2koqTq9t2EGQSf17M22ndx3KfTNF0g4RV1jBE2zGg-aBtzhxxfa6DOXtNDcpX2xz7zxt1VL33N2l7mZVEdgZU5uW0kfg7POrfePFDqJ67WZhO9MHnosXO5VL6HY5sm2_U_unb1LfzcW1z9U2g8LdUVcH9Cu7ydeokigXoMvCWnLH6v82M-I_jyLPMiHEchrGaf10Tk_37J5GAh3ty-G8cfReWr8GbaxuyGzK5K05vjUT5tSq6hCjfrXWoOZqPlE1pzw6Zglpp-nrS5G89cWFwTlz9rtf5HNSMUbCE=w1246-h1344-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="設定ファイル類"&gt;設定ファイル類&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;package.json&lt;/code&gt;とか&lt;code&gt;.babelrc&lt;/code&gt;とかを確認したりいじったりできるようです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/_4T75vNdOmgWaqhl_45MX6CE8W1NZ-JZSMkml2dYM4iAahMtgVSIM6zVKdygfOkL_r8uKldL9dJQbFzOFDup_Pfy0nVTVAfdWrp5r4Pi7XposFs_xXGOpbj2bswhSwQjy9DSIfT8rfm4p3FVfG1R5bSeEpaMeWxrBj2qeU1UcuGrDvuh8sIeAausC-4qdfFfWmyhYGylKPdL-rfK4atvMMQzbtFNIKMWoY8J17hKME8BuUPe-h9Ejm4dRX2RKzn-2laolqvqzO-yrufpef9PLGLHZiuXbo0LgvEotWwdDFLfrhs0_OHDyV1LO38yZMVgWbhRbarprELzDQVDusNBd21igziszFf3i7fn5R7fZFWLHTnW7WSPZ5gR-RW1-DA0Ih6M9f-7d6hUIVCnbhMfZ6KQ2cFX7BFsWlUZ70RGvkXze8mGFGo4PXoEHoLxHmyu_beQzF1wDhEmCVlrhIHTRQc0n-WDPn-6nNelpBucN5ckoUC4z4nTToMyqBEqnWbi050eXXeZzFRbNXYDT799KYwxUxCmAw9moo_DdA1o_C0mxdmlSBSMlsFka2CM_WI5JsAvqGOB8sULaKCo2DQfNmRNI87VNPdzx4QiKkY9GFq61Zgp8XjJ8nE5P8J7625T4UQTFfdCl0s5BMlHWbQjSBg_qW742Phz_gAzhTv1sQSheLKM7W4vxhKe2EA8apJiRQp4h0Sau-UNbgMSLrk=w1572-h1040-no"&gt;&lt;img src="https://lh3.googleusercontent.com/_4T75vNdOmgWaqhl_45MX6CE8W1NZ-JZSMkml2dYM4iAahMtgVSIM6zVKdygfOkL_r8uKldL9dJQbFzOFDup_Pfy0nVTVAfdWrp5r4Pi7XposFs_xXGOpbj2bswhSwQjy9DSIfT8rfm4p3FVfG1R5bSeEpaMeWxrBj2qeU1UcuGrDvuh8sIeAausC-4qdfFfWmyhYGylKPdL-rfK4atvMMQzbtFNIKMWoY8J17hKME8BuUPe-h9Ejm4dRX2RKzn-2laolqvqzO-yrufpef9PLGLHZiuXbo0LgvEotWwdDFLfrhs0_OHDyV1LO38yZMVgWbhRbarprELzDQVDusNBd21igziszFf3i7fn5R7fZFWLHTnW7WSPZ5gR-RW1-DA0Ih6M9f-7d6hUIVCnbhMfZ6KQ2cFX7BFsWlUZ70RGvkXze8mGFGo4PXoEHoLxHmyu_beQzF1wDhEmCVlrhIHTRQc0n-WDPn-6nNelpBucN5ckoUC4z4nTToMyqBEqnWbi050eXXeZzFRbNXYDT799KYwxUxCmAw9moo_DdA1o_C0mxdmlSBSMlsFka2CM_WI5JsAvqGOB8sULaKCo2DQfNmRNI87VNPdzx4QiKkY9GFq61Zgp8XjJ8nE5P8J7625T4UQTFfdCl0s5BMlHWbQjSBg_qW742Phz_gAzhTv1sQSheLKM7W4vxhKe2EA8apJiRQp4h0Sau-UNbgMSLrk=w1572-h1040-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="エディター部"&gt;エディター部&lt;/h2&gt;
&lt;p&gt;普通のエディターですが&lt;code&gt;vue&lt;/code&gt;ファイルまで扱えます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/zlJCZeoemwkEgM2nCnBym6Q-kdKBA0bXcRKC7X3SRzwgwtsN9JEiplCmpBv2bF5pKulv5Y84YRLLzCPYM_izFJFm2QNssY88AaIh5piodDZYP9iwjQwlYzcZzl0lTaipM40vFn9VAr-_q5bOMSgXvnU5b6fOhKSheXz1rQ920GRC7dHsHN5DLy-3ZwQmoXi6hO-qvt3FReQuKsZFTOnnCqWqeoaNuu37fsCPul6D20IQaEnrRwNOmIhNqM8d_rC0TAhhAmmgwty8dnwj2rsu2VZCfHURpEKutyp-TYR1TQe7kKJg1Ch7lKUfzRCU2-6cy8LqvOmfn6sVR3YTbWrtBhgqz8Zqn1hWys4qB6H3PepJ4w_A0w2e61v_JW0uavcpibvohsp6-04RtPIpwkfqQeLWnTjZgRjeOktEIXSFL__0POiMnVi1REmUYRp8Wpf18vM956pAjp_vQRDkExDx4jeb33_AWrHbeICXJpKGD5krzy3VcKfxpd7PV8IAwoATL9GPlpptpOt7H0EsK4Kv8bL46YPhMd6sQibhmyRDq3NfgLlHiGkpLfGOEWyUIQJRnQZDWyJdnXLHVyOHp97stW8wbLjl-t6gQ5zs1rh2Sh84vnnfxgJQWP15yokkxPV4uqA6k7zLRIuu6KcGdr4Wv8G7oveyaNgfKYIYhopRkRhbJ2YtkuKGhsAuO4wmPPTXOn3fxMt--bwbUoyzgzI=w1204-h1342-no"&gt;&lt;img src="https://lh3.googleusercontent.com/zlJCZeoemwkEgM2nCnBym6Q-kdKBA0bXcRKC7X3SRzwgwtsN9JEiplCmpBv2bF5pKulv5Y84YRLLzCPYM_izFJFm2QNssY88AaIh5piodDZYP9iwjQwlYzcZzl0lTaipM40vFn9VAr-_q5bOMSgXvnU5b6fOhKSheXz1rQ920GRC7dHsHN5DLy-3ZwQmoXi6hO-qvt3FReQuKsZFTOnnCqWqeoaNuu37fsCPul6D20IQaEnrRwNOmIhNqM8d_rC0TAhhAmmgwty8dnwj2rsu2VZCfHURpEKutyp-TYR1TQe7kKJg1Ch7lKUfzRCU2-6cy8LqvOmfn6sVR3YTbWrtBhgqz8Zqn1hWys4qB6H3PepJ4w_A0w2e61v_JW0uavcpibvohsp6-04RtPIpwkfqQeLWnTjZgRjeOktEIXSFL__0POiMnVi1REmUYRp8Wpf18vM956pAjp_vQRDkExDx4jeb33_AWrHbeICXJpKGD5krzy3VcKfxpd7PV8IAwoATL9GPlpptpOt7H0EsK4Kv8bL46YPhMd6sQibhmyRDq3NfgLlHiGkpLfGOEWyUIQJRnQZDWyJdnXLHVyOHp97stW8wbLjl-t6gQ5zs1rh2Sh84vnnfxgJQWP15yokkxPV4uqA6k7zLRIuu6KcGdr4Wv8G7oveyaNgfKYIYhopRkRhbJ2YtkuKGhsAuO4wmPPTXOn3fxMt--bwbUoyzgzI=w1204-h1342-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;入力補完もある程度効く模様。え、すごくない？&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/f-BvrrYk7_5vTVuvNnSeHX81a1O-3yjAMNuCe91RivjNrfLkgY6Q8cBSGBusuJk9opbF8E5WlUH-RGUHfiK65iISKTQcbgB_6PIcr4thAUgfEBILYHrRuQHp57dd7x3Z9eFPw2j0n1npDdEFeVvrVPLAOR9sj5pr-EKQpjtYEoddSmbI0VEWK5a2pLKxlC3ComJOZR3fE3MXBWYbqp0XjbuoEVc5TkD-CFGV2VO9wZYCP8ss86KXyt3K9BdQJCTvBV10xSSvTkv3IaO3t5FXy2kb88hR0YnZZHx-lKjwVZUunXW2FU6dJbYgLBHO4LeCtnYDu5MPHs0NIMD7N6xCv5KtsI3CBqztv8XiUsu-Lv-fnCrluISQzVglg7ABIo6EIl4Lr8xdHUfPP32BwAeA8uJEUH1BtwW1un7vnC-SfoPzUew4g6fgsb8uB8FFCFcvYtnVEOr1IHX_gq7-IPaeAWCY4Qb_CJf0LT2EtwMIUy5DdOihu2yrwO01tkEhybC5HC5vLq91qZzYfDY3l16mbGJ9P6OeqaSKuGPShfa1ORvAy_xMmlulVj7mdqLb9nITwJOHNiUDy6nvZuskynQufmafkCJ1-qU1PdJ40huBVFeohiezam--cVNyrIi2FAtbK97y5Rxe60jrm2qqINPqMU026mxtknb7tGQb4s4p0vnLn9TVhjcrrAnrD4TN70u3DgWBtDQQH2jMhQUvAUw=w624-h362-no"&gt;&lt;img src="https://lh3.googleusercontent.com/f-BvrrYk7_5vTVuvNnSeHX81a1O-3yjAMNuCe91RivjNrfLkgY6Q8cBSGBusuJk9opbF8E5WlUH-RGUHfiK65iISKTQcbgB_6PIcr4thAUgfEBILYHrRuQHp57dd7x3Z9eFPw2j0n1npDdEFeVvrVPLAOR9sj5pr-EKQpjtYEoddSmbI0VEWK5a2pLKxlC3ComJOZR3fE3MXBWYbqp0XjbuoEVc5TkD-CFGV2VO9wZYCP8ss86KXyt3K9BdQJCTvBV10xSSvTkv3IaO3t5FXy2kb88hR0YnZZHx-lKjwVZUunXW2FU6dJbYgLBHO4LeCtnYDu5MPHs0NIMD7N6xCv5KtsI3CBqztv8XiUsu-Lv-fnCrluISQzVglg7ABIo6EIl4Lr8xdHUfPP32BwAeA8uJEUH1BtwW1un7vnC-SfoPzUew4g6fgsb8uB8FFCFcvYtnVEOr1IHX_gq7-IPaeAWCY4Qb_CJf0LT2EtwMIUy5DdOihu2yrwO01tkEhybC5HC5vLq91qZzYfDY3l16mbGJ9P6OeqaSKuGPShfa1ORvAy_xMmlulVj7mdqLb9nITwJOHNiUDy6nvZuskynQufmafkCJ1-qU1PdJ40huBVFeohiezam--cVNyrIi2FAtbK97y5Rxe60jrm2qqINPqMU026mxtknb7tGQb4s4p0vnLn9TVhjcrrAnrD4TN70u3DgWBtDQQH2jMhQUvAUw=w624-h362-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="ブラウザ部分"&gt;ブラウザ部分&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;index.html&lt;/code&gt;を開いて実行結果を見ることができます。リロードが効くのでコードを編集するとリアルタイムに更新されていくし、コードが間違っていればエラーを出してくれます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/0t4g2C3EAjOfJL6qlJldhX5d0YRWO750yDRBOlLqpWOh4nkX1_pkppklCfRq5o77PNsWkN_x87_coF5mhebRrNziIi6WvYhihnUYz4VOqEgDGharJpC4on9btheth_oSRuwdvuKn73bhWd07l745U6iA4qVPrMGhiyieQtyNaTPjdCMSkvNXvH73O0l-S3S9l0D5fbGZZBrYsGrD2ry9U5LANw9B7QZ7rJexgJ5DdQH8Xur97Bk938q3tKOqxKLMXATIgqSxhSIFmDh88xKcQaZK0tTfS-96mTXfTAG4Yg4DeraDarQ2gGg_aecPLhIblFQxJbIqyshLvw3kVCjckoBlTNoPEUTuNDB6G73Tz87ITIWozSp-9KgUatlWn9JtS9DdslteAeQcg9Uevu2OHP95JVuPYSOVX8TkBNmozzh8Vh-1MTLTKiwmywCUe-nSkpgK_tHqM2FysudBYhOIGTUcpE5U0Eh92OOEo3HlNpnfpboOPbTHdKeFjq3pnek5f8-H0vDoiBxu8P90ZvgMqRkYBvqVWlsu622Zh31yOOyEk0oQZ4G2_jx89ZvTIjaRJVh_CcICKp3HWd_ReUcDi6jUog3ExxZqsxC_t00gw7YVKIYb6eXDRuY8jK-_g8mX2pVbs-UBumvKs4tyNaiIEXiKTVjspXFMUdOLb5zEErQdwv_InKgucRld3Ri8EGV2y7xwNM72kxgH50JRhUk=w858-h710-no"&gt;&lt;img src="https://lh3.googleusercontent.com/0t4g2C3EAjOfJL6qlJldhX5d0YRWO750yDRBOlLqpWOh4nkX1_pkppklCfRq5o77PNsWkN_x87_coF5mhebRrNziIi6WvYhihnUYz4VOqEgDGharJpC4on9btheth_oSRuwdvuKn73bhWd07l745U6iA4qVPrMGhiyieQtyNaTPjdCMSkvNXvH73O0l-S3S9l0D5fbGZZBrYsGrD2ry9U5LANw9B7QZ7rJexgJ5DdQH8Xur97Bk938q3tKOqxKLMXATIgqSxhSIFmDh88xKcQaZK0tTfS-96mTXfTAG4Yg4DeraDarQ2gGg_aecPLhIblFQxJbIqyshLvw3kVCjckoBlTNoPEUTuNDB6G73Tz87ITIWozSp-9KgUatlWn9JtS9DdslteAeQcg9Uevu2OHP95JVuPYSOVX8TkBNmozzh8Vh-1MTLTKiwmywCUe-nSkpgK_tHqM2FysudBYhOIGTUcpE5U0Eh92OOEo3HlNpnfpboOPbTHdKeFjq3pnek5f8-H0vDoiBxu8P90ZvgMqRkYBvqVWlsu622Zh31yOOyEk0oQZ4G2_jx89ZvTIjaRJVh_CcICKp3HWd_ReUcDi6jUog3ExxZqsxC_t00gw7YVKIYb6eXDRuY8jK-_g8mX2pVbs-UBumvKs4tyNaiIEXiKTVjspXFMUdOLb5zEErQdwv_InKgucRld3Ri8EGV2y7xwNM72kxgH50JRhUk=w858-h710-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;また、実行環境のURL&lt;code&gt;https://81oy51q9o8.codesandbox.io/&lt;/code&gt;は外部からも使えないこともないです。永続的に使える感じではなさそうに見えます。どうなのかな。ブラウザ変えて確認してみるみたいなときに便利かもしれません。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://81oy51q9o8.codesandbox.io/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;81oy51q9o8.codesandbox.io →&lt;/span&gt;&lt;span&gt;https://81oy51q9o8.codesandbox.io/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="埋め込み"&gt;埋め込み&lt;/h2&gt;
&lt;p&gt;埋め込んでみるとこんな感じになります。&lt;/p&gt;
&lt;iframe src="https://codesandbox.io/embed/81oy51q9o8" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"&gt;&lt;/iframe&gt;
&lt;p&gt;&lt;a href="https://codesandbox.io/s/81oy51q9o8"&gt;&lt;img src="https://codesandbox.io/static/img/play-codesandbox.svg" alt="Edit Vue Template"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="その他"&gt;その他&lt;/h2&gt;
&lt;p&gt;その他にもコンソールが下からにゅっとでてきたりとか、GitHubと連携できたりとか、すごいです。&lt;/p&gt;
&lt;p&gt;もしかしてCodePenとかと比べるのが間違ってて、Cloud9とかと比べたほうがいいのではないかもしれない。&lt;/p&gt;</description></item><item><title>Vue.jsでのフォームバリデーションにVeeValidateを使ってみる</title><link>https://blog.piyo.tech/posts/2018-10-28-vuejs-vee-validate/</link><pubDate>Sun, 28 Oct 2018 06:48:32 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-28-vuejs-vee-validate/</guid><description>&lt;p&gt;ちょこちょこVue.jsを使ってるんですが、まだ手に馴染みません。まだまだ馴染まない理由の1つにフォームがあります。&lt;/p&gt;
&lt;p&gt;Railsをメインに使う生活をしているので、&lt;code&gt;form_for&lt;/code&gt;がないとフォームが書けません。というか、&lt;code&gt;simple_form&lt;/code&gt; gemばかり使っているのでさらになまっていて、たとえば&lt;code&gt;bootstrap&lt;/code&gt;のフォームがどんな構造なのかを忘れているので、すごく手間がかかってしまいます。&lt;/p&gt;
&lt;p&gt;さて、フォームを組み立てたら次はValidationしたくなります。昔ながらなRailsアプリケーションではフォームの内容をいったんサーバーに送って、サーバーサイドでバリデーションを書けます。&lt;/p&gt;
&lt;p&gt;せっかくVue.js使うならクライアントサイドでもそれなりにやってしまったほうが良いですよね（ですよね？）。&lt;/p&gt;
&lt;p&gt;VeeValidateというVue.js用のバリデーションライブラリを見つけたので試しました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/logaretm/vee-validate" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://repository-images.githubusercontent.com/64519183/bb229680-19a0-11eb-9d6f-0ff1d615b046" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - logaretm/vee-validate: ✅ Painless Vue forms&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;✅ Painless Vue forms. Contribute to logaretm/vee-validate development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="veevalidate用サンプルアプリ"&gt;VeeValidate用サンプルアプリ&lt;/h1&gt;
&lt;p&gt;問い合わせフォームっぽいものを作りました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;メールアドレス&lt;/li&gt;
&lt;li&gt;タイトル&lt;/li&gt;
&lt;li&gt;本文&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;を入れてもらうフォームで、全項目必須、メールはフォーマットまで確認するということにしました。&lt;/p&gt;
&lt;h2 id="html"&gt;HTML&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;form&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;action&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;submit&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;prevent&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;validate&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;form-group&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;label&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;for&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&amp;gt;メールアドレス&amp;lt;/&lt;span style="color:#f92672"&gt;label&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;input&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;email&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;form-control&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;v-validate&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#39;required|email&amp;#39;&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;span&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text-danger&amp;#34;&lt;/span&gt;&amp;gt;{{ errors.first(&amp;#39;email&amp;#39;) }}&amp;lt;/&lt;span style="color:#f92672"&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;form-group&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;label&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;for&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&amp;gt;タイトル&amp;lt;/&lt;span style="color:#f92672"&gt;label&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;input&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;form-control&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;v-validate&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#39;required&amp;#39;&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;span&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text-danger&amp;#34;&lt;/span&gt;&amp;gt;{{ errors.first(&amp;#39;title&amp;#39;) }}&amp;lt;/&lt;span style="color:#f92672"&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;form-group&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;label&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;for&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&amp;gt;本文&amp;lt;/&lt;span style="color:#f92672"&gt;label&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;textarea&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rows&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;5&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;form-control&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;body&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;v-validate&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#39;required&amp;#39;&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;textarea&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;span&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text-danger&amp;#34;&lt;/span&gt;&amp;gt;{{ errors.first(&amp;#39;body&amp;#39;) }}&amp;lt;/&lt;span style="color:#f92672"&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;button&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;submit&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;btn btn-primary&amp;#34;&lt;/span&gt;&amp;gt;送信&amp;lt;/&lt;span style="color:#f92672"&gt;button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;form&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;見た目は↓↓な感じね。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/_0qokTsCoa-s8UkMe1XBCela_fLAk-UVzOtlFsXrcJulcsj678mtGnwmUsf1Yh2m1AGh3MVG33Y8TP2BleCEeqT695nOahl_GqS0RaenIHLS2YbLlFaV1ZD0DeD-0kwDaXaB3KKqyV_kWbkrfgKcc39b3AyeqR_FlQp9OfJjpV-xrNqhwX4LxdzPhODmzHAFMRTDzrpkrS-dHNXLPu-5TbKVWj6kfc92NIFtjU3bIxdOqqRTKSXQpY3WEhRUXzgwg0NPOA0aTw6e6_Xk6a3ykJY5SOS5SEqIy7lpHGWqtBSrw_ePnD-YEUo_4bRW8PdrKWwEp-9EBU8o1ezBqhLRtGqHPapz7v8WbSEXD8V2Lc1q_1MYkR1JqLe9QM0EnUOp0sFvYy2IEYB1bAiB6MnOoojM7QCB6Z4GGtWU2ICONC25JYSWo2zxdfJ5yWG9Vq9_3i2fnwr2kPMxXGDp6TzEDyOBSzZXp5NtDdlIilmpX4Qt4a4LpNglQzDAPa8zSjYjrepLrVheSOMcQa3BAoUZIlcDDBvncn4gLfBIGbGdew3WSOjCH5G42zwJ0_NbFWvCYue6GpZkx5tKA7gLa4PgLU90nNEEcLx4-OT70LBrbt6eT_BZf-636-o-neg4oWNnBV_3rMNRfSBEM1Ili_i9MPSX0FGYIr0h9D90QwbeTmj8HIqqy7i8erA7SkserHVtwpdMtDCkysttDKnrK9w=w1028-h854-no"&gt;&lt;img src="https://lh3.googleusercontent.com/_0qokTsCoa-s8UkMe1XBCela_fLAk-UVzOtlFsXrcJulcsj678mtGnwmUsf1Yh2m1AGh3MVG33Y8TP2BleCEeqT695nOahl_GqS0RaenIHLS2YbLlFaV1ZD0DeD-0kwDaXaB3KKqyV_kWbkrfgKcc39b3AyeqR_FlQp9OfJjpV-xrNqhwX4LxdzPhODmzHAFMRTDzrpkrS-dHNXLPu-5TbKVWj6kfc92NIFtjU3bIxdOqqRTKSXQpY3WEhRUXzgwg0NPOA0aTw6e6_Xk6a3ykJY5SOS5SEqIy7lpHGWqtBSrw_ePnD-YEUo_4bRW8PdrKWwEp-9EBU8o1ezBqhLRtGqHPapz7v8WbSEXD8V2Lc1q_1MYkR1JqLe9QM0EnUOp0sFvYy2IEYB1bAiB6MnOoojM7QCB6Z4GGtWU2ICONC25JYSWo2zxdfJ5yWG9Vq9_3i2fnwr2kPMxXGDp6TzEDyOBSzZXp5NtDdlIilmpX4Qt4a4LpNglQzDAPa8zSjYjrepLrVheSOMcQa3BAoUZIlcDDBvncn4gLfBIGbGdew3WSOjCH5G42zwJ0_NbFWvCYue6GpZkx5tKA7gLa4PgLU90nNEEcLx4-OT70LBrbt6eT_BZf-636-o-neg4oWNnBV_3rMNRfSBEM1Ili_i9MPSX0FGYIr0h9D90QwbeTmj8HIqqy7i8erA7SkserHVtwpdMtDCkysttDKnrK9w=w1028-h854-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="javascript"&gt;JavaScript&lt;/h2&gt;
&lt;p&gt;JavaScriptはあまり書くことがありません。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;VeeValidate&lt;/code&gt;自体の登録&lt;/li&gt;
&lt;li&gt;Vueインスタンスの生成&lt;/li&gt;
&lt;li&gt;バリデーション処理&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;うまくいったときだけ&lt;code&gt;alert&lt;/code&gt;が表示されます。実際のアプリケーションではサーバーにPOSTするなど必要な処理を実行することになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;use&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;VeeValidate&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#app&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;methods&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;validate&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;$validator&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;validateAll&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;valid!&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="veevalidateの使い方"&gt;VeeValidateの使い方&lt;/h2&gt;
&lt;p&gt;VeeValidateで重要なのことはこの2行を見れば大体わかると言えそうです。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;input name=&amp;#34;email&amp;#34; type=&amp;#34;text&amp;#34; class=&amp;#34;form-control&amp;#34; v-validate=&amp;#34;&amp;#39;required|email&amp;#39;&amp;#34; /&amp;gt;
&amp;lt;span class=&amp;#34;text-danger&amp;#34;&amp;gt;{{ errors.first(&amp;#39;email&amp;#39;) }}&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;1行目の&lt;code&gt;name=&lt;/code&gt;と&lt;code&gt;v-validate=&lt;/code&gt;、2行目の&lt;code&gt;errors.first('email')&lt;/code&gt;が重要です。&lt;/p&gt;
&lt;h3 id="name"&gt;name&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;name&lt;/code&gt;か&lt;code&gt;data-vv-name&lt;/code&gt;がないと警告が出ます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;#34;[vee-validate] A field is missing a &amp;#39;name&amp;#39; or &amp;#39;data-vv-name&amp;#39; attribute&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;後述するエラー情報などに使われるからだと考えられます。&lt;/p&gt;
&lt;h3 id="v-validate"&gt;v-validate&lt;/h3&gt;
&lt;p&gt;こちらはバリデーション条件を指定する属性で、文字列やオブジェクトを渡すことができるようです。&lt;/p&gt;
&lt;p&gt;必須項目には&lt;code&gt;'required'&lt;/code&gt;、必須かつメールアドレスのフォーマットチェックには&lt;code&gt;'required|email'&lt;/code&gt;のように複数の条件を結合して使えそうです。&lt;/p&gt;
&lt;p&gt;ルールの一覧はこちらのドキュメントに。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://baianat.github.io/vee-validate/guide/rules.html" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;baianat.github.io →&lt;/span&gt;&lt;span&gt;https://baianat.github.io/vee-validate/guide/rules.html&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;かなり豊富なので大抵のことは簡単に指定できそう。&lt;/p&gt;
&lt;p&gt;さきほどの例では、&lt;code&gt;'required'&lt;/code&gt;と&lt;code&gt;'required|email'&lt;/code&gt;を使っています。&lt;/p&gt;
&lt;h3 id="エラー表示"&gt;エラー表示&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;errors.first('email')&lt;/code&gt;には、&lt;code&gt;name=&amp;quot;email&amp;quot;&lt;/code&gt;なinputにバリデーションエラーがある場合に、エラーメッセージが入っています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;span&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text-danger&amp;#34;&lt;/span&gt;&amp;gt;{{ errors.first(&amp;#39;email&amp;#39;) }}&amp;lt;/&lt;span style="color:#f92672"&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;として表示するようにしておくと、エラーがあるときだけメッセージが表示されます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/dNRnDGCDTeMunJfXZaA8l0aXr1eLK0cLcQ3c_3aBrdv9Vn7FvIvTScpYZIP9VUbnx3G6rjFSA8AfSBSLAiu-CGy2Wc1WcbfdWSuiHc7GBuCqcBa8JB3L2yyyhF7Mh_RompWlrao2W5_XC-zg9rq4ErphnWE38oXdVOp28uA1bffxEVHMEto17BJION9YKMhoLCklLEnKtCq-EHmP2V0GAH33k-DEp4ng-RpYKAvdCwR_VlgYAtdAfjhccqQKMO-GCTaE7P1fAUpGrsGgKj8I-FGiEhw8x7-tayWLqVxhsT1nI_IEJ3EejwtdeJfV6cpvgZD_Ot8xqFRM-Nb2W09srPxbqbgp0vjB0tbsJ3S-OcxPW3LSK5FatiT3Sb-_ovTTeTFEoiuqKYD4OYKXM8l-YTxSCCbibAtdBvMMBWxfAb_7FEkgTYL0acdy2_Az6H6gJj8T0fBBvqUuDsM7bz1lcHfM5WHd58v1Y6njX6emfupy1EbqAkfEfkKwwEz5Eyi742Y03PY7xNyG5P4CHRQLHbedncE8A2pU0xPtJrDpjOYR5hqJjC9OpbstUwbePYsxiEvCnPJ5ETPpq1sD2np7m06jDtBK2m14ZYEYc5VWgr2kUIuI2ILZc86hbxrOqkyhkdycei4I4KCMlA6Ka3YVsVhnT8DjqjVugo0hBPITxlLOYoN7iAtUWjt4FNOlmVSlHjUWh115R7zg9XbGAf8=w1038-h1006-no"&gt;&lt;img src="https://lh3.googleusercontent.com/dNRnDGCDTeMunJfXZaA8l0aXr1eLK0cLcQ3c_3aBrdv9Vn7FvIvTScpYZIP9VUbnx3G6rjFSA8AfSBSLAiu-CGy2Wc1WcbfdWSuiHc7GBuCqcBa8JB3L2yyyhF7Mh_RompWlrao2W5_XC-zg9rq4ErphnWE38oXdVOp28uA1bffxEVHMEto17BJION9YKMhoLCklLEnKtCq-EHmP2V0GAH33k-DEp4ng-RpYKAvdCwR_VlgYAtdAfjhccqQKMO-GCTaE7P1fAUpGrsGgKj8I-FGiEhw8x7-tayWLqVxhsT1nI_IEJ3EejwtdeJfV6cpvgZD_Ot8xqFRM-Nb2W09srPxbqbgp0vjB0tbsJ3S-OcxPW3LSK5FatiT3Sb-_ovTTeTFEoiuqKYD4OYKXM8l-YTxSCCbibAtdBvMMBWxfAb_7FEkgTYL0acdy2_Az6H6gJj8T0fBBvqUuDsM7bz1lcHfM5WHd58v1Y6njX6emfupy1EbqAkfEfkKwwEz5Eyi742Y03PY7xNyG5P4CHRQLHbedncE8A2pU0xPtJrDpjOYR5hqJjC9OpbstUwbePYsxiEvCnPJ5ETPpq1sD2np7m06jDtBK2m14ZYEYc5VWgr2kUIuI2ILZc86hbxrOqkyhkdycei4I4KCMlA6Ka3YVsVhnT8DjqjVugo0hBPITxlLOYoN7iAtUWjt4FNOlmVSlHjUWh115R7zg9XbGAf8=w1038-h1006-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;エラーメッセージの日本語化やフォームの見た目調整など気になるところはありますが、ひとまずこれでバリデーションできたと言えそうなところまで来ました。&lt;/p&gt;
&lt;h2 id="コード全体"&gt;コード全体&lt;/h2&gt;
&lt;p&gt;今回のコード全体です。&lt;/p&gt;
&lt;p data-height="265" data-theme-id="light" data-slug-hash="ePxOEN" data-default-tab="html,result" data-user="pi-chan" data-pen-title="vee-validate" class="codepen"&gt;See the Pen &lt;a href="https://codepen.io/pi-chan/pen/ePxOEN/"&gt;vee-validate&lt;/a&gt; by hiromasa (&lt;a href="https://codepen.io/pi-chan"&gt;@pi-chan&lt;/a&gt;) on &lt;a href="https://codepen.io"&gt;CodePen&lt;/a&gt;.&lt;/p&gt;
&lt;script async src="https://static.codepen.io/assets/embed/ei.js"&gt;&lt;/script&gt;</description></item><item><title>GitHubのsuggestion機能でプルリクエストのレビュー中にコードを提案できるらしい</title><link>https://blog.piyo.tech/posts/2018-10-27-github-suggestion-comment/</link><pubDate>Sat, 27 Oct 2018 06:07:05 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-27-github-suggestion-comment/</guid><description>&lt;p&gt;というのをTwitterで見かけたので試してみました。&lt;/p&gt;
&lt;p&gt;プルリクエストのレビュー欄で案内が出るので見たことがある人も多いかもしれません。&lt;/p&gt;
&lt;p&gt;検証のため、本当に雑なプルリクエストを作って試しました。コードに意味はないので気にしないでください。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/pi-chan/MobxTodoApp/pull/1" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://avatars.githubusercontent.com/u/3599510?s=400&amp;amp;v=4" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;suggestionを試す by pi-chan · Pull Request #1 · pi-chan/MobxTodoApp&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/-oFxT87EPq6_7rahpHiK5azUjFe3gJC6YDSYNHrmX7LK0sjPZCsDEwISxzza0uqLfK5yUUBsTurRYb_bOqhTjK1K_VTqYmiFlS1Io8n8zG3zDzdWDoe6huktXN1pbO64FF3rStdO9THnLXe2VBOMb-rLDzhTQqlZH_MpPoqGmutppIWyf2Fup_u0DQuhGdgDTZF9Ht7naVxbiWT6yhLjmCwyLPv8hKD9CtD_dhFmmYsh3P0Kxdl5F1xrqiuAd8avfnOVORx-CokCKOsldljz-xyQHqCWrp-H1z6CdkWKfQ46EJ98z1c-2yRdRWTQXqBpeYxly7I65WYuDS6gXiDzDjP6tcUTeEplURNhnujccNxJJLMXs_HeJ84mkmMSxOr-ENjP6derZALaYk3ierbLjXW0_7LTmavwWUPwWeTNAO8N9nlBXn4M53h-gsBXwNSf5oYE044zPT9nU_iRgoNNeOg8fUcppXhyqQwT_Gr1ibFKKBMaPzvTqTP0eRNWKh1Zv8y7efjGVUclsdI0NnurIMHed3AEOfOpPIOK7bSHhOyi2aHCdV1rvfTG3kehbq400gU3OfnRj6PGkH6KZi7-mvnckltpo1Y8VxzTUmtspUaxw3oyr-bUDSwPDnxwBETxH8HtwryUDhe6LSOup0xhObQ4guExZnDY5sis9_X49Gz4OxTAobAg4d_GEAU_ls4memy0E80d7KIXGavhKrA=w1102-h230-no"&gt;&lt;img src="https://lh3.googleusercontent.com/-oFxT87EPq6_7rahpHiK5azUjFe3gJC6YDSYNHrmX7LK0sjPZCsDEwISxzza0uqLfK5yUUBsTurRYb_bOqhTjK1K_VTqYmiFlS1Io8n8zG3zDzdWDoe6huktXN1pbO64FF3rStdO9THnLXe2VBOMb-rLDzhTQqlZH_MpPoqGmutppIWyf2Fup_u0DQuhGdgDTZF9Ht7naVxbiWT6yhLjmCwyLPv8hKD9CtD_dhFmmYsh3P0Kxdl5F1xrqiuAd8avfnOVORx-CokCKOsldljz-xyQHqCWrp-H1z6CdkWKfQ46EJ98z1c-2yRdRWTQXqBpeYxly7I65WYuDS6gXiDzDjP6tcUTeEplURNhnujccNxJJLMXs_HeJ84mkmMSxOr-ENjP6derZALaYk3ierbLjXW0_7LTmavwWUPwWeTNAO8N9nlBXn4M53h-gsBXwNSf5oYE044zPT9nU_iRgoNNeOg8fUcppXhyqQwT_Gr1ibFKKBMaPzvTqTP0eRNWKh1Zv8y7efjGVUclsdI0NnurIMHed3AEOfOpPIOK7bSHhOyi2aHCdV1rvfTG3kehbq400gU3OfnRj6PGkH6KZi7-mvnckltpo1Y8VxzTUmtspUaxw3oyr-bUDSwPDnxwBETxH8HtwryUDhe6LSOup0xhObQ4guExZnDY5sis9_X49Gz4OxTAobAg4d_GEAU_ls4memy0E80d7KIXGavhKrA=w1102-h230-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="suggestion機能の使い方"&gt;suggestion機能の使い方&lt;/h1&gt;
&lt;p&gt;suggestion機能は、プルリクエストのレビューをしていて、「ここのコード、こっちの書き方のほうがいいよとか、こっちの書き方じゃないとまずいよ」というときに、コードの差分をまるっと書いてあげるとそのまま取り込める、みたいな機能です。&lt;/p&gt;
&lt;h2 id="suggestionを作る"&gt;suggestionを作る&lt;/h2&gt;
&lt;p&gt;プルリクエストのコメント欄のここ（↓）にボタンがあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/aHZwhdKkX2f4d37REb-MUNm9PxPNEk4x8ykYytIBKLkqZm-rh_fHN6rz4skxlMyz7i2m2pmvv8-OSt0eoyX1rtvLIYwyioK_iQFF34lNKBznblZ4Scmn3jsRE4uVKViPnaUK4FeHNyLSvW7G2689y0xvWCT3H3pkIY_IGlGR2o2wqWWld8pb9eFCeZonCHWJ8v4U9TtVugqebHjboqSfaExI9NT7Vo0DxN8QmadgVdtJ5WYphzp5dBS2T6LKONmsnLcagx3YFl42cNXvi2WLHA6N2pk6ur83AiQ6STyT8jJQhFGBFT1ncHbS1PlWKoUOBsNAzSfA5_5ulbhjkl5W8vj6qGeCBNH0oothcIfKpU-2bnZB9dk7N5xp6Q99ezH7c4TgHDvxdlIAwU9eKOkzi6us44BL6FDi3q3EkDjVoVCPsaz5wM2KNjxQUhEFucEKjfMPmgvcdS2eqvVCgCZFPS7JhpAL7MGUGT0SZnMtr4AcXWPA4CJE5dOz38HnsBXOgEZDkjQRa6yC5X7C7S1ynPRUwQWScFXOIJBtA_8FhuQWX9l_GzpqlZDCEItF7W4tFqdrf3YkT5_gsvKoU0tOae1ChjeerotRNADMk4akz96_FA3kR3GiUzqS9ozcZGHVhSs0oK44fAzLw_F5Ie9JVCNqWmTEG0sUOH_tNNZOSyZFWrVeqHiZm5P2IEGp27Umve4nGFp3DqTELnZLZ1Y=w1662-h650-no"&gt;&lt;img src="https://lh3.googleusercontent.com/aHZwhdKkX2f4d37REb-MUNm9PxPNEk4x8ykYytIBKLkqZm-rh_fHN6rz4skxlMyz7i2m2pmvv8-OSt0eoyX1rtvLIYwyioK_iQFF34lNKBznblZ4Scmn3jsRE4uVKViPnaUK4FeHNyLSvW7G2689y0xvWCT3H3pkIY_IGlGR2o2wqWWld8pb9eFCeZonCHWJ8v4U9TtVugqebHjboqSfaExI9NT7Vo0DxN8QmadgVdtJ5WYphzp5dBS2T6LKONmsnLcagx3YFl42cNXvi2WLHA6N2pk6ur83AiQ6STyT8jJQhFGBFT1ncHbS1PlWKoUOBsNAzSfA5_5ulbhjkl5W8vj6qGeCBNH0oothcIfKpU-2bnZB9dk7N5xp6Q99ezH7c4TgHDvxdlIAwU9eKOkzi6us44BL6FDi3q3EkDjVoVCPsaz5wM2KNjxQUhEFucEKjfMPmgvcdS2eqvVCgCZFPS7JhpAL7MGUGT0SZnMtr4AcXWPA4CJE5dOz38HnsBXOgEZDkjQRa6yC5X7C7S1ynPRUwQWScFXOIJBtA_8FhuQWX9l_GzpqlZDCEItF7W4tFqdrf3YkT5_gsvKoU0tOae1ChjeerotRNADMk4akz96_FA3kR3GiUzqS9ozcZGHVhSs0oK44fAzLw_F5Ie9JVCNqWmTEG0sUOH_tNNZOSyZFWrVeqHiZm5P2IEGp27Umve4nGFp3DqTELnZLZ1Y=w1662-h650-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これを押すと、&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```suggestion
// code
```
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;みたいなテキストがコメント欄に挿入されます。ここに、どのように元のコードから変えたほうがいいのか、みたいなことを書きます。&lt;/p&gt;
&lt;p&gt;たとえば画像の例ではletをconstに変えようという指摘をしています。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```suggestion
let dummy = 'dummy text';
```
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最初↑のように挿入されたものを↓に書き換えてコメントを登録します。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```suggestion
const dummy = 'dummy text';
```
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;すると差分つきのコメントになります。&lt;code&gt;Resolve conversation&lt;/code&gt;ボタンや&lt;code&gt;Apply suggestions&lt;/code&gt;ボタンもありますね。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/rBDmSODNU9dXLHeVd_sWMvQX1dGuQgguMRobhlN8UuvdKBaSMVwSvRIayy4X4U3mFlQJ2uyjtsUMIAk_EtzZSdhypz8Oayr1B7ErpHK-pQTPlFqBr8yWFxAB1YICpzwPQ5-GtSN_KI3ZEPYHAi4vh3ZQN25MfAXwplGbT-ogPXStXNC-cMXvgUFv8LDSdjbRKzsKvDNz7kMeqHQdq4iLcgTEFnQpBiGcR7NlPNFtPPXWC_hDsn3izlfm2qdV0-Cj8wRpWqVML3ZrSn5lnx2AVwDUuGOhT7hxLUmMYLB9Oh_lKPilS-bft-J0u4azzFyPrAwA56yqAQkMyEtSAeqcocb8ApgX15kBaYQrBm5fi1pgth_H2fuNthSmDXJDbeN4bHL3D7578foD5bRkLZIEgap3fsfsvvP8OXW5XAw5KozumqikZATTi0YztZ_bmohsdBF1eGarqT_gKy0I3DI5rxVH4mCg5fbs--FQl8oYgy22VIBh7ZqXTwgPit2lVLQ1q3mPLof4NxoPb3i86S4VfyL1xL2dKfaweJtvWBY3QhsP6LLVRKQR-SXwXf3M1IgwIrbKi7299hau9CSQQsdNJot2vYGHeM44fnEcchGrt_o7d_FJNP4DFN96Va4jOlQjuXZMnsD6CmvUPx65ib-PAF27IqZj8R0xPL0gcf5A7svPE25JV_p7O0hUVRAa5ZKu9Y2OEEpx4ZiwhGW-VO0=w1636-h742-no"&gt;&lt;img src="https://lh3.googleusercontent.com/rBDmSODNU9dXLHeVd_sWMvQX1dGuQgguMRobhlN8UuvdKBaSMVwSvRIayy4X4U3mFlQJ2uyjtsUMIAk_EtzZSdhypz8Oayr1B7ErpHK-pQTPlFqBr8yWFxAB1YICpzwPQ5-GtSN_KI3ZEPYHAi4vh3ZQN25MfAXwplGbT-ogPXStXNC-cMXvgUFv8LDSdjbRKzsKvDNz7kMeqHQdq4iLcgTEFnQpBiGcR7NlPNFtPPXWC_hDsn3izlfm2qdV0-Cj8wRpWqVML3ZrSn5lnx2AVwDUuGOhT7hxLUmMYLB9Oh_lKPilS-bft-J0u4azzFyPrAwA56yqAQkMyEtSAeqcocb8ApgX15kBaYQrBm5fi1pgth_H2fuNthSmDXJDbeN4bHL3D7578foD5bRkLZIEgap3fsfsvvP8OXW5XAw5KozumqikZATTi0YztZ_bmohsdBF1eGarqT_gKy0I3DI5rxVH4mCg5fbs--FQl8oYgy22VIBh7ZqXTwgPit2lVLQ1q3mPLof4NxoPb3i86S4VfyL1xL2dKfaweJtvWBY3QhsP6LLVRKQR-SXwXf3M1IgwIrbKi7299hau9CSQQsdNJot2vYGHeM44fnEcchGrt_o7d_FJNP4DFN96Va4jOlQjuXZMnsD6CmvUPx65ib-PAF27IqZj8R0xPL0gcf5A7svPE25JV_p7O0hUVRAa5ZKu9Y2OEEpx4ZiwhGW-VO0=w1636-h742-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="suggestionを適用しない場合"&gt;suggestionを適用しない場合&lt;/h2&gt;
&lt;p&gt;議論した結果やっぱりこの差分使わない、となった場合はコメント左下にある&lt;code&gt;Resolve conversation&lt;/code&gt;を押せばOK。suggestionは畳まれるのでそのあとあまり邪魔にはなりません。&lt;/p&gt;
&lt;p&gt;差分そのままじゃなくて自分でもうちょっと直すというときもResolveしそう。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/hUTbm3YLkmwd-8I7_iOqxEz0uF7_7AgNFrmfJTdIG4gvGnBL7SP5qFSTIe3yPk4IF8Bpvb36slvpDnQ_EIDZKHXvXCogkMNlTfIA2NDNV2kJb1EqFUgmnGf_2XEb4pUqmu80JT2PEs6x3K49B6mgZN0PcurLiQqFXPaFQUoGz2KhLaBLGIeOtIYwOWn_XyuOT0QVpG6woQ_2up-VWpsV4KZAJpHtOuLEg8YcxhMeJL80eFagmRijV0jeW9N_IRH1I5bM_m-4tLX0LUcIJ6dNqstqKs6dQB7qRITnwG5aA37-jKYxneRL0VPfTsVKXvpQpjaOXQ8jKOiPjVIGDe-6tli1TNh87suMDEDELRNl5tl9YTD-4KHaEZYcM_Je0WW0Ysi9i_yGtBF8_cRWWMjjLNphjjidL_MVURrZc6fBDjHRyIMeL6mEDpHbnH-v12_KflwasBP9EIBc2OqYS7UEl-uoe8dR0dJXRYZMkh86NriUlsddkeuFot5ALGVRzKzh6qo95FzfiZMO_LYruKLhNjOtKVolD8w_fTgwQcKdkPB7iXEKIWy08GZnTeyNEM4JDP8cSvargc7EzryGY4VOwlqtoJTpraGnnPiYQz7mx9qbS5lhisYyAWUflOIt46Ee_Phlmc_Rpr6p6eTByTbRs4IsQ6aW55IDHdzZYe8TvdmSsNd0ywoY8A_qOXtzxGf997zULZdsEmxlAsfh7l0=w1624-h466-no"&gt;&lt;img src="https://lh3.googleusercontent.com/hUTbm3YLkmwd-8I7_iOqxEz0uF7_7AgNFrmfJTdIG4gvGnBL7SP5qFSTIe3yPk4IF8Bpvb36slvpDnQ_EIDZKHXvXCogkMNlTfIA2NDNV2kJb1EqFUgmnGf_2XEb4pUqmu80JT2PEs6x3K49B6mgZN0PcurLiQqFXPaFQUoGz2KhLaBLGIeOtIYwOWn_XyuOT0QVpG6woQ_2up-VWpsV4KZAJpHtOuLEg8YcxhMeJL80eFagmRijV0jeW9N_IRH1I5bM_m-4tLX0LUcIJ6dNqstqKs6dQB7qRITnwG5aA37-jKYxneRL0VPfTsVKXvpQpjaOXQ8jKOiPjVIGDe-6tli1TNh87suMDEDELRNl5tl9YTD-4KHaEZYcM_Je0WW0Ysi9i_yGtBF8_cRWWMjjLNphjjidL_MVURrZc6fBDjHRyIMeL6mEDpHbnH-v12_KflwasBP9EIBc2OqYS7UEl-uoe8dR0dJXRYZMkh86NriUlsddkeuFot5ALGVRzKzh6qo95FzfiZMO_LYruKLhNjOtKVolD8w_fTgwQcKdkPB7iXEKIWy08GZnTeyNEM4JDP8cSvargc7EzryGY4VOwlqtoJTpraGnnPiYQz7mx9qbS5lhisYyAWUflOIt46Ee_Phlmc_Rpr6p6eTByTbRs4IsQ6aW55IDHdzZYe8TvdmSsNd0ywoY8A_qOXtzxGf997zULZdsEmxlAsfh7l0=w1624-h466-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="suggestionを適用する場合"&gt;suggestionを適用する場合&lt;/h2&gt;
&lt;p&gt;差分をまるっと取り込みたい場合は&lt;code&gt;Apply sugggestions&lt;/code&gt;します。コミットメッセージをつけてコミットができます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Sqot7ngNOf8vrRV7c9bz2BaB5sT7GNb4jbdqXNTPGA2lnNjQW7ZiY-nkww2tdkBwYMZwfCV--NR4IwJEXVfYigSQkSxHylPqA-oMgLueDEyYvmgKZBFV9v2Y1kI3C20CgybpXxp4vadvmaxpxSty-8-B_97sOM8ObDl4SbaefMDAZU72wZyQ_tLdt-ZOJjwKK6x1NUq-74rDeFsD8Hj7AJi4y6zX9ISkQRHv7AvvMdGcaNcBIkwk8rrDciMskSzPPGaA9sv_WQGGz6qCspsfKdCLcItI_F2d1bG3iB3c4PGS5PT40u400v1zZ9PIWELyZrpePu2S3o86nyxABwYFLe9AXhP7MvkPsSSkDKb7SZfZCrg563vA4LlTWAMp5UpH1SLHgzVzWlvm1wB75FmCqiaXQHwwb2OmYoiJ0p8K1mPEpyNyh_a33oQCOpQKtPGvxRGfp7k0gRi6kMK8ymMzzkQCWHMfZP58oyjsQtDgiBW-Rf7eF0eZY4-r7Cs9Ctp-tAhcxcf6q2JC1NT1TmlOHkIhnC59TkxdOzXBDoOrRTzyh8d08cdC-h7YGJysbl_2AuY1P85jxno9U0BLDP777Mu21ssqpkaqio6SaBlveP55yjTp92eYUU3fiUUqes3LBBCldmysUk7kl6LlMdenvbvDDXlh_BNEaT4FqNZ_y-1zuZEzbybRuMNTfQ5NDZaceSBUda8zJTi3vmL4KcY=w1660-h734-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Sqot7ngNOf8vrRV7c9bz2BaB5sT7GNb4jbdqXNTPGA2lnNjQW7ZiY-nkww2tdkBwYMZwfCV--NR4IwJEXVfYigSQkSxHylPqA-oMgLueDEyYvmgKZBFV9v2Y1kI3C20CgybpXxp4vadvmaxpxSty-8-B_97sOM8ObDl4SbaefMDAZU72wZyQ_tLdt-ZOJjwKK6x1NUq-74rDeFsD8Hj7AJi4y6zX9ISkQRHv7AvvMdGcaNcBIkwk8rrDciMskSzPPGaA9sv_WQGGz6qCspsfKdCLcItI_F2d1bG3iB3c4PGS5PT40u400v1zZ9PIWELyZrpePu2S3o86nyxABwYFLe9AXhP7MvkPsSSkDKb7SZfZCrg563vA4LlTWAMp5UpH1SLHgzVzWlvm1wB75FmCqiaXQHwwb2OmYoiJ0p8K1mPEpyNyh_a33oQCOpQKtPGvxRGfp7k0gRi6kMK8ymMzzkQCWHMfZP58oyjsQtDgiBW-Rf7eF0eZY4-r7Cs9Ctp-tAhcxcf6q2JC1NT1TmlOHkIhnC59TkxdOzXBDoOrRTzyh8d08cdC-h7YGJysbl_2AuY1P85jxno9U0BLDP777Mu21ssqpkaqio6SaBlveP55yjTp92eYUU3fiUUqes3LBBCldmysUk7kl6LlMdenvbvDDXlh_BNEaT4FqNZ_y-1zuZEzbybRuMNTfQ5NDZaceSBUda8zJTi3vmL4KcY=w1660-h734-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;コミットすると、プルリクエストの元ブランチに新しいコミットとして追加されます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/9CHXFbT94k5b_Toky2H6PqCHDopBhV-mj7BUAKpHu53HMyG-aVuorcsgPeAS9vG_cq-hG88PPuVr5VBS-SdbUSnB27iPuxUd5FQAbmBMk2VHlte2tBqcTf8dn_ww8UEGK2K4R7w2c-4rmbvUhrUM34xrUllcmHnVQJ3m7ISw5n7wjJMCeQmqHb69aHAq8PvzieIfML0JMxAgztCZhhMY5Ca11fOd8_YTBKVqXKOWXkk8Mz8OOW1104oZ4N8DxwIp-IWJ8VRi0cQp5tq86kyVQvpoi_eESUcGM8TxJNJa9Fkphxfgjb0Hc1bJOY8IZwCa-uQmAyMXe3ixh4Jh441TcQNZWjwst212I0xGY2Z8s2MvJeXkNPCGb2uiZDZv7Ky17N9cxYSVGnzTXukoN-Gtync0iFXkEUkHG9I7AL4vsw2jHf4k2Utc6ulowWxHpGyrGmay6gri0ohzSsstng99W7r85draksQIav0r5qXyO9g6Y-4KVImFZTtkqw5OLz69lr-M8vqEO5GF65KUVgdcmtSV0ml5NjnPY72EHpZEiK9Fg4HK5pfXa8NIx8g3yau6-XilOh_MqtaCE6WZDCuIFPTfBRQ0Z5_ZjDf0QY4eUlO4UvjJ_JuFRBCzxvoC6B_85sEo8fZeV0WoJlmfGwiymAqbyWnoImFLvsA1vPHG38C6G3rxwRS6NiixjjUWJxj61pv9oPVAadD6XL0vSzI=w1230-h500-no"&gt;&lt;img src="https://lh3.googleusercontent.com/9CHXFbT94k5b_Toky2H6PqCHDopBhV-mj7BUAKpHu53HMyG-aVuorcsgPeAS9vG_cq-hG88PPuVr5VBS-SdbUSnB27iPuxUd5FQAbmBMk2VHlte2tBqcTf8dn_ww8UEGK2K4R7w2c-4rmbvUhrUM34xrUllcmHnVQJ3m7ISw5n7wjJMCeQmqHb69aHAq8PvzieIfML0JMxAgztCZhhMY5Ca11fOd8_YTBKVqXKOWXkk8Mz8OOW1104oZ4N8DxwIp-IWJ8VRi0cQp5tq86kyVQvpoi_eESUcGM8TxJNJa9Fkphxfgjb0Hc1bJOY8IZwCa-uQmAyMXe3ixh4Jh441TcQNZWjwst212I0xGY2Z8s2MvJeXkNPCGb2uiZDZv7Ky17N9cxYSVGnzTXukoN-Gtync0iFXkEUkHG9I7AL4vsw2jHf4k2Utc6ulowWxHpGyrGmay6gri0ohzSsstng99W7r85draksQIav0r5qXyO9g6Y-4KVImFZTtkqw5OLz69lr-M8vqEO5GF65KUVgdcmtSV0ml5NjnPY72EHpZEiK9Fg4HK5pfXa8NIx8g3yau6-XilOh_MqtaCE6WZDCuIFPTfBRQ0Z5_ZjDf0QY4eUlO4UvjJ_JuFRBCzxvoC6B_85sEo8fZeV0WoJlmfGwiymAqbyWnoImFLvsA1vPHG38C6G3rxwRS6NiixjjUWJxj61pv9oPVAadD6XL0vSzI=w1230-h500-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;という感じでした。&lt;/p&gt;
&lt;p&gt;これ結構使えそうだー。&lt;/p&gt;</description></item><item><title>macOS MojaveでDockに最近使ったアプリがでるようになったのを消したい</title><link>https://blog.piyo.tech/posts/2018-10-26-mojave-dock-recent-apps/</link><pubDate>Fri, 26 Oct 2018 06:12:26 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-26-mojave-dock-recent-apps/</guid><description>&lt;p&gt;macOSをMojaveにアップデートしたらDockに最近使ったアプリがでて少々邪魔。&lt;/p&gt;
&lt;p&gt;こんな風に出るやつ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/0a6gE23SDnwwBeNS3EfuUIcqEqyiU_honTyqTThOuqISmRX-141khYWL6EnVkICVjfg1T6sr4-oq4qzNopl4xbWpJDrS-agcF-TwFcJfkztZHkATwVmX-XcCWoWlMpZrMT5GkEYq0heAunmYD_FvErIWjXCh7XvHeVZaosbulKct1QiTgt75tvUtDVRz2oEo_IKfsga5VNVDvMc2RhHnrsIaKhgUeQeAcT2yjGQiDdtKsFlVL0MEPCnZaWLXUEry8TeEdWwYo1peM0GL4cDecYK12NLisja8NcztjBZR9MdMXjPRhfGPgB13-KpoNEJlNEmCBsjOPXNj5lnWg2hJm0Dlap_LGpCLZujIg8aE9CZ4Fyyz3UyT-_9y0bfhox5w7-pFIDXldk8PgQXY7LsDRMMAxAxjxY0xr_HcyYV5eCF7nDmOBpFCU55ctjg6ZtMwXwxHE0PxTGAd2bV_3dcywnP7sLy5MRicnkgzkr1175B1gXU5vVEgtJu3p_eGtwP4b3rkSgNP8iAyoqNWWxWcIrAxOMlGb43jQydLlww1nCUdmWzGWOFewDt7HT9vS1WBjQ7uw12DTBAhETylnEgCvIEmvtqli4PyXJ_537_xN144vPymT71zADn3oZ1cxS_sCU-HyPMbGciVyoM7ryMppi1t9u4AFbGCePnYUcCM0R6RsgkWIcfKnbuocQ=w610-h128-no"&gt;&lt;img src="https://lh3.googleusercontent.com/0a6gE23SDnwwBeNS3EfuUIcqEqyiU_honTyqTThOuqISmRX-141khYWL6EnVkICVjfg1T6sr4-oq4qzNopl4xbWpJDrS-agcF-TwFcJfkztZHkATwVmX-XcCWoWlMpZrMT5GkEYq0heAunmYD_FvErIWjXCh7XvHeVZaosbulKct1QiTgt75tvUtDVRz2oEo_IKfsga5VNVDvMc2RhHnrsIaKhgUeQeAcT2yjGQiDdtKsFlVL0MEPCnZaWLXUEry8TeEdWwYo1peM0GL4cDecYK12NLisja8NcztjBZR9MdMXjPRhfGPgB13-KpoNEJlNEmCBsjOPXNj5lnWg2hJm0Dlap_LGpCLZujIg8aE9CZ4Fyyz3UyT-_9y0bfhox5w7-pFIDXldk8PgQXY7LsDRMMAxAxjxY0xr_HcyYV5eCF7nDmOBpFCU55ctjg6ZtMwXwxHE0PxTGAd2bV_3dcywnP7sLy5MRicnkgzkr1175B1gXU5vVEgtJu3p_eGtwP4b3rkSgNP8iAyoqNWWxWcIrAxOMlGb43jQydLlww1nCUdmWzGWOFewDt7HT9vS1WBjQ7uw12DTBAhETylnEgCvIEmvtqli4PyXJ_537_xN144vPymT71zADn3oZ1cxS_sCU-HyPMbGciVyoM7ryMppi1t9u4AFbGCePnYUcCM0R6RsgkWIcfKnbuocQ=w610-h128-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;システム環境設定のDockの設定を開いてみたら消せたので消しました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/rgkMQQjz6k96DmPZX0FCvaJpfKvc1jHcYtjdR1Q6dni10XzKCqYwLmcM_XvsgqLaaMnznYNAX4glZIp-UGS4tF4G6UMHV5BbOzIcQbCumPPt3BImgpArygZsQJ8Bts12WgO6hqCYANrjlQePpMcGnnEVKK0X3FDwMUp-OyicnSKBzUU88djVz3h_U0hvzMkMPUTuZjujhnY-FQHfyAaEQNS64dsQ4NqZjhiLBRjIHEwoeb5TiSbCjCqF4Bjq7M8HL81KcJQxF1p9W9UrO6v3hFE9-tO_ux6goqPtcT3gts1IFYaX-xT49uCWpZHLoQ5DBEWvHvCJ6TcOOcyGchOZ6WvEekMLD4A22A06Iym_b82dd9yIbsnUobWEdYGNC5qt-zJZQrt35UqHY6XwV5xRaHi27v_c4itjuqWMJ3khYi1sekubIaJ1xHjX_jeA8kLlAQh_m3KOdfWjmG7GIIFTHcjx6C5TxXhcJxohRVVJH9eLyGjJ3zEwsIvqc1neWUvixQFhEl9nTFtih-rgyd-rJ45yTyZ8Xh_sG-VJlFKX4t17Phryb_xYoxDHkEDl48rtS1p1cRZ-PghLEOYVAPZM4bhD5OfkkRE58Qx_m3PumEikP5pExfRhY9qu-o7sUUCfVSJzcq4ojOv9eeoNjxIsOcY7dkS50TfYton7wJO2BNXdWejdIHyPBGeIaQ=w1560-h1026-no"&gt;&lt;img src="https://lh3.googleusercontent.com/rgkMQQjz6k96DmPZX0FCvaJpfKvc1jHcYtjdR1Q6dni10XzKCqYwLmcM_XvsgqLaaMnznYNAX4glZIp-UGS4tF4G6UMHV5BbOzIcQbCumPPt3BImgpArygZsQJ8Bts12WgO6hqCYANrjlQePpMcGnnEVKK0X3FDwMUp-OyicnSKBzUU88djVz3h_U0hvzMkMPUTuZjujhnY-FQHfyAaEQNS64dsQ4NqZjhiLBRjIHEwoeb5TiSbCjCqF4Bjq7M8HL81KcJQxF1p9W9UrO6v3hFE9-tO_ux6goqPtcT3gts1IFYaX-xT49uCWpZHLoQ5DBEWvHvCJ6TcOOcyGchOZ6WvEekMLD4A22A06Iym_b82dd9yIbsnUobWEdYGNC5qt-zJZQrt35UqHY6XwV5xRaHi27v_c4itjuqWMJ3khYi1sekubIaJ1xHjX_jeA8kLlAQh_m3KOdfWjmG7GIIFTHcjx6C5TxXhcJxohRVVJH9eLyGjJ3zEwsIvqc1neWUvixQFhEl9nTFtih-rgyd-rJ45yTyZ8Xh_sG-VJlFKX4t17Phryb_xYoxDHkEDl48rtS1p1cRZ-PghLEOYVAPZM4bhD5OfkkRE58Qx_m3PumEikP5pExfRhY9qu-o7sUUCfVSJzcq4ojOv9eeoNjxIsOcY7dkS50TfYton7wJO2BNXdWejdIHyPBGeIaQ=w1560-h1026-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>GoogleのOAuthの設定のリダイレクトURIに.testドメインが使えなくて困る</title><link>https://blog.piyo.tech/posts/2018-10-25-google-oauth-domain/</link><pubDate>Thu, 25 Oct 2018 06:24:56 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-25-google-oauth-domain/</guid><description>&lt;p&gt;個人用にGoogleのOAuthで認証できるRailsアプリを作っているんですが、開発時に用いるリダイレクトURIに開発サーバーの&lt;code&gt;.test&lt;/code&gt;ドメインが使えなくて困っています。&lt;/p&gt;
&lt;p&gt;結論から言うと解決策はわかっていません。なので、ただの愚痴です。&lt;/p&gt;
&lt;p&gt;もともとは、Railsアプリケーションのために&lt;code&gt;puma-dev&lt;/code&gt;を使って&lt;code&gt;.dev&lt;/code&gt;ドメインで、&lt;code&gt;http://my-app.dev&lt;/code&gt;とかで開発したサイトを確認していました。ところが、&lt;code&gt;.dev&lt;/code&gt;ドメインはGoogleが所有していて、Chromeでは&lt;code&gt;.dev&lt;/code&gt;ドメインにHSTSが効くようになってしまっています。&lt;/p&gt;
&lt;p&gt;なのでpuma-dev勢はみんな「puma-devでは&lt;code&gt;.test&lt;/code&gt;ドメインを使おう」という対応をしたわけです。HSTS以外にもGoogleが勝手になにかする可能性がないとも言えないしね。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://qiita.com/cyborg__ninja/items/46f6e4d3674ef572d6bd" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFtYXpvbmF3cy5jb20lMkYwJTJGNzEzNyUyRnByb2ZpbGUtaW1hZ2VzJTJGMTQ3MzY4NDA4MT9peGxpYj1yYi00LjAuMCZhcj0xJTNBMSZmaXQ9Y3JvcCZtYXNrPWVsbGlwc2UmYmc9RkZGRkZGJmZtPXBuZzMyJnM9MzY5NTExNmQwOTMwZDdhOWVkOTA2MmFjNDNlN2QzMGE%26blend-x%3D120%26blend-y%3D462%26blend-w%3D90%26blend-h%3D90%26blend-mode%3Dnormal%26mark64%3DaHR0cHM6Ly9xaWl0YS1vcmdhbml6YXRpb24taW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnMzLWFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkZxaWl0YS1vcmdhbml6YXRpb24taW1hZ2UlMkZhYTY1NTNlZjI0NjgwMjdlM2U3NmEwNDM0N2M4ZWFiNDYyNzVmMDdkJTJGb3JpZ2luYWwuanBnJTNGMTQ2Mzk4MDUwND9peGxpYj1yYi00LjAuMCZ3PTQ0Jmg9NDQmZml0PWNyb3AmbWFzaz1jb3JuZXJzJmNvcm5lci1yYWRpdXM9OCZiZz1GRkZGRkYmYm9yZGVyPTIlMkNGRkZGRkYmZm09cG5nMzImcz1iMDc4M2QyMTE4MWViNzE5ODMzNTY5OTk1ODQxNWQ3Zg%26mark-x%3D186%26mark-y%3D515%26mark-w%3D40%26mark-h%3D40%26s%3D29c293c84a767ca706d12a9e5b907bdb?ixlib=rb-4.0.0&amp;amp;w=1200&amp;amp;fm=jpg&amp;amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9cHVtYSUyMCUyNiUyMHB1bWEtZGV2JTIwJUUzJTgxJUE3JUU1JTg4JUE5JUU3JTk0JUE4JUU0JUI4JUFEJUUzJTgxJUFFLmRldiVFMyU4MiU5Mi50ZXN0JUUzJTgxJUFBJUUzJTgxJUE5JUUzJTgxJUFCJUU1JUE0JTg5JUU2JTlCJUI0JUUzJTgxJTk5JUUzJTgyJThCJnR4dC1hbGlnbj1sZWZ0JTJDdG9wJnR4dC1jb2xvcj0lMjMxRTIxMjEmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9NTYmdHh0LXBhZD0wJnM9NmMzNDU0OTcwZDZlZTU4YzBlOTk0ZDhlYmM4MmQzODA&amp;amp;mark-x=120&amp;amp;mark-y=112&amp;amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDBjeWJvcmdfX25pbmphJnR4dC1jb2xvcj0lMjMxRTIxMjEmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9MzYmdHh0LXBhZD0wJnM9MzJmY2U3Yjg2YWU5MWY5NjA0ODgxN2YyYmI0MTA2MzI&amp;amp;blend-x=242&amp;amp;blend-y=454&amp;amp;blend-w=838&amp;amp;blend-h=46&amp;amp;blend-fit=crop&amp;amp;blend-crop=left%2Cbottom&amp;amp;blend-mode=normal&amp;amp;txt64=5qCq5byP5Lya56S-ZmF2eQ&amp;amp;txt-x=242&amp;amp;txt-y=539&amp;amp;txt-width=838&amp;amp;txt-clip=end%2Cellipsis&amp;amp;txt-color=%231E2121&amp;amp;txt-font=Hiragino%20Sans%20W6&amp;amp;txt-size=28&amp;amp;s=2cdf47e6b59d87829a167d05e3c3a0df" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;puma &amp;amp; puma-dev で利用中の.devを.testなどに変更する - Qiita&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;やってくれたな。GoogleChromeよ。 HSTS(HTTP Strict Transport Security) HTTP Strict Transport Security (エイチティーティーピー・ストリクト・トランスポート・セキュリティ、略称 HSTS)とは...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;qiita.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;普段の開発は&lt;code&gt;.test&lt;/code&gt;ドメインを使うだけで大丈夫でしたが、久しぶりにGoogleのOAuthを使っているアプリを動かそうと思ったときに困りました。&lt;/p&gt;
&lt;p&gt;Google側に登録しているOAuthアプリケーションの設定では、リダイレクトURIに&lt;code&gt;my-app.dev&lt;/code&gt;のURLを登録していました。ところがローカルのサーバーは&lt;code&gt;.test&lt;/code&gt;ドメインで動いています。&lt;/p&gt;
&lt;p&gt;なので、&lt;code&gt;my-app.test&lt;/code&gt;として登録しようとしたら、エラーになりやがる。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/r08TJLZGiqDSGzbHv4UHTuQwW068s7Nv42CPwE7m-o2MYLorZMSaQxHcKjHTTotldQmxByUyi_e8jgdD15KqyGo7sriHiFAyer1nGf_HeAQAhbEFJM9zDsBV36KUIbTunak1utl8n-RtnWnxDUvt1QxwN20SKpW8OzZh1aeFkw0zHH-SB7fAguP7fmsUFa2_6q3ag-6ZObKB_cwfG9kOhRvfnLv436eIoi3PljkFzV43dHp24JWwDb0UkT_Qzy51BRdLTBVq7JMvRHkjA3Q96dSMJyhJ4FIZSfX1rCp4fMv8GlgZMC1yKUGS-lgLB_nmOb-qMNSsdebdxtcNNrr0CrMsuIConhdyPTt1-DZIaCEt7nQ0ZwteeCgaTgduVB7Ugzjom0cgg-WdpxEiBFLi0LUJRactJfRu03KhBeqiWh5uy46Qp_vEOOR9GwdGOGDcj5i-O1IZ8y_RqQRILjSiJXWdPEUBbkCJduLlDxeTxY758FwywiybIbYRJH608GiaXgVMod3xbeY1jxmT4MxCe8HekTHHYrRyGxLka3haAEQfW4a6mxGgDAbLWE4rxoNjeTSlKcab0RXwyUsG_OFmVF2zq9yVqmxlqurHr8hQhvWEhYn3Xn3YGR9d_btCUbSbRoKNtmbxtF2lLpCCx-K5kM8XhdmH7mNOQBqIzWQrME_GTCkV0eB6-ujBNQ=w1232-h368-no"&gt;&lt;img src="https://lh3.googleusercontent.com/r08TJLZGiqDSGzbHv4UHTuQwW068s7Nv42CPwE7m-o2MYLorZMSaQxHcKjHTTotldQmxByUyi_e8jgdD15KqyGo7sriHiFAyer1nGf_HeAQAhbEFJM9zDsBV36KUIbTunak1utl8n-RtnWnxDUvt1QxwN20SKpW8OzZh1aeFkw0zHH-SB7fAguP7fmsUFa2_6q3ag-6ZObKB_cwfG9kOhRvfnLv436eIoi3PljkFzV43dHp24JWwDb0UkT_Qzy51BRdLTBVq7JMvRHkjA3Q96dSMJyhJ4FIZSfX1rCp4fMv8GlgZMC1yKUGS-lgLB_nmOb-qMNSsdebdxtcNNrr0CrMsuIConhdyPTt1-DZIaCEt7nQ0ZwteeCgaTgduVB7Ugzjom0cgg-WdpxEiBFLi0LUJRactJfRu03KhBeqiWh5uy46Qp_vEOOR9GwdGOGDcj5i-O1IZ8y_RqQRILjSiJXWdPEUBbkCJduLlDxeTxY758FwywiybIbYRJH608GiaXgVMod3xbeY1jxmT4MxCe8HekTHHYrRyGxLka3haAEQfW4a6mxGgDAbLWE4rxoNjeTSlKcab0RXwyUsG_OFmVF2zq9yVqmxlqurHr8hQhvWEhYn3Xn3YGR9d_btCUbSbRoKNtmbxtF2lLpCCx-K5kM8XhdmH7mNOQBqIzWQrME_GTCkV0eB6-ujBNQ=w1232-h368-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Googleの言葉を借りれば、&lt;code&gt;.test&lt;/code&gt;は「パブリック トップレベル ドメイン」ではないようで、登録できないわけです。&lt;/p&gt;
&lt;p&gt;これで詰み、とはならないですが少々不便です。仕方ないので&lt;code&gt;localhost:3000&lt;/code&gt;のURLを登録して&lt;code&gt;rails s&lt;/code&gt;して開発しています。面倒です。&lt;/p&gt;</description></item><item><title>RubyでネストしたHashのキーをフルパス？にする方法</title><link>https://blog.piyo.tech/posts/2018-10-24-ruby-convert-nested-hash-to-fullkeypath/</link><pubDate>Wed, 24 Oct 2018 06:47:53 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-24-ruby-convert-nested-hash-to-fullkeypath/</guid><description>&lt;p&gt;RubyでYAMLファイルを読むとネストしたHashにできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;b&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;c1&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;hogehoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;c2&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;fugafuga&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;であればこうなります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;yaml&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;hash &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;YAML&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;load_file(&lt;span style="color:#e6db74"&gt;&amp;#39;さっきのyml&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# hashは↓と同じものになる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;a&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;b&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;c1&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;hogehoge&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;c2&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;fugafuga&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ところでRailsの多言語対応のための仕組みI18nではYAMLを使いますよね。で、&lt;code&gt;I18n.l('activerecord.errors.messages.record_invalid')&lt;/code&gt;などとして、キーを渡すと翻訳が返ってきます。&lt;/p&gt;
&lt;p&gt;このキーの部分をドットで&lt;code&gt;split&lt;/code&gt;してYAMLを読み込んだHashを辿れば目的の翻訳にたどり着けるわけですが、その逆の全てのキーを結合してフルパスみたいにしたHashが欲しくなったのでどうやってやるのかなーと調べました。&lt;/p&gt;
&lt;p&gt;（そもそもなんて呼んだらいいのかわからないので、便宜的にフルパスとでも呼んでおきます。）&lt;/p&gt;
&lt;p&gt;つまり、↓のようなYAMLファイルがあったら（rails-i18nのja.ymlを拝借しています）、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;ja&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;activerecord&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;errors&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;messages&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;record_invalid&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;バリデーションに失敗しました: %{errors}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restrict_dependent_destroy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;has_one&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;%{record}が存在しているので削除できません&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;has_many&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;%{record}が存在しているので削除できません&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↓こうなってほしいのです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ja.activerecord.errors.messages.record_invalid&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;バリデーションに失敗しました: %{errors}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ja.activerecord.errors.messages.restrict_dependent_destroy.has_one&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;%{record}が存在しているので削除できません&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ja.activerecord.errors.messages.restrict_dependent_destroy.has_many&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;%{record}が存在しているので削除できません&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;調べてみてさっとできそうな方法がわからなかったので、再起的に書いてみることにしました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;module&lt;/span&gt; HashKeyJoiner
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;module_function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;join&lt;/span&gt;(hash, divider &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; h &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; each_path(hash&lt;span style="color:#f92672"&gt;.&lt;/span&gt;dup, &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;, divider) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;path, value&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; h&lt;span style="color:#f92672"&gt;[&lt;/span&gt;path&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; value
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; h
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;each_path&lt;/span&gt;(object, path, divider &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;block)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; object&lt;span style="color:#f92672"&gt;.&lt;/span&gt;is_a?(&lt;span style="color:#66d9ef"&gt;Hash&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; object&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;key, value&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; div &lt;span style="color:#f92672"&gt;=&lt;/span&gt; path&lt;span style="color:#f92672"&gt;.&lt;/span&gt;empty? ? &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt; : divider
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; next_path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;path, key&lt;span style="color:#f92672"&gt;].&lt;/span&gt;join(div)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; each_path value, next_path, divider, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;block
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;yield&lt;/span&gt; path, object
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hashを拡張するのもよいのですが、専用のモジュールにして呼ぶだけにしておきました。&lt;/p&gt;
&lt;p&gt;Hashを辿りながら、次の子要素がHashであれば再帰処理、終端の文字列であれば新しいHashに値を追加をしています。途中経過のpathを結合していきながらたどっているので、キーのフルパスで新しいHashを作れます。&lt;/p&gt;
&lt;p&gt;↓のように呼び出すと、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;yaml &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;YAML&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;load_file(&lt;span style="color:#e6db74"&gt;&amp;#39;./ja.yml&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;puts &lt;span style="color:#66d9ef"&gt;HashKeyJoiner&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(yaml)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↓のようにHash化されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &amp;#34;ja.activerecord.errors.messages.record_invalid&amp;#34;=&amp;gt;&amp;#34;バリデーションに失敗しました: %{errors}&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &amp;#34;ja.activerecord.errors.messages.restrict_dependent_destroy.has_one&amp;#34;=&amp;gt;&amp;#34;%{record}が存在しているので削除できません&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &amp;#34;ja.activerecord.errors.messages.restrict_dependent_destroy.has_many&amp;#34;=&amp;gt;&amp;#34;%{record}が存在しているので削除できません&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使いみちはあまりなさそうですが、ひとまず僕の目的は達成。&lt;/p&gt;</description></item><item><title>Vue Componentのstyleを上書きするには</title><link>https://blog.piyo.tech/posts/2018-10-23-vuejs-override-child-component-style/</link><pubDate>Tue, 23 Oct 2018 06:58:45 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-23-vuejs-override-child-component-style/</guid><description>&lt;p&gt;今日も&lt;code&gt;vuejs-datepicker&lt;/code&gt;に絡めての話。&lt;/p&gt;
&lt;p&gt;datepickerをインライン表示したら幅が固定になっていて困りました。&lt;/p&gt;
&lt;p&gt;こうじゃなくて、&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/59frkh0pm-afZiyJmKcPiMxSUEwaiuzH0uhx-63Wy3zt2rwaiz43OtRkEO1ks37944cnyWuKpYCz4KH5lkQ7x3iGaa6Aph37t-4FoRyX6BWHZDJy_zgducJrTfoE7gxqc-Zu2toVswkMEY1Jk2eB6Xu1nIL834Gu_U7Q45FnrcPC2sNl0G1YrhVIDXM5IBHzVUj7DaKdfxUFy7pDl6aPkahvJsNx58nX9RvJKaW_n35kgXTymxiI0XT3qI4y8mfNE7kEi8oo3tdFpRNgSuOpyjYb3Q7XbIObr2exwKkAz8EoxcAiSIpBqO4IfayJq-m6jlylAF-6gYk6gHeR_3vYzfA3ZzKJso4scCHGzwWgbcQChfcJm_De1uaNaVWi6ildgBjcPODDw7m0dE9mSe9gpUZRiLVSQnMvZF1I1vEkQLqkUiK3tcoViKr9B4pA6wRzsaL5wMM5cLXITxIwFADb1Y9yHcCIFYgz7pWsBZGQRsW4lDjq-ZhM4P7mM2oHPQejgMOMO0moCkYM3Sq5jPkmgSX7ggsZktRtoMc2zEJxHil3eKrbRhjzV9-7sr3PKxPNNrjP7cQNAxFcQUo0X1ZbuawI57ASjNTzsDmpoQXDnwLb0i8A5QIuJrQKEg2XWKHylo8IsCFocvUSOxRppdxzdA-n0o85DzpxjlekCw0RZMQp-0lD93GoVLmLdA=w1034-h740-no"&gt;&lt;img src="https://lh3.googleusercontent.com/59frkh0pm-afZiyJmKcPiMxSUEwaiuzH0uhx-63Wy3zt2rwaiz43OtRkEO1ks37944cnyWuKpYCz4KH5lkQ7x3iGaa6Aph37t-4FoRyX6BWHZDJy_zgducJrTfoE7gxqc-Zu2toVswkMEY1Jk2eB6Xu1nIL834Gu_U7Q45FnrcPC2sNl0G1YrhVIDXM5IBHzVUj7DaKdfxUFy7pDl6aPkahvJsNx58nX9RvJKaW_n35kgXTymxiI0XT3qI4y8mfNE7kEi8oo3tdFpRNgSuOpyjYb3Q7XbIObr2exwKkAz8EoxcAiSIpBqO4IfayJq-m6jlylAF-6gYk6gHeR_3vYzfA3ZzKJso4scCHGzwWgbcQChfcJm_De1uaNaVWi6ildgBjcPODDw7m0dE9mSe9gpUZRiLVSQnMvZF1I1vEkQLqkUiK3tcoViKr9B4pA6wRzsaL5wMM5cLXITxIwFADb1Y9yHcCIFYgz7pWsBZGQRsW4lDjq-ZhM4P7mM2oHPQejgMOMO0moCkYM3Sq5jPkmgSX7ggsZktRtoMc2zEJxHil3eKrbRhjzV9-7sr3PKxPNNrjP7cQNAxFcQUo0X1ZbuawI57ASjNTzsDmpoQXDnwLb0i8A5QIuJrQKEg2XWKHylo8IsCFocvUSOxRppdxzdA-n0o85DzpxjlekCw0RZMQp-0lD93GoVLmLdA=w1034-h740-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;こっちにしたい。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/oNYm7V31BJ_p7Yf2nNurD5BuvkYMlJcfaf_gbOzeXEJRWYRoKHWvQXH3ScPi-gsgQOGBiLa0xR2ga57MtTnsRRby01_2RUrgcm2UrjM-rdp67whg_EodLF4cPA1jtLWAedcs5lrJ-bg48Na3K2vUO6Kp3hGSKi04Vp3IeAKU7lUi75dL5-taBJXSqhY5ekjQ1Jjw04rRWKWJNqLq0SAwaGDCPGFj6TKBxn9pKqK0B6BruABLuXf3kQsXzvkUW06GFqigeJ1z-_N9hPtcyXZ1MeIW64AHxjcar6Pr9hRoWnp7uwVg2V8XMkzli59rhlW6UhK4sSslcJG6ZmhCqhqwePJACe4DYWwQ_zGkjzj-R251xv0LAsTCfEL8v8JLtL_sQsqAtgF7ohFmlahfbuu-cqZLncHgK1zcTmn5hnLj0dmz93R4SUMmEXISZ8ZG8TwBsRdC_K4GKmvfbzgMR0B6_bN8OdrDSbUMmTMkdT5qddcmVSncbZ-qKbsSK98QzwWT1Ewd43LTImkXuRA8GIdMGSRMGu7Ia7_U1q_MpbLPNgY0aQz9zoZvgoxtBfYk5z0eoawFT8USf_We9I1ZGjjKlMPMJI1DP7a_RbtQk2-4ACMcKAxSJjyKO0uVWwtmv22uu-AAnVVUHeDOiMdWK2VI0xK_k40tlxqBFgUAbxRL70PNilz_xDFbR9iMhA=w1022-h780-no"&gt;&lt;img src="https://lh3.googleusercontent.com/oNYm7V31BJ_p7Yf2nNurD5BuvkYMlJcfaf_gbOzeXEJRWYRoKHWvQXH3ScPi-gsgQOGBiLa0xR2ga57MtTnsRRby01_2RUrgcm2UrjM-rdp67whg_EodLF4cPA1jtLWAedcs5lrJ-bg48Na3K2vUO6Kp3hGSKi04Vp3IeAKU7lUi75dL5-taBJXSqhY5ekjQ1Jjw04rRWKWJNqLq0SAwaGDCPGFj6TKBxn9pKqK0B6BruABLuXf3kQsXzvkUW06GFqigeJ1z-_N9hPtcyXZ1MeIW64AHxjcar6Pr9hRoWnp7uwVg2V8XMkzli59rhlW6UhK4sSslcJG6ZmhCqhqwePJACe4DYWwQ_zGkjzj-R251xv0LAsTCfEL8v8JLtL_sQsqAtgF7ohFmlahfbuu-cqZLncHgK1zcTmn5hnLj0dmz93R4SUMmEXISZ8ZG8TwBsRdC_K4GKmvfbzgMR0B6_bN8OdrDSbUMmTMkdT5qddcmVSncbZ-qKbsSK98QzwWT1Ewd43LTImkXuRA8GIdMGSRMGu7Ia7_U1q_MpbLPNgY0aQz9zoZvgoxtBfYk5z0eoawFT8USf_We9I1ZGjjKlMPMJI1DP7a_RbtQk2-4ACMcKAxSJjyKO0uVWwtmv22uu-AAnVVUHeDOiMdWK2VI0xK_k40tlxqBFgUAbxRL70PNilz_xDFbR9iMhA=w1022-h780-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;コンポーネントのstyleを見ると幅300pxと固定になっています。これを幅100%にしたいの上書きします。&lt;/p&gt;
&lt;h1 id="普通にグローバルなcssに書いちゃう"&gt;普通にグローバルなCSSに書いちゃう&lt;/h1&gt;
&lt;p&gt;このカレンダーの幅を指定しているのが、&lt;code&gt;.vdp-datepicker__calendar&lt;/code&gt;クラスです。scopedスタイルでは書かれていないのでグローバルなスタイルとして書いてしまえば上書きできそうです。&lt;/p&gt;
&lt;p&gt;なので、↓のようにしちゃえば万事解決です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;.&lt;span style="color:#a6e22e"&gt;vdp-datepicker__calendar&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;width&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;%&lt;/span&gt; &lt;span style="color:#75715e"&gt;!important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一番シンプル。&lt;/p&gt;
&lt;p&gt;だけど、複数箇所でカレンダーを使いたくて、それぞれ異なったスタイルにしたい場合はこれでは解決できません。&lt;/p&gt;
&lt;h1 id="scopedとは別にstyleを書く"&gt;scopedとは別にstyleを書く&lt;/h1&gt;
&lt;p&gt;Vueコンポーネントのファイルに&lt;code&gt;&amp;lt;style&amp;gt;&amp;lt;/style&amp;gt;&lt;/code&gt;を複数持ってしまうこともできます。片方は&lt;code&gt;scoped&lt;/code&gt;、もう片方はグローバルという感じ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-vue" data-lang="vue"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;style&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;scoped&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/* こっちはコンポーネント用のスタイル */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;.&lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;component&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;style&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;style&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;.&lt;span style="color:#a6e22e"&gt;vdp&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;datepicker__calendar&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;width&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;&lt;span style="color:#f92672"&gt;%&lt;/span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;style&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これだとグローバルなCSSに書くのと変わりません。書くファイルが違うという程度。&lt;/p&gt;
&lt;p&gt;部分的に適用したいという用途がある場合には問題となります。&lt;/p&gt;
&lt;h1 id="scopedなstyleに書く"&gt;scopedなstyleに書く&lt;/h1&gt;
&lt;p&gt;vuejs-datepickerのコンポーネントのルート要素は&lt;code&gt;.vdp-datepicker&lt;/code&gt;です。&lt;/p&gt;
&lt;p&gt;なので、自前のVueコンポーネント内でにdatepickerを置いた場合には、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data-v-356757fe&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data-v-73d4f3b9&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&amp;gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- 自前コンポーネント --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data-v-356757fe&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;vdp-datepicker&amp;#34;&lt;/span&gt;&amp;gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- datepicker --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;vdp-datepicker__calendar&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;position: static;&amp;#34;&lt;/span&gt;&amp;gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- styleをあてたい --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;といった構造になります。&lt;/p&gt;
&lt;p&gt;もちろん↓のようにscopedなstyleを書くと、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-vue" data-lang="vue"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;style&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;scoped&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;.&lt;span style="color:#a6e22e"&gt;vdp&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;datepicker__calendar&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;width&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;&lt;span style="color:#f92672"&gt;%&lt;/span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;style&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;生成されるのは次のようなcssなので、styleが適用されません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;.&lt;span style="color:#a6e22e"&gt;vdp-datepicker__calendar&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#f92672"&gt;data-v-356757fe&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;width&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;%&lt;/span&gt; &lt;span style="color:#75715e"&gt;!important&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そこで&lt;code&gt;vue-loader&lt;/code&gt;のディープセレクタという機能を使います。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://vue-loader-v14.vuejs.org/ja/features/scoped-css.html" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;スコープ付き CSS · vue-loader&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://vue-loader-v14.vuejs.org/../../gitbook/images/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;vue-loader-v14.vuejs.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;scoped スタイルのセレクタを &amp;ldquo;deep&amp;rdquo; にしたい、つまり子コンポーネントに及ぼしたい場合は、&amp;raquo;&amp;gt; コンビネータを使用することができます:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ということで、コードは次のようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-vue" data-lang="vue"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;style&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;scoped&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;.&lt;span style="color:#a6e22e"&gt;vdp&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;datepicker&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; .&lt;span style="color:#a6e22e"&gt;vdp&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;datepicker__calendar&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;width&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;&lt;span style="color:#f92672"&gt;%&lt;/span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;important&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;style&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;が、↓のようにコンパイルされます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;.&lt;span style="color:#a6e22e"&gt;vdp-datepicker&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#f92672"&gt;data-v-356757fe&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; .&lt;span style="color:#a6e22e"&gt;vdp-datepicker__calendar&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;width&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;%&lt;/span&gt; &lt;span style="color:#75715e"&gt;!important&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Vueのデータ属性が親にしか付与されないため、子コンポーネントのスタイルをオーバーライドできるというわけです。&lt;/p&gt;</description></item><item><title>Vue Componentインスタンスの関数を呼び出す方法</title><link>https://blog.piyo.tech/posts/2018-10-22-vuejs-access-instance/</link><pubDate>Mon, 22 Oct 2018 06:13:36 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-22-vuejs-access-instance/</guid><description>&lt;p&gt;Vue Componentの関数、具体的には&lt;code&gt;vuejs-datepicker&lt;/code&gt;の&lt;code&gt;setDate&lt;/code&gt;を呼び出すのってどうするの？というのでちょっと迷ったのでメモ。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/charliekassel/vuejs-datepicker" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/4a1d467fe59f72c5a6d813ac3df85df94be2dd38bb9e5a90ee445606f145cb82/charliekassel/vuejs-datepicker" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - charliekassel/vuejs-datepicker: A simple Vue.js datepicker component. Supports disabling of dates, inline mode, translations&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;A simple Vue.js datepicker component. Supports disabling of dates, inline mode, translations - charliekassel/vuejs-datepicker&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;このdatepickerをインライン表示で使おうとしてるんですが、Todayボタンがなさそうなのが不便なので自分でボタンを置いて作ろうとしました。&lt;/p&gt;
&lt;p&gt;なんですが、設定する方法がわからず。&lt;/p&gt;
&lt;p&gt;最初&lt;code&gt;v-model=&amp;quot;date&amp;quot;&lt;/code&gt;とかやっておけば勝手に反映されるかなと思ったんですが違いましてね。&lt;/p&gt;
&lt;p&gt;なんとなくコードを読んだことでdatepicker自体に&lt;code&gt;setDate&lt;/code&gt;なる関数があることはわかっていたので、それを呼べばいいんだろうと思ったものの、じゃあどうやってアクセスするの？と。&lt;/p&gt;
&lt;p&gt;結論からいうと、&lt;code&gt;ref属性&lt;/code&gt;で大丈夫でした。ドキュメントにも書いてあった。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://vuejs.org/v2/guide/components-edge-cases.html" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://jp.vuejs.org/images/logo.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;特別な問題に対処する — Vue.js&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Vue.js - The Progressive JavaScript Framework&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://jp.vuejs.org/images/icons/android-icon-192x192.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;jp.vuejs.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;なので、Todayボタンを実現するためのコードはこんな感じになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-vue" data-lang="vue"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;template&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;datepicker&lt;/span&gt; &lt;span style="color:#f92672"&gt;v-model&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;date&amp;#34; :inline=&amp;#34;true&amp;#34; :language=&amp;#34;ja&amp;#34; ref=&amp;#34;picker&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;datepicker&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;btn btn-primary&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;@click&lt;/span&gt;&lt;span style="color:#e6db74"&gt;=&amp;#34;todayClick&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;今日&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;template&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Datepicker&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;vuejs-datepicker&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; {&lt;span style="color:#a6e22e"&gt;ja&lt;/span&gt;} &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;vuejs-datepicker/dist/locale&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;date&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Date(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ja&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;components&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Datepicker&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;methods&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;todayClick&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;$refs&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;picker&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setDate&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Date());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>High Sierra以降のmacOSではBoot CampのWindowsからMacを指定して再起動できない</title><link>https://blog.piyo.tech/posts/2018-10-21-boot-camp-high-sierra/</link><pubDate>Sun, 21 Oct 2018 06:59:39 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-21-boot-camp-high-sierra/</guid><description>&lt;p&gt;先日Boot Campを使ってWindowsも入れているMacをSierraからMojaveまでアップグレードしました。&lt;/p&gt;
&lt;p&gt;そしてWindowsを使ってからBootCampのメニューから「OS Xで再起動」を実行すると、**「OS X のブートボリュームが見つかりませんでした」**とのメッセージが！&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/qnCrTD9MCtYR7e9Po-yTPF5s3sWEw-t3yS3QaHu3VRQiXJpUEt0GduB18YFMs4DbeD5Y0wSeFKZstUDfVnZJOYCViiXxL8x5nX1ZEswS1rKmaeZxiXiZXAkXjbQxkxbTV-jgKAfZrAzIWMLEtvVdgb8te9OeG3nLEDjvhUhBxxkSxkobWUe7-WunVejwj094wMXXARu3-fos1d8_h_n8CugGVJTNw4mx7_FwTbhJF0rVj_2JDdW6XN48c-3SB9IUXNCRThoqRyWv5ZXdlJGAsac3ShOj_iXh_3pTLq2oZWw3n2aFlMxBMrTj1s37ldFLOw-4-gGhxK1r67N4UpJrZIjbjSx409ZqB0rvas7YYMQGCDWnPnD7eMMV6e389oLI4c0fFXaYdxdDXGaKcD8CU4JoQbUwFpOMBRd2wI4yWaTwv3Hvh6mg_iT436I_DDRaaHXRfeb1tgM455nez6cGbilYVRWA2skCeOzwRAYO3wT4Z1YrDp_CbGmfBb-E_ah03-JHHZsq5_Q-vIo4KXRdYXUxUerXPP150iWtauM4zOLPV08r6vs0sWGixY3shPyudjn1_Y5qKrK7YAJ7FhzRITXPNClJj8UIDl9Rlum0A5H93qAi9crdBah9nGmok97BfVis2alzqEWjJTDTEwGmVYF1RKHbedAveU48FxfdcCOAgk5HVdcfs82pwA=w455-h251-no"&gt;&lt;img src="https://lh3.googleusercontent.com/qnCrTD9MCtYR7e9Po-yTPF5s3sWEw-t3yS3QaHu3VRQiXJpUEt0GduB18YFMs4DbeD5Y0wSeFKZstUDfVnZJOYCViiXxL8x5nX1ZEswS1rKmaeZxiXiZXAkXjbQxkxbTV-jgKAfZrAzIWMLEtvVdgb8te9OeG3nLEDjvhUhBxxkSxkobWUe7-WunVejwj094wMXXARu3-fos1d8_h_n8CugGVJTNw4mx7_FwTbhJF0rVj_2JDdW6XN48c-3SB9IUXNCRThoqRyWv5ZXdlJGAsac3ShOj_iXh_3pTLq2oZWw3n2aFlMxBMrTj1s37ldFLOw-4-gGhxK1r67N4UpJrZIjbjSx409ZqB0rvas7YYMQGCDWnPnD7eMMV6e389oLI4c0fFXaYdxdDXGaKcD8CU4JoQbUwFpOMBRd2wI4yWaTwv3Hvh6mg_iT436I_DDRaaHXRfeb1tgM455nez6cGbilYVRWA2skCeOzwRAYO3wT4Z1YrDp_CbGmfBb-E_ah03-JHHZsq5_Q-vIo4KXRdYXUxUerXPP150iWtauM4zOLPV08r6vs0sWGixY3shPyudjn1_Y5qKrK7YAJ7FhzRITXPNClJj8UIDl9Rlum0A5H93qAi9crdBah9nGmok97BfVis2alzqEWjJTDTEwGmVYF1RKHbedAveU48FxfdcCOAgk5HVdcfs82pwA=w455-h251-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;MacのアップデートでBoot Campがおかしくなったか？と焦りました。&lt;/p&gt;
&lt;p&gt;しかし、きちんとAppleのサポートドキュメントがありました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://support.apple.com/ja-jp/102450" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://cdsassets.apple.com/live/7WUAS350/images/inline-icons/up-carat-icon.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;MacをmacOSまたはWindowsで再起動する - Apple サポート (日本)&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Boot Campを使ってIntel搭載のMacにMicrosoft Windowsをインストールした後、MacをmacOSまたはWindowsのどちらで起動するかを選択できます。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://support.apple.com/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;support.apple.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;High Sierraから導入されたAPFSによってそれまでと同じ方法が使えなくなってしまったようです。&lt;/p&gt;
&lt;p&gt;起動方法は↓です。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Mac を再起動して、すぐに「option」キーを押し、そのまま押し続けます。&lt;/li&gt;
&lt;li&gt;Startup Manager のウインドウが表示されたら「option」キーを放します。&lt;/li&gt;
&lt;li&gt;macOS または Windows の起動ディスクを選択してから、矢印ボタンをクリックするか「return」キーを押します。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;今まではWindowsを終わりつつ勝手にMacで起動できたのが、Windowsを止めたあとoptionsキーを押しっぱなしにしてStartup Managerを待つという手間ができた分面倒になりました。&lt;/p&gt;
&lt;p&gt;まあ、壊れたわけじゃなくてよかったですけども。&lt;/p&gt;</description></item><item><title>Macのスクロールバー表示設定を「スクロール時に表示」に変えたらすっきりした</title><link>https://blog.piyo.tech/posts/2018-10-18-scrollbar-display-config/</link><pubDate>Thu, 18 Oct 2018 06:48:17 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-18-scrollbar-display-config/</guid><description>&lt;p&gt;Macでは普段トラックパッドを接続して使っているます。
その関係で各種ウィンドウには常にスクロールバーが表示されています。&lt;/p&gt;
&lt;p&gt;それが普通だと思っていました。&lt;/p&gt;
&lt;p&gt;ところが最近iTerm2のプロンプトがずれる問題が多発。
スクロールバーのせいじゃないか？いやむしろターミナルにスクロールバーが出てる事自体やぼったいのではないか？と思うに至りました。&lt;/p&gt;
&lt;p&gt;そういう流れでスクロールバー表示の設定を見直してみたら、見慣れない「スクロール時に表示」の設定が。
これ、元々ありましたっけ？ググってみると少なくとも5年前から設定があるので僕が知らなかっただけですね。&lt;/p&gt;
&lt;p&gt;デフォルトでは**「マウスまたはトラックパッドに基づいて自動的に表示」**されています。&lt;/p&gt;
&lt;p&gt;MacBook本体のトラックパッドのみの場合には、スクロールバーは常には表示されずスクロール時のみふわっと表示されます。
おそらくUSBマウス接続時にはスクロールバーを常に表示する設定なっているのでしょう。
もしかしたらApple製品ではないポインティングデバイスの場合にスクロールバーが現れるのかもしれません。&lt;/p&gt;
&lt;p&gt;USBマウスでも常に表示される必要はない！と思い、設定を変更しました。ここを**「スクロール時に表示」**です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/v0NJTOMzj-MtJiZ4wsQvG_dDl62FMPUKEUlbWqGZXwKN5vXP6I5bVUO2ZPpOW3kKw0P7Q_TfxL6kiy4Qm_zAH11PVgLO2fh8Rjh6m4Gy9y6ymIB_6_0TqF8dDYJ1W9aI_f4JD-3IXteHcr72ykNtwoUZxYK2Nu1cT4fRc_VzEggUzL_qMIBcgA5XuYgeBhtjLYmsO5OPkwg2PvOfgpMRURqmYcxvyYr3T8o3h8JZGuGh2Pnib79yY9dgVE9k5IOKd68VyLQDhmfT3gc1_5y5OwSOX0-IuteMYunc8WjuacF1TBkbl0IiM3OJ9m6v2HX-pfg3iMvDvHMe0fxvlaHrGJiaIXLLHFae7F-D3u6bHaghCeyuVBpbwOIw0KHIycsg9JecvABZSk8oenG6zOr3V-hy4ywfS-c_DfTAf9Z8U_LrSF6MK679HC53V5udOK_E2pKgNcLj9SijGvKAJThfI7FQXBs6FeEmMmXFjVnz19dhEtFntJSuhTYsg52kL3PhbcTjCrXiL7DFSUmFzOPbQBVJjwn0GSy2rpJj5TSzzI4CfMhA8SJpStkqPvJaverEnFg9OKXz4fKeCrS3WdhiF1gR-Id5YCKyt86SBfs9EQi6DsiOMJoKu4FVTOcGn0fQIQpc5f2Z6IOpI0O69uhCdx_T0Tw9wSleh_Boup9g0yXru1goarWD7KBvhg=w902-h913-no"&gt;&lt;img src="https://lh3.googleusercontent.com/v0NJTOMzj-MtJiZ4wsQvG_dDl62FMPUKEUlbWqGZXwKN5vXP6I5bVUO2ZPpOW3kKw0P7Q_TfxL6kiy4Qm_zAH11PVgLO2fh8Rjh6m4Gy9y6ymIB_6_0TqF8dDYJ1W9aI_f4JD-3IXteHcr72ykNtwoUZxYK2Nu1cT4fRc_VzEggUzL_qMIBcgA5XuYgeBhtjLYmsO5OPkwg2PvOfgpMRURqmYcxvyYr3T8o3h8JZGuGh2Pnib79yY9dgVE9k5IOKd68VyLQDhmfT3gc1_5y5OwSOX0-IuteMYunc8WjuacF1TBkbl0IiM3OJ9m6v2HX-pfg3iMvDvHMe0fxvlaHrGJiaIXLLHFae7F-D3u6bHaghCeyuVBpbwOIw0KHIycsg9JecvABZSk8oenG6zOr3V-hy4ywfS-c_DfTAf9Z8U_LrSF6MK679HC53V5udOK_E2pKgNcLj9SijGvKAJThfI7FQXBs6FeEmMmXFjVnz19dhEtFntJSuhTYsg52kL3PhbcTjCrXiL7DFSUmFzOPbQBVJjwn0GSy2rpJj5TSzzI4CfMhA8SJpStkqPvJaverEnFg9OKXz4fKeCrS3WdhiF1gR-Id5YCKyt86SBfs9EQi6DsiOMJoKu4FVTOcGn0fQIQpc5f2Z6IOpI0O69uhCdx_T0Tw9wSleh_Boup9g0yXru1goarWD7KBvhg=w902-h913-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;やはりターミナルはスクロールバーのような野暮ったいのは出てないほうがよいです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/iF1JLfbpiTN1Ul-LJ74js2oWqaWqmZNWBIfxsoI0-d2i_0blg-x750kO3-W1x9NPkd0ceJPl7waW4YtQ4bpk7ZSKqgt-LIYqbUA4VrbYeTpkFhNgzfAPnLylR_9R4idSbuW6tpbXjDvl4gWLvwFbBV0xKoPHLorsTtC1ljgfJWwZW347AaTFwZU9L1BjnNWtnS7bXCg48NfKze_S9KCxut6_V0FhivIZ3A0xnbbvDgdFLWZNDrZyq9XVgR0VZM6VbXqq3npdzFBantLQWNQOQbni55DgYGYKjS9h4A_0i5HkakldO3l4B9p3fYXXdlnn2VG5ERP0Nd5FBudn-363VUVHOmHUvx4EyJJLjzC7WEPru8mO5Ylc5km5jqSIzNubA3FVLNLqTET7qqIKHpET1V7mWCYz0ncQv8tgXMXQHQq7irSvdao7K7zD-FCGxnw0ZUtrNGgzS3v4UZY8ybCA7_Xy4lJHiUbhUxrRXldBz9sjaMXnd7J7SGTm6vBAdRq16eOIfAjN162QWOQpfezd8ag7WJUmmi9ArApRRUzDHKkGisgScx5qtEFJRWO_h9n9rfsRFm5HhNwsSgesUyizI6O-rpPCx7Ee_PiobhFGwHe5JgwBXPVnQzut-LpeK4C9fXJgL5nA55m0HCOyfByU-2bjNf2v9er4-LQV7UgNUIkEWKWRdhPIcPkKcQ=w961-h655-no"&gt;&lt;img src="https://lh3.googleusercontent.com/iF1JLfbpiTN1Ul-LJ74js2oWqaWqmZNWBIfxsoI0-d2i_0blg-x750kO3-W1x9NPkd0ceJPl7waW4YtQ4bpk7ZSKqgt-LIYqbUA4VrbYeTpkFhNgzfAPnLylR_9R4idSbuW6tpbXjDvl4gWLvwFbBV0xKoPHLorsTtC1ljgfJWwZW347AaTFwZU9L1BjnNWtnS7bXCg48NfKze_S9KCxut6_V0FhivIZ3A0xnbbvDgdFLWZNDrZyq9XVgR0VZM6VbXqq3npdzFBantLQWNQOQbni55DgYGYKjS9h4A_0i5HkakldO3l4B9p3fYXXdlnn2VG5ERP0Nd5FBudn-363VUVHOmHUvx4EyJJLjzC7WEPru8mO5Ylc5km5jqSIzNubA3FVLNLqTET7qqIKHpET1V7mWCYz0ncQv8tgXMXQHQq7irSvdao7K7zD-FCGxnw0ZUtrNGgzS3v4UZY8ybCA7_Xy4lJHiUbhUxrRXldBz9sjaMXnd7J7SGTm6vBAdRq16eOIfAjN162QWOQpfezd8ag7WJUmmi9ArApRRUzDHKkGisgScx5qtEFJRWO_h9n9rfsRFm5HhNwsSgesUyizI6O-rpPCx7Ee_PiobhFGwHe5JgwBXPVnQzut-LpeK4C9fXJgL5nA55m0HCOyfByU-2bjNf2v9er4-LQV7UgNUIkEWKWRdhPIcPkKcQ=w961-h655-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;↑がこう↓なりました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/_QAcm6R9RT1C06OO5coO31vDIZ_zB08WeMrep_gzVNJYznNukQezTWz36_w8XfYwm1DHugtIxCI9aI81bcVqkGV6LFujqj7WamdshjDHI_XSnx5MI1KsIPafnYWX5MWlRba8uoq2nKc6pc5-8U9aoGM6sBt5HGVwzWhtvz6CEj2U5_ian9x5RyC9c3yySkFVDqbvEA4AhXEPrST6dnt0GaIHxlEkOAimX78wipOLXyRZHLgsoO1NYK9RKcwmsRm5la_INGLRseF2QNVOLaxKM97qa36BjRvYuZJHHpS2z41Hu9npHn_uW9L3ESoOl_VoAhnzg_5xQf3YnF_CvJ6i_l19V7SMrdQQh3yMJ3y573ojJvELtKyuYYAsi8twBtOKgm9G_4RuqkKCqoikOAJgqdQ473SwuNhy-7fDLQ2ZvxhTmkI3sTXxKXAjRbQRFEADwA4q3nQVf043px84CxsqOzCpEz7gINV5TciXVC29UDYC-Z-uAbaUE2SrTw0d6x7jzUfYoaJzvd1xcHbPJmUWKhLZf-97lkUldv2sXr17fymlABYPSnt2mwYgy3BEiW8HoLdZOj1ot3JQ-c2qZUb52InsHnKj46cWWAIX4bmY6EtQ6zGcadrcz_DNJlOlT2pixHfnZsnchn5kunRCAA8BMaxvDwmfoXcTOSyXTwQrdv1gkT50lcwkgVKlmg=w962-h647-no"&gt;&lt;img src="https://lh3.googleusercontent.com/_QAcm6R9RT1C06OO5coO31vDIZ_zB08WeMrep_gzVNJYznNukQezTWz36_w8XfYwm1DHugtIxCI9aI81bcVqkGV6LFujqj7WamdshjDHI_XSnx5MI1KsIPafnYWX5MWlRba8uoq2nKc6pc5-8U9aoGM6sBt5HGVwzWhtvz6CEj2U5_ian9x5RyC9c3yySkFVDqbvEA4AhXEPrST6dnt0GaIHxlEkOAimX78wipOLXyRZHLgsoO1NYK9RKcwmsRm5la_INGLRseF2QNVOLaxKM97qa36BjRvYuZJHHpS2z41Hu9npHn_uW9L3ESoOl_VoAhnzg_5xQf3YnF_CvJ6i_l19V7SMrdQQh3yMJ3y573ojJvELtKyuYYAsi8twBtOKgm9G_4RuqkKCqoikOAJgqdQ473SwuNhy-7fDLQ2ZvxhTmkI3sTXxKXAjRbQRFEADwA4q3nQVf043px84CxsqOzCpEz7gINV5TciXVC29UDYC-Z-uAbaUE2SrTw0d6x7jzUfYoaJzvd1xcHbPJmUWKhLZf-97lkUldv2sXr17fymlABYPSnt2mwYgy3BEiW8HoLdZOj1ot3JQ-c2qZUb52InsHnKj46cWWAIX4bmY6EtQ6zGcadrcz_DNJlOlT2pixHfnZsnchn5kunRCAA8BMaxvDwmfoXcTOSyXTwQrdv1gkT50lcwkgVKlmg=w962-h647-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>webpackerのwebpack-dev-serverが動くポートを環境変数を使って変更する</title><link>https://blog.piyo.tech/posts/2018-10-14-change-webpacker-dev-server-port/</link><pubDate>Sun, 14 Oct 2018 06:33:04 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-14-change-webpacker-dev-server-port/</guid><description>&lt;p&gt;webpackerを使ったRailsプロジェクトでは多くの場合&lt;code&gt;webpack-dev-server&lt;/code&gt;を同時に動かしておくことが多いと思われます。&lt;/p&gt;
&lt;p&gt;ところがその&lt;code&gt;webpack-dev-server&lt;/code&gt;、配信側もアプリ側もポート番号が&lt;code&gt;3035&lt;/code&gt;に固定されているように見えます。&lt;/p&gt;
&lt;p&gt;これでは複数のRailsアプリケーションを動かしたいときに、ポートが衝突してしまって1つしか&lt;code&gt;webpack-dev-server&lt;/code&gt;を起動できない事態になってしまいます。&lt;/p&gt;
&lt;h1 id="環境変数によってポートを変更する方法"&gt;環境変数によってポートを変更する方法&lt;/h1&gt;
&lt;p&gt;まずは結論から。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rails server&lt;/code&gt;と&lt;code&gt;webpack-dev-server&lt;/code&gt;のコマンドの両方に↓の環境変数を追加すればOKです（たとえばポートを3036に変えるとしましょう）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WEBPACKER_DEV_SERVER_PORT=3036&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WEBPACKER_DEV_SERVER_PUBLIC=localhost:3036&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;（ただ動くようにするためには、&lt;code&gt;webpack-dev-server&lt;/code&gt;側の&lt;code&gt;…_PUBLIC&lt;/code&gt;の環境変数は不要です。ですが、&lt;code&gt;webpack-dev-server&lt;/code&gt;のログには&lt;code&gt;…_PUBLIC&lt;/code&gt;のURLが表示されており、それはそれで気持ち悪いので両方にセットするのが無難です）&lt;/p&gt;
&lt;h1 id="環境変数がどこで有効になるのか"&gt;環境変数がどこで有効になるのか&lt;/h1&gt;
&lt;h2 id="webpack-dev-server"&gt;webpack-dev-server&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;webpack-dev-server&lt;/code&gt;では設定ファイルのyamlを読み込んだあと、ポートなどの値を取りに行きます。
そのとき、環境変数側に値があれば環境変数を優先するというロジックになっていました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/rails/webpacker/blob/master/lib/webpacker/dev_server.rb#L62-L64"&gt;https://github.com/rails/webpacker/blob/master/lib/webpacker/dev_server.rb#L62-L64&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="js側"&gt;JS側&lt;/h2&gt;
&lt;p&gt;Rails起動時に&lt;code&gt;config/webpack/development.js&lt;/code&gt;が読まれます。
このとき、内部では&lt;a href="https://github.com/rails/webpacker/blob/master/package/environments/development.js#L7"&gt;ここのコード&lt;/a&gt;が呼び出されており、さらにその先で環境変数がある場合は優先するような記述があります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/rails/webpacker/blob/master/package/dev_server.js#L13-L14"&gt;https://github.com/rails/webpacker/blob/master/package/dev_server.js#L13-L14&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;p&gt;環境変数が長ったらしいこともあり、これらの環境変数をコマンドに毎回付与するのはあまり実用的じゃありません。
ですが、当面は1回目だけ頑張って入力して、それ以降はコマンド履歴から探すというのが楽そうです。
環境変数で指定するだけであればプロジェクトメンバー全員で統一する必要もありませんしね。&lt;/p&gt;
&lt;p&gt;以下ただの感想です。&lt;/p&gt;
&lt;p&gt;これらの環境変数についてはあまりドキュメントに書かれておらず、結局コードを読んでいくはめになりました。
環境変数名がわかってからリポジトリ内を調べてみると、一部ドキュメントがありましたのでリンクしておきます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/rails/webpacker/blob/227661b546701e107213aa9b6f83451bc89cf7d5/docs/cloud9.md" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/521d9cc8a26447adbbc650dfc768fcfc88746d0aff92f0f40b0212a8fdb56358/rails/webpacker" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;webpacker/docs/cloud9.md at 227661b546701e107213aa9b6f83451bc89cf7d5 · rails/webpacker&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Use Webpack to manage app-like JavaScript modules in Rails - rails/webpacker&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Cloud9だとこう使うよ、というドキュメントにポートなどを個別にしていするためのやり方が載っていました。
そっちかよという気持ちです。&lt;/p&gt;</description></item><item><title>Macのメニューバーにリソースモニターを表示する</title><link>https://blog.piyo.tech/posts/2018-10-13-mac-menu-bar-resource-monitor/</link><pubDate>Sat, 13 Oct 2018 06:05:37 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-13-mac-menu-bar-resource-monitor/</guid><description>&lt;p&gt;MacのメニューバーでCPUやメモリなどのリソース状況を把握するためのツールがあるようなので入れてみることにしました（thanks to 同僚の&lt;a href="https://twitter.com/ruzia"&gt;@ruzia&lt;/a&gt;）。&lt;/p&gt;
&lt;p&gt;気がついたら遅くなっているなんてことがたまにあるので、CPUとメモリの状況を簡単に知るたら良いと考えての導入です。&lt;/p&gt;
&lt;p&gt;こちらからダウンロードしてインストールできます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://member.ipmu.jp/yuji.tachikawa/MenuMetersElCapitan/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="light.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;MenuMeters for OS X El Capitan 10.11 and later&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://member.ipmu.jp/spires.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;member.ipmu.jp&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;昔のWebを感じさせるサイトではありますが、きちんとメンテナンスされておりmacOS Mojaveでも動くことが確認されています。&lt;/p&gt;
&lt;p&gt;また、ソースコードがGitHubにあるのが1つの安心材料にはなりそうです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/yujitach/MenuMeters" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/4c5be9348862bcb91d3099d3ac68ae63a108f63da1070ba8bb83a8046d23f635/yujitach/MenuMeters" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - yujitach/MenuMeters: my fork of MenuMeters by http://www.ragingmenace.com/software/menumeters/&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;my fork of MenuMeters by http://www.ragingmenace.com/software/menumeters/ - yujitach/MenuMeters&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="インストール方法"&gt;インストール方法&lt;/h1&gt;
&lt;p&gt;配布サイトの「Setting up」のあたりにダウンロードリンクがあるのでそこからダウンロードします。というか、Setting upの説明を見れば導入できますね。&lt;/p&gt;
&lt;p&gt;zipがダウンロードされるので展開すると、&lt;code&gt;MenuMeters.prefPane&lt;/code&gt;というファイルが現れます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/MQdfnABl8JtcqsjkDY_5O0hHEhMCiHfxL0zdZA-__CjTYkJtBBiJ6qIA5LjIbBe-axCp_wYZNgv-XFLD2anH51MRZVSIcWRRtFPDiRNm0dnFsacVyxsWQP1gGjb0Kzhsyn7QYXVOuvkwfVc5gP7Ta-5s3tYagOikeoBaYx9VUz9Xh-jOzW0YhII2NIAAYbd3eFWuNodN-o8fOi_bq8Y1w_eeqAd2elt2qL3qR8hFlFVDMvC1g5AdiFSYrEAA78YiULQmgkqKTdNf0lKDzuTHvvjmKtB5GD7Dmzp3IOUS7ii_VDl3DRkHl4POkLA8GA_sVIDLevaU3S8bwQ527za9GFqsrq48Hv7tWD9waiI2HoDngPyjj9Mzv_BwVHOdkv1fw3NSeeU2G_8hc4yWDqPZfAsyWRTUqZsP8kuu7ZqfCX_lJFj77eet46fGNp7HuthHgDQvScrd7d8rVYN4ywqT4jcEbs50YFEVLbphRNnmOJnZc6yGIgGwJZckfknzmVVMXrIpkrIqdjdFONv8Nu_6JO-RsXxN2X1WE5-obIfWXH0tqA9bNURpCzqcUHJfCXBapc4cAtuAERn9rgHDtks30Pq8XUPwIQLeN-iSCmkQhjiQ1PNWRwho1DVi_Wdl8XQC0AvNiWwni1OqyogF_EXsH6oBDGmurFvXRz975_B2KOdDYEbl0lKadO_bmw=w742-h112-no"&gt;&lt;img src="https://lh3.googleusercontent.com/MQdfnABl8JtcqsjkDY_5O0hHEhMCiHfxL0zdZA-__CjTYkJtBBiJ6qIA5LjIbBe-axCp_wYZNgv-XFLD2anH51MRZVSIcWRRtFPDiRNm0dnFsacVyxsWQP1gGjb0Kzhsyn7QYXVOuvkwfVc5gP7Ta-5s3tYagOikeoBaYx9VUz9Xh-jOzW0YhII2NIAAYbd3eFWuNodN-o8fOi_bq8Y1w_eeqAd2elt2qL3qR8hFlFVDMvC1g5AdiFSYrEAA78YiULQmgkqKTdNf0lKDzuTHvvjmKtB5GD7Dmzp3IOUS7ii_VDl3DRkHl4POkLA8GA_sVIDLevaU3S8bwQ527za9GFqsrq48Hv7tWD9waiI2HoDngPyjj9Mzv_BwVHOdkv1fw3NSeeU2G_8hc4yWDqPZfAsyWRTUqZsP8kuu7ZqfCX_lJFj77eet46fGNp7HuthHgDQvScrd7d8rVYN4ywqT4jcEbs50YFEVLbphRNnmOJnZc6yGIgGwJZckfknzmVVMXrIpkrIqdjdFONv8Nu_6JO-RsXxN2X1WE5-obIfWXH0tqA9bNURpCzqcUHJfCXBapc4cAtuAERn9rgHDtks30Pq8XUPwIQLeN-iSCmkQhjiQ1PNWRwho1DVi_Wdl8XQC0AvNiWwni1OqyogF_EXsH6oBDGmurFvXRz975_B2KOdDYEbl0lKadO_bmw=w742-h112-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これを開いて（ダブルクリックして）、Macの設定画面にMenuMetersをインストールします。&lt;/p&gt;
&lt;p&gt;インストールの際、次のような確認のポップアップが現れます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/ouasj4NGK3eS_g5RYHQ82O-o6PiqYJYj0ViXPJwBsmtWZz7bh7nvU3vs16c-QoKpEwzYcyQuk4JhpAM4RlnhClefvnXVCJ-ynmXsZh3TrFjo3Qp7x4lPl0_-vgStxQNB0ZbDFPGBH334WwVq1SUl8LcPKqKQgRsv9LgwhpUp_erk2HgnOudx6y8dFScJG33cTRJWc8mbSg9ISwd963X51yCFennpTShEjl7nmucWQdrmrNW91cRO93JAtiqaPPpWR-GO2rmhfzEuMinj0PZ7_-lS0XD1-l7JPe-g6SBrrrqxzowariC5paX7t5TA2Qao00-lvNugFgen7kFHidU3pbhvHOmJJ5gjykf5FzkcWelScEDmXuzbdNSK6ckryyKSCH3gVfRclgSFldBaWMp2NQ3t4EwXEQFL3bpkQJJGY8zPizFbW2C5wSNnjgGQii-m8CvyLSHGKGdJjmmo9tir_xxUSwnjmBo_KNSIZ3xbS_G44F0rzyzPoo4btXwI6I4m5IZepgWFJImZxlzTOXpdjfV63oCSn_9_UJRJbZew2j81EgH0FQlP8tNNXMh1m4ZQ4kAUfTZOXTl8C5ZqjXy_ZET_AQ8G--kdm5kPOHR7jLk1mz4n2JnrNOYsM2OUX9MIH6PJmxgt-eVby4KS3xeL2_zOARDJzNwCAuwYYfvtZSn6kiSl0viC4g6NCQ=w1320-h525-no"&gt;&lt;img src="https://lh3.googleusercontent.com/ouasj4NGK3eS_g5RYHQ82O-o6PiqYJYj0ViXPJwBsmtWZz7bh7nvU3vs16c-QoKpEwzYcyQuk4JhpAM4RlnhClefvnXVCJ-ynmXsZh3TrFjo3Qp7x4lPl0_-vgStxQNB0ZbDFPGBH334WwVq1SUl8LcPKqKQgRsv9LgwhpUp_erk2HgnOudx6y8dFScJG33cTRJWc8mbSg9ISwd963X51yCFennpTShEjl7nmucWQdrmrNW91cRO93JAtiqaPPpWR-GO2rmhfzEuMinj0PZ7_-lS0XD1-l7JPe-g6SBrrrqxzowariC5paX7t5TA2Qao00-lvNugFgen7kFHidU3pbhvHOmJJ5gjykf5FzkcWelScEDmXuzbdNSK6ckryyKSCH3gVfRclgSFldBaWMp2NQ3t4EwXEQFL3bpkQJJGY8zPizFbW2C5wSNnjgGQii-m8CvyLSHGKGdJjmmo9tir_xxUSwnjmBo_KNSIZ3xbS_G44F0rzyzPoo4btXwI6I4m5IZepgWFJImZxlzTOXpdjfV63oCSn_9_UJRJbZew2j81EgH0FQlP8tNNXMh1m4ZQ4kAUfTZOXTl8C5ZqjXy_ZET_AQ8G--kdm5kPOHR7jLk1mz4n2JnrNOYsM2OUX9MIH6PJmxgt-eVby4KS3xeL2_zOARDJzNwCAuwYYfvtZSn6kiSl0viC4g6NCQ=w1320-h525-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;好みの選択肢を選んでインストールを完了しましょう。&lt;/p&gt;
&lt;h1 id="設定画面"&gt;設定画面&lt;/h1&gt;
&lt;p&gt;MenuMetersの設定画面はこんな感じです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/ndzOm3KkC4Y85LhxhkfNeTN6V2O9CFotnvXkd2tLTrsxJG0p-B7sSEtbdscxL9Tc-yT3qgMjwy4CEYdMuGui792mCw9eh9n4ol9JlKke1Dj3SVw_ykX7duojhkVc6O7-JakzyQv7YSjjXkbyNmR0Leo7GX8ivisdbDGmk0M29OMi2cs57rMmvFtqYPGy2bqKRdcaA2YJg2G3Qeb1oW-NtA-mq-zoDgZMTxazoFljXTk6UA4paYbBg7pEPXbQv6stLr3NY4KsywMKTlOXRajnPCZm4l8B_MiA15MsykSKlNVIP_0rVx_p56CIGAz3F-bKFyTivxx869r0vYL-nKc3m30K-x8UXNrW8y3DLHTryNzllm45IRt3Uin7PZ3K37fKyfbOjnEDbTmPp5Puw_g0LVUcpz77w1Z7sMHXZcbuf5WLH9Pnqy9zDgmrcZCGRuI0jUvcASiAtv6zoM4u5-JVJmV8moFHoqkgbmg1G7aO0dJxst35eIFamMo6KvjU6JaHFpgbR8fhPXrPEWgr8GW6TLUhNG8Gr1soxA3GL2v1Bt922op9t53xzvk1ibC4l_gMnm5QvHXYgT_Z5zuEx-H4j43KnPDIiMRwZo79asVjhaINAOFOoY4mpk_6SKoiCJ4SJZhGK5AEejxb5DiIptP4ezcVtk_hfRUHGwDwThRtSYuagxtRUGXIay_Tbg=w866-h913-no"&gt;&lt;img src="https://lh3.googleusercontent.com/ndzOm3KkC4Y85LhxhkfNeTN6V2O9CFotnvXkd2tLTrsxJG0p-B7sSEtbdscxL9Tc-yT3qgMjwy4CEYdMuGui792mCw9eh9n4ol9JlKke1Dj3SVw_ykX7duojhkVc6O7-JakzyQv7YSjjXkbyNmR0Leo7GX8ivisdbDGmk0M29OMi2cs57rMmvFtqYPGy2bqKRdcaA2YJg2G3Qeb1oW-NtA-mq-zoDgZMTxazoFljXTk6UA4paYbBg7pEPXbQv6stLr3NY4KsywMKTlOXRajnPCZm4l8B_MiA15MsykSKlNVIP_0rVx_p56CIGAz3F-bKFyTivxx869r0vYL-nKc3m30K-x8UXNrW8y3DLHTryNzllm45IRt3Uin7PZ3K37fKyfbOjnEDbTmPp5Puw_g0LVUcpz77w1Z7sMHXZcbuf5WLH9Pnqy9zDgmrcZCGRuI0jUvcASiAtv6zoM4u5-JVJmV8moFHoqkgbmg1G7aO0dJxst35eIFamMo6KvjU6JaHFpgbR8fhPXrPEWgr8GW6TLUhNG8Gr1soxA3GL2v1Bt922op9t53xzvk1ibC4l_gMnm5QvHXYgT_Z5zuEx-H4j43KnPDIiMRwZo79asVjhaINAOFOoY4mpk_6SKoiCJ4SJZhGK5AEejxb5DiIptP4ezcVtk_hfRUHGwDwThRtSYuagxtRUGXIay_Tbg=w866-h913-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;見た目の種類を変えたり色を微調整したりと、それなりに調整可能なオプションがあって好みの設定にできます。&lt;/p&gt;
&lt;p&gt;ちなみに僕はCPUとメモリだけをモニターしています。&lt;/p&gt;
&lt;p&gt;メニューバーの表示はこのようになりました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/p4CnPf3Qj4oXujNA35NCe8-qqKUa1U2AziGGlFATrEyInKipFH9QRNQk9OTu8oiWjawf109sJQv5VNKumqIINCPe1UrDMZ1Y2IJPXYPBeFY7avTBwSIVBoZeV3GTxlMf7d_DtdpteQzSbMvw5zyybZCXlC2Y9E6wQ_hoKRpfPXaEal6JIZLtkpO5akQy84-2mhXSkTnDcQCVz9-4YLDydC3poJ3HdO7AcYBpt2Sp9pCS7zGAL5MsD7PQA8SxXQQG2QOhzWZjwakAnvWAcKBJnEMnTzj_ShPF67xk4I9Qk_rJIBfAJYgzKM2-YCCsRfus9_y11DetADZ5Yw2jKuuNprLigd1PS3qHfjrnbhZjVV7F44D9HuQTcW8nJliYzfQEY4uFozUtjsAvz9Nm8YD1evs4q-sa54HlzErN8Zkomg6dIo_m7qT5nFfT0_roNkeyZBKI9VNFwtwdTKH4OhghUBSBlsAOcWMhoGOmpAf9CELAhEZ3CnYdUg6jpsFSv74Gd0Nf3ljOvIaLuKXhkY9pzEwfkrO8iUjGQ-z3fZOE-OTdO185YHiKE3yqp9Wo979KL-IFDg0A26tfHvmgmTDmW_dQkprITM5Y3ZRnquPZxangU7O_ZutZpvRm7rNraWpaqqW5MT3XS1Fgst8vJqvU-U1jvbFODBm0wKrzm0T3EBETJdgh3d_EvjvyFw=w436-h46-no"&gt;&lt;img src="https://lh3.googleusercontent.com/p4CnPf3Qj4oXujNA35NCe8-qqKUa1U2AziGGlFATrEyInKipFH9QRNQk9OTu8oiWjawf109sJQv5VNKumqIINCPe1UrDMZ1Y2IJPXYPBeFY7avTBwSIVBoZeV3GTxlMf7d_DtdpteQzSbMvw5zyybZCXlC2Y9E6wQ_hoKRpfPXaEal6JIZLtkpO5akQy84-2mhXSkTnDcQCVz9-4YLDydC3poJ3HdO7AcYBpt2Sp9pCS7zGAL5MsD7PQA8SxXQQG2QOhzWZjwakAnvWAcKBJnEMnTzj_ShPF67xk4I9Qk_rJIBfAJYgzKM2-YCCsRfus9_y11DetADZ5Yw2jKuuNprLigd1PS3qHfjrnbhZjVV7F44D9HuQTcW8nJliYzfQEY4uFozUtjsAvz9Nm8YD1evs4q-sa54HlzErN8Zkomg6dIo_m7qT5nFfT0_roNkeyZBKI9VNFwtwdTKH4OhghUBSBlsAOcWMhoGOmpAf9CELAhEZ3CnYdUg6jpsFSv74Gd0Nf3ljOvIaLuKXhkY9pzEwfkrO8iUjGQ-z3fZOE-OTdO185YHiKE3yqp9Wo979KL-IFDg0A26tfHvmgmTDmW_dQkprITM5Y3ZRnquPZxangU7O_ZutZpvRm7rNraWpaqqW5MT3XS1Fgst8vJqvU-U1jvbFODBm0wKrzm0T3EBETJdgh3d_EvjvyFw=w436-h46-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>highlightjs-line-numbers.jsの結果に変な出力 "{1}" が混じる</title><link>https://blog.piyo.tech/posts/2018-10-12-highlight-js-bug/</link><pubDate>Fri, 12 Oct 2018 06:35:34 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-12-highlight-js-bug/</guid><description>&lt;p&gt;このブログではソースコードのシンタックスハイライトに&lt;code&gt;highlight.js&lt;/code&gt;を使っており、行番号の表示には&lt;code&gt;highlightjs-line-numbers.js&lt;/code&gt;を使用しています。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-04-23-add-line-number/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/r0owED5cBmCrD0wSbGkZkndJpmBW1SzYJPnfeb4w6XtcRfmmAr7IEYeo2nsjt3cHb81HlpByTaF4-1_UIXqJrWCfj_m-EaPaoYEszOlNg5qSIgQPbKBiyLQVgylgohhqzlss39qtNC7C6PzmxN0t6i0tAlfN858y1NXR-p9zoGsNDD_ESSfy5xrMOqAyWcav-aqnKjggx4xOnbxK0zA7qw8zVdqztuAfysiwKZI1r39UZ13ina1SjA_TEeC3zdQ132HcK4UuGSyLFmB0W662oCOyZaCz4yaTVN4tcXQm8aGsNn1nyyp7S0MQiJk2Oy-zFHcwh4WAojtUMX9HJa9T_C34B6LNPrgoavxsVumFk76ZmCVguxzLstJ1GUg61u61j1f3g_Yd3f83cTz64mc5Tg3dn4EFrgrBRQ0ZudYx99jZDTC2vYPvlZBTxWzjkWNo0AFEwO2IcZtRf31y07Jqrp5LtXwAayPNEO138CoeS7Bhc88Llw3SM76R2KYu-gbVnbljhq1xYI_bgTT_zNNl561znfF96T9wX8bwfVYEziO8i5iVIK5vUl4l1d_JCi_9Ydy-bK8ooczLhq9hWaw0czTbT8X36HjU8NmfZLDrvZC7JaBhaki5JeMjvQEw0BlchpNVno0IHoZyEe2vv59ZJpu-_agRSarUKA=w1000-h667-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Hugoブログのシンタックスハイライトに行番号をつける - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;このブログ、ソースコードを載せることが多いです。載せたコードについて書く時、◯行目とかいいたくなったので行番号を表示したいなと思いました。 でも、Hugoってどうやってソースコード出してるんだろう？ということで調べてみると、元々は Pygments 、現在はGo実装の Chroma というのを使っているようです。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;あるとき、行番号の処理の結果として&lt;code&gt;{1}&lt;/code&gt;のような不思議な文字列が紛れ込むことに気が付きました。
たとえば↓のようなものです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/H6LC06tY5A9SUIDDgpH5m55f_UahmZMvLdmviTEid_-o-wlTYT-DFKWdVfeFdYIkDqgxRn_EgK74ifuqizZpUVHLbABCzpTt2wxXhSUE-t-eFcLga_F3Gup85AV3QyvEBxSFYAHaCGDJ-F_4s4CPNu4mhTDUmKa-7lUGpcUQblAbivEi70cctVJTIloHKvCGAjg9sXMjiYJ7no1G7L9EBpujDY3AcRO4QJE8BrW8WWnNZOrPL12C2adA8KukMuqJqpPNMRdVAy3wRsHvl4wKw-lkfFxOzR_Isrtj6jiHIxaAS7HdhsbX3Tic1Lj6D_NXp9kjlJJIGJnGeBbjshbPfYVkFW2ui1DFriwUsba-l0XU3v7AYqjpHrEg8H2JukT3jR-Y-K3Ms4UrUObw21PNcgFQk1UM2jismoVRcyd9dh5XfuBAHljRBy7VB9cPb0UmP41-U-El2OxYY2UwVpulxOK2NCmegLoHjYfCqslmBFQ0OHAEUd15_4GVRJpaXwusHMNFwC0qG_OR-GTRESUida1CuYk7J_bIR8cemEiH0V6uXBrxgq2Iue-yq0RPz2Uy70Z5ZTlWXowfvASnsDbj-pSAWN1Ou5mroOlj7X7eFzGQaPcVSMuehwwrhqP-6GfZA1BGOu9EHxxx7VExBm6luv-WFfnSXsJlX_u7EpzNng5WYRCICN41L0VyGQ=w1052-h718-no"&gt;&lt;img src="https://lh3.googleusercontent.com/H6LC06tY5A9SUIDDgpH5m55f_UahmZMvLdmviTEid_-o-wlTYT-DFKWdVfeFdYIkDqgxRn_EgK74ifuqizZpUVHLbABCzpTt2wxXhSUE-t-eFcLga_F3Gup85AV3QyvEBxSFYAHaCGDJ-F_4s4CPNu4mhTDUmKa-7lUGpcUQblAbivEi70cctVJTIloHKvCGAjg9sXMjiYJ7no1G7L9EBpujDY3AcRO4QJE8BrW8WWnNZOrPL12C2adA8KukMuqJqpPNMRdVAy3wRsHvl4wKw-lkfFxOzR_Isrtj6jiHIxaAS7HdhsbX3Tic1Lj6D_NXp9kjlJJIGJnGeBbjshbPfYVkFW2ui1DFriwUsba-l0XU3v7AYqjpHrEg8H2JukT3jR-Y-K3Ms4UrUObw21PNcgFQk1UM2jismoVRcyd9dh5XfuBAHljRBy7VB9cPb0UmP41-U-El2OxYY2UwVpulxOK2NCmegLoHjYfCqslmBFQ0OHAEUd15_4GVRJpaXwusHMNFwC0qG_OR-GTRESUida1CuYk7J_bIR8cemEiH0V6uXBrxgq2Iue-yq0RPz2Uy70Z5ZTlWXowfvASnsDbj-pSAWN1Ou5mroOlj7X7eFzGQaPcVSMuehwwrhqP-6GfZA1BGOu9EHxxx7VExBm6luv-WFfnSXsJlX_u7EpzNng5WYRCICN41L0VyGQ=w1052-h718-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;本来はただの空行なのに変なのが混じっています。&lt;/p&gt;
&lt;p&gt;内容のせいかなと色々試行錯誤しても駄目だったので、さきほど本格的に調べてみることにしました。&lt;/p&gt;
&lt;p&gt;そこでようやく気がついたのが、&lt;code&gt;highlight.js&lt;/code&gt;本体ではなくて、&lt;code&gt;highlightjs-line-numbers.js&lt;/code&gt;のほうだったということ。
本体側だと思いこんでいました。&lt;/p&gt;
&lt;p&gt;そこでissueをあたってみると、まさにこれというissueがありました。
単なる不具合だったようで、すでにマージされ、リリースまでされていました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/yauhenipakala/highlightjs-line-numbers.js/issues/42" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/ceabdd75bd8fb1f1bd5828d6007c4bb016977d3dfbe87591894f413019ef278e/yauhenipakala/highlightjs-line-numbers.js/issues/42" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;PHP Code Block extra line containing &amp;#39;{1}&amp;#39; · Issue #42 · yauhenipakala/highlightjs-line-numbers.js&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;When using php as language and an html element contains a class attribute the result contains an extra line containing only: {1} To Reproduce Minimal bug example: &amp;lt;link ...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;2週間ほど前に対応されており、ちょうどいいタイミングで調べたなーという感じです。&lt;/p&gt;
&lt;p&gt;参照しているファイルを変更することで対応できました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;//cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.3.0/highlightjs-line-numbers.min.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↓&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;//cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.4.0/highlightjs-line-numbers.min.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Y2hE_UQgCMS_FLAtHmrNO-EN3KXV-c8pWI-4oBPWC3hEWr16Dm0qQYy0D3tahK7s7-2HbvRObCUlC2INwBu6yOp48s-piZuD3uUx4Bdkslq3WQ2FixYPHsIHvkGl9wYuj6ghlSDgn_pTPNn8XsaBQjnAxhLqEQvqBTSnfPNSiUAXJJoZpN3AzrrKLq5Sd3BAN0r5BjBsIPtdeyJ04ZbQicIJvFYk2J1y8-AuphR_slyPaDLF8tFIi7DqokRvyex-bHBARBIqrltFUgc3sRAAuif1GoxC6110TrVBXO_6bAFZHgvpfwCPTwJpNedp1XdMBuItw5kpCcb6MV716xq2c6arooKoja1m75Quc_EuOsPnWLflzCutZnrwOPQvO7I6wQcSmlAHXB6XLdaFSDJY4xRiM_kcRN_mlj_B-rMm2peOvqpr_MJTTHTtkJ5dUYZzo22m4ePkTyDCnsimcwKrgfPXMAGl-EgZ8TbysJ8i9961PsV6jhyMZ_Gwy22eJM0GetB16mRCkt_HqJbLUHGdTwS-XnfobcKuE3X60zUOo_9wG1NVXL_Ms5yoxnMAC9KhFJV8k4QhniGxEeXnyrDiDo1eKVTxUtlbqkAHowaR5xF6HO8_ZlDC5dYtP_CbjYDqD6IFdsro7p5KHP5AEf_sfLsoEu4bY0fyR6tHNzg5IFl5m-tVV44s7OO8AQ=w1136-h728-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Y2hE_UQgCMS_FLAtHmrNO-EN3KXV-c8pWI-4oBPWC3hEWr16Dm0qQYy0D3tahK7s7-2HbvRObCUlC2INwBu6yOp48s-piZuD3uUx4Bdkslq3WQ2FixYPHsIHvkGl9wYuj6ghlSDgn_pTPNn8XsaBQjnAxhLqEQvqBTSnfPNSiUAXJJoZpN3AzrrKLq5Sd3BAN0r5BjBsIPtdeyJ04ZbQicIJvFYk2J1y8-AuphR_slyPaDLF8tFIi7DqokRvyex-bHBARBIqrltFUgc3sRAAuif1GoxC6110TrVBXO_6bAFZHgvpfwCPTwJpNedp1XdMBuItw5kpCcb6MV716xq2c6arooKoja1m75Quc_EuOsPnWLflzCutZnrwOPQvO7I6wQcSmlAHXB6XLdaFSDJY4xRiM_kcRN_mlj_B-rMm2peOvqpr_MJTTHTtkJ5dUYZzo22m4ePkTyDCnsimcwKrgfPXMAGl-EgZ8TbysJ8i9961PsV6jhyMZ_Gwy22eJM0GetB16mRCkt_HqJbLUHGdTwS-XnfobcKuE3X60zUOo_9wG1NVXL_Ms5yoxnMAC9KhFJV8k4QhniGxEeXnyrDiDo1eKVTxUtlbqkAHowaR5xF6HO8_ZlDC5dYtP_CbjYDqD6IFdsro7p5KHP5AEf_sfLsoEu4bY0fyR6tHNzg5IFl5m-tVV44s7OO8AQ=w1136-h728-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>textlintでテキスト校正くんのように表記揺れの指摘を行うには</title><link>https://blog.piyo.tech/posts/2018-10-11-textlint-like-kousei-kun/</link><pubDate>Thu, 11 Oct 2018 06:11:35 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-11-textlint-like-kousei-kun/</guid><description>&lt;p&gt;ひとつ前の記事ではtextlintの結果をEmacs上で確認できるようにしました。
次はテキスト校正くんが持っている、用語の表記や漢字の開き方に関する指摘の機能の部分を導入します。&lt;/p&gt;
&lt;h1 id="textlint-rule-prhの導入"&gt;textlint-rule-prhの導入&lt;/h1&gt;
&lt;p&gt;下準備として&lt;code&gt;textlint-rule-prh&lt;/code&gt;導入します。
&lt;code&gt;textlint-rule-prh&lt;/code&gt;は&lt;code&gt;prh&lt;/code&gt;という日本語の自動校正ツールをtextlintから使うための仕組みです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/textlint-rule/textlint-rule-prh" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/6c1967db72ace2660eef8cc5e1b210057f8117cb0646e9751bb1b0df060efa73/textlint-rule/textlint-rule-prh" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - textlint-rule/textlint-rule-prh: textlint rule for prh.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;textlint rule for prh. Contribute to textlint-rule/textlint-rule-prh development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/prh/prh" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/8d2b3f271c7d2b29990d8752dca86b9abec9224af8a21f756e1bca0d9dc64405/prh/prh" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - prh/prh: proofreading helper&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;proofreading helper. Contribute to prh/prh development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;prh&lt;/code&gt;自体が自動校正ツールとしての側面があるものの、おそらく汎用的に使える作りにはなっていません。
textlintのルールにすることで汎用的になっているのだと思われます。&lt;/p&gt;
&lt;p&gt;前の記事の例ではtextlintをグローバルにインストールしていますので、&lt;code&gt;textlint-rule-prh&lt;/code&gt;もグローバルに入れてしまいます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% npm install -g textlint-rule-prh
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="textlint-rule-preset-icsmediaの導入"&gt;textlint-rule-preset-icsmediaの導入&lt;/h1&gt;
&lt;p&gt;続いてテキスト校正くんの内部で使われている&lt;code&gt;textlint-rule-preset-icsmedia&lt;/code&gt;を導入します。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/ics-creative/textlint-rule-preset-icsmedia" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/fcad5867143a3b86dc8e5d938d57d088219f367dce3778aaa8f259902564c4c0/ics-creative/textlint-rule-preset-icsmedia" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - ics-creative/textlint-rule-preset-icsmedia: ics.media で利用されているテキストリントのルールです&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;ics.media で利用されているテキストリントのルールです. Contribute to ics-creative/textlint-rule-preset-icsmedia development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;こちらもグローバルに。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% npm install -g textlint-rule-preset-icsmedia
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;そして今入れた2つを使うように&lt;code&gt;.textlintrc&lt;/code&gt;を更新します。&lt;code&gt;&amp;quot;prh: &amp;quot;&lt;/code&gt;としている箇所がそれです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;rules&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;preset-ja-technical-writing&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;prh&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;rulePaths&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;/usr/local/lib/node_modules/textlint-rule-preset-icsmedia/dict/prh.yml&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;prh&lt;/code&gt;にはルールを記述したファイルが置かれたパスを書きます。&lt;/p&gt;
&lt;p&gt;具体的ルールは↓のURLを見ていただくとわかります。
このプリセットでは複数ファイル分のルールが有効になっています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ics-creative/textlint-rule-preset-icsmedia/tree/master/dict"&gt;https://github.com/ics-creative/textlint-rule-preset-icsmedia/tree/master/dict&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;たとえばファイル&lt;code&gt;prh_web_technology.yml&lt;/code&gt;には次のような記述があり、&lt;code&gt;GitHub&lt;/code&gt;とすべき箇所の表記揺れに指摘をいれてくれるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;rules&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;expected&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;GitHub&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;patterns&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;Github&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;github&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;Git Hub&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;git hub&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="応用できそう"&gt;応用できそう&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;prh&lt;/code&gt;のルール記述は割と簡単なので、オリジナルのルールの追加も容易そうです。
自分が間違えやすいタイポや書き間違いがある方はルールとして追加しておくと良さそうです。&lt;/p&gt;</description></item><item><title>textlintの結果をEmacs上で確認できるようにした</title><link>https://blog.piyo.tech/posts/2018-10-10-textlint-on-emacs/</link><pubDate>Wed, 10 Oct 2018 06:07:31 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-10-textlint-on-emacs/</guid><description>&lt;p&gt;昨日テキスト校正くんが便利だという記事を書いたばかりではありますが、Visual Studio CodeではなくEmacsで書けるのが望ましいです。&lt;/p&gt;
&lt;p&gt;いずれはテキスト校正くんと同様のチェックをかけたいものの、まずは以前textlint導入記事で導入したルールを使って判定するところまで持っていきます。&lt;/p&gt;
&lt;p&gt;Emacs上での結果表示には&lt;code&gt;flycheck&lt;/code&gt;という有名な拡張を使用します。&lt;/p&gt;
&lt;h1 id="textlint再導入"&gt;textlint再導入&lt;/h1&gt;
&lt;p&gt;textlintは&lt;code&gt;.textlintrc&lt;/code&gt;ファイルにより、プロジェクトごとに独自のルールによって文章校正が可能です。
とはいったものの、僕にとってそれはオーバースペックです。
個別のルールまでは不要のため、グローバルにtextlintを導入しました。&lt;/p&gt;
&lt;p&gt;先日の記事でも導入した、&lt;code&gt;textlint-rule-preset-ja-technical-writing&lt;/code&gt;を利用することにします。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-07-23-textlint-ja-for-blog/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/CLwfUprE2KrR0yjxGFFtAgHgYOW_PeH59O6YQhb1P-QlPijiqFpiL258Y98_tBfodN6zCRAi3wYOr5RIhPF0-wM1T_fAwOIIUDiPcSRkPedfLs-4l8a7HYzxDZ0ClUlZhjgVifHxZC9j0dstANPdm0rtk2_Ppkhrzk7n4SJeDlz-jkN_gEt1caDsYVsS3ZFWY6xABGa8qIWmAh9h7h04eElCY6doJtI2XmTQDsZW3ZH_wVKnthHJk_60EfuDfRpkW475jiLzWMpcoV1ZM4DIogolDSu-wDP2mQaXoQ1-3uP4rro-vYT-527U3L513w7nkR_wRWkTIcYbeGUdCM6w8qIORcpTcsJH5j9GBwB1e_HOK9kFaOHLqVFW4OP6g6c2nzNNrrZccLpt2olFtoyUBZU5TMHI0bi1jI1BP_n1QiJnkVzebGVXVWSMrMwvvapVMdLvx5CGV-LRHU0q3bbUy3fJvtPLXw2yv8nQ-vbsyeeliV0B6Ta_4dnsvfugZ1fLsW4_6gF8Qe96C4_MH3aTO8yCxwFDgkNcZhFwib65eFX-K-Cx5Nvf7cZVeq0EQTmY7w-2odr1zxWS--8aGogOud1964CaoMySv5eKtevyO3mUS8E6SWpio6foRxUd2QEImBWC10ZGn0sCNDEnoogUR9GbQt-w5gdzpvE8NA5RPV8oaQQP5qj4MxIJ6w=w1200-h500-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;文書を自動チェックするtextlintを日本語の技術ブログにも使おう - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;日本語にtextlintをかけると便利、という話をチラっと聞いたのでブログに応用すべく導入してみました。 まず、textlint自体がこちら。 https://github.com/textlint/textlint そして、日本語技術文書用のルールプリセットがこちらです。 https://github.com/textlint-ja/textlint-rule-preset-ja-technical-writing ブログに応用するという観点で考えると、Hugoのルートディレクトリがよさそうです。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;今回はグローバルにインストールしますので、&lt;code&gt;-g&lt;/code&gt;オプションをつけてインストールします。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% npm install -g textlint
% npm install -g textlint-rule-preset-ja-technical-writing
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;また、設定ファイルはホームディレクトリに設置します。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% cat ~/.textlintrc
{
&amp;#34;rules&amp;#34;: {
&amp;#34;preset-ja-technical-writing&amp;#34;: true
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これでtextlintの導入は完了ですね。&lt;/p&gt;
&lt;h1 id="flycheckの設定"&gt;flycheckの設定&lt;/h1&gt;
&lt;p&gt;Emacsユーザーでflycheckを使っている方は多いと思われますので、flycheck自体のインストールは割愛します。&lt;/p&gt;
&lt;p&gt;こちらのGistを参考に、&lt;code&gt;markdown-mode&lt;/code&gt;でtextlintを使う設定を↓のように書きました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://gist.github.com/PharaohKJ/cc849ad12ca613fec9604e5e91012ffc" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://github.githubassets.com/assets/gist-og-image-54fd7dc0713e.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;textlint for emacs flycheck&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;textlint for emacs flycheck. GitHub Gist: instantly share code, notes, and snippets.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;gist.github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;(flycheck-define-checker textlint
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;A linter for Markdown.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;:command&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#34;textlint&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;--format&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;unix&amp;#34;&lt;/span&gt; source)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;:error-patterns&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; ((&lt;span style="color:#66d9ef"&gt;warning&lt;/span&gt; line-start (file-name) &lt;span style="color:#e6db74"&gt;&amp;#34;:&amp;#34;&lt;/span&gt; line &lt;span style="color:#e6db74"&gt;&amp;#34;:&amp;#34;&lt;/span&gt; column &lt;span style="color:#e6db74"&gt;&amp;#34;: &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; (id (one-or-more (&lt;span style="color:#a6e22e"&gt;not&lt;/span&gt; (any &lt;span style="color:#e6db74"&gt;&amp;#34; &amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; (message (one-or-more not-newline)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; (zero-or-more &lt;span style="color:#e6db74"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt; (any &lt;span style="color:#e6db74"&gt;&amp;#34; &amp;#34;&lt;/span&gt;) (one-or-more not-newline)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; line-end))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;:modes&lt;/span&gt; (text-mode markdown-mode gfm-mode))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;(add-hook &lt;span style="color:#e6db74"&gt;&amp;#39;markdown-mode-hook&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#39;&lt;/span&gt;(lambda ()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#66d9ef"&gt;setq&lt;/span&gt; flycheck-checker &lt;span style="color:#e6db74"&gt;&amp;#39;textlint&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; (flycheck-mode &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この設定を評価後にMarkdown形式のファイルを開くとチェック結果がきちんと対象箇所に波線で表示されるようになりました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/tT-2W6DZ__Zf3AHRn9h1DugxHzxIFmzWU5tSSK4fioKUPd12lHVmHZyiKeVJC4xxfq2yxonI-PoRkuvqgD-65hz7WNRo_i2WdbEF7WT4yrtFbdSCOokCAnXCetHQdLfmPsNOartFRrvHcDlB9N1QPLeqTbGFjAEhcrU3i82p4oq-IIttRtLvCTsTn1Cw0zrEpR6_X2y-GE3gT7D2Z4DG_gf2kt9Mp8xOJN8Qz76o7aC6mPoG32SeeoIkaqOtNSBa0F-0Uv4mfWljboIWn8BwIKu3U-zrbvkiLNayrZOBTSXdJETW6vopg03BeVdUJdeHbmSG8ETnz5AFTgYqymmRy7idO55C2QN-HvY_MAFO7l7M5fYTrJtPrbgSx5Uaze0ZTqV-0vXfC4ZIseNOsJ7-jgSDymDeJXYsMpWdLHR8aJCwk_8SSnyv7JLt4neFNC3D5HT7ih4dCflspT2nwaU_FUhEuKIMSCv8tvupUhuD3ocJJEpL8Jb2LlqT8hs3nc-rmVfJUC144aJtkHcTHQCSE3lJDihy_Jecoj9cxej0UhdxMzRDgI6V_8YBA1UsBS85l96CxovRmRkM15EnYbIsw6wv_KZ9THYM-QCkvUkSNXIQFH4Xeh3CCkzBrV5FXAf1dXjWL411PRj6QuqYMAC3ldz1LzCsf1rfJ3D1-iaEx9pI7FUs9SgE-MvV-A=w1360-h386-no"&gt;&lt;img src="https://lh3.googleusercontent.com/tT-2W6DZ__Zf3AHRn9h1DugxHzxIFmzWU5tSSK4fioKUPd12lHVmHZyiKeVJC4xxfq2yxonI-PoRkuvqgD-65hz7WNRo_i2WdbEF7WT4yrtFbdSCOokCAnXCetHQdLfmPsNOartFRrvHcDlB9N1QPLeqTbGFjAEhcrU3i82p4oq-IIttRtLvCTsTn1Cw0zrEpR6_X2y-GE3gT7D2Z4DG_gf2kt9Mp8xOJN8Qz76o7aC6mPoG32SeeoIkaqOtNSBa0F-0Uv4mfWljboIWn8BwIKu3U-zrbvkiLNayrZOBTSXdJETW6vopg03BeVdUJdeHbmSG8ETnz5AFTgYqymmRy7idO55C2QN-HvY_MAFO7l7M5fYTrJtPrbgSx5Uaze0ZTqV-0vXfC4ZIseNOsJ7-jgSDymDeJXYsMpWdLHR8aJCwk_8SSnyv7JLt4neFNC3D5HT7ih4dCflspT2nwaU_FUhEuKIMSCv8tvupUhuD3ocJJEpL8Jb2LlqT8hs3nc-rmVfJUC144aJtkHcTHQCSE3lJDihy_Jecoj9cxej0UhdxMzRDgI6V_8YBA1UsBS85l96CxovRmRkM15EnYbIsw6wv_KZ9THYM-QCkvUkSNXIQFH4Xeh3CCkzBrV5FXAf1dXjWL411PRj6QuqYMAC3ldz1LzCsf1rfJ3D1-iaEx9pI7FUs9SgE-MvV-A=w1360-h386-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;校正くんが提供してくれる漢字を開くルールや技術用語に関するルールなどはおいおい取り込んでみたいと考えています。&lt;/p&gt;</description></item><item><title>Visual Studio Code拡張の「テキスト校正くん」で日本語文書を校正する</title><link>https://blog.piyo.tech/posts/2018-10-09-japanese-proofreading/</link><pubDate>Tue, 09 Oct 2018 06:34:56 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-09-japanese-proofreading/</guid><description>&lt;p&gt;先日「エンジニアのための、いますぐ使える文章校正テクニック」という記事がバズっていました。僕はちゃんとしなきゃーと思いながら読んでおりました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://ics.media/entry/19096/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://ics.media/entry/19096/images/eyecatch.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;エンジニアのための、いますぐ使える文章校正テクニック - ICS MEDIA&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;ウェブ制作や開発の仕事で文章を扱う機会は多いはず。書き手は不自然に思っていない文章でも、読み手は違和感をもっていることがあります。文章校正テクニックを覚えるだけでおかしな表現は少なくなり、読みやすい文章を書けるようになります。本記事では、ICS MEDIAで実践している文章校正の一例を紹介します。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://ics.media/_assets/icons/favicon.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;ics.media&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;記事中に紹介されていた「テキスト校正くん」なるVisual Studio Code用の拡張が良さそうに見えたので早速導入してみました。&lt;/p&gt;
&lt;h1 id="テキスト校正くんの導入方法"&gt;テキスト校正くんの導入方法&lt;/h1&gt;
&lt;p&gt;まずVisual Studio Code（以下Code）を入手する必要があります。こちらのページから各環境ごとのパッケージやインストーラーをダウンロードします。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://code.visualstudio.com/Download" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://code.visualstudio.com/opengraphimg/opengraph-home.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Download Visual Studio Code - Mac, Linux, Windows&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows. Download Visual Studio Code to experience a redefined code editor, optimized for building and debugging modern web and cloud applications.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://code.visualstudio.com/assets/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;code.visualstudio.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;僕はCodeインストール済ではあったものの普段使いはしていませんでした。なので設定ファイルなどをすべて削除し、Code自体をアンインストールしてから再度インストールしました。&lt;/p&gt;
&lt;p&gt;続いてCode内、拡張機能の画面からテキスト校正くんを入れます。これだけでOKでした。&lt;/p&gt;
&lt;p&gt;ちなみにテキスト校正くんのページはこちらです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=ICS.japanese-proofreading" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://ICS.gallerycdn.vsassets.io/extensions/ics/japanese-proofreading/1.3.0/1681289997233/Microsoft.VisualStudio.Services.Icons.Default" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;テキスト校正くん - Visual Studio Marketplace&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Extension for Visual Studio Code - VS CodeでテキストファイルやMarkdownファイルの日本語の文章をチェックする拡張機能&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;span class="truncate"&gt;marketplace.visualstudio.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="実際に使ってみた"&gt;実際に使ってみた&lt;/h1&gt;
&lt;p&gt;テキスト校正くんの指摘対象となる単語や文を適当にいれてみました。雰囲気はこのような感じ。&lt;/p&gt;
&lt;p&gt;リアルタイムに波線が引かれ、エラー表示のショートカットやマウスオーバーにより内容を確認できます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/_1miGMmsln8tbjL4lUWgrIBaBhuobUI0-i5kD13rMrHPN_hxsqONlrdNBmz6_vs0Bk3zLS1N_o4EroR2qeefvfZEC1Bzn4xm0BUCH-p_ax0uldO5Ix5g6XXxXPMqK1lIplvOBKIM1OF0Iy84TtoriD5GCRPxuLlM6arTI9-YV_UwhS3A7taaDIFEEgD4dWENLo_zZBGc8A1Isp9tg1zKv5zqMt1EFqNVExq5nyZe9baoN1KFXB8TJ7NaP4UgUk0rcTD7z1ypNeLnwnPG836gx99lpF9hIQnSnK2bt_OQeg6UmgE1hKyBF2ix-QFgn2chNjJDLWIruyByukn3ldbb-_mImJIzzNp3YWxQqgkxTuVfnohHWvjDY9LWlaQOjrxqiKL6kKUfJ7ZMVTSXs6tLYnbsA9UUqWgJOFwd7JV8ol4ULyup28oTfZ2mEMGLsWIx0nS_nRrKvwgwp1j2O7zQRmNKGRVO3UaSQ-xOBRSHZ1_7hrHKlqwNifrfpfsNsbvU5oym1amIupcQKY481s7YBh3hjoqBfq0Bdm5_FmjLST-PAOoMo6s7K9jCoHo8irotOlTjCH9M7ZR8l9Sp3d3fJ3JKaHldHuFr6f0LreGDm5lbeSdk06g1z-j9d-ngP2CzDH0QsLbuf-xZuyeH5X1QEX2PqMBqns9sUlnAdj4AunSq-T_YujpqL6V8Jg=w529-h194-no"&gt;&lt;img src="https://lh3.googleusercontent.com/_1miGMmsln8tbjL4lUWgrIBaBhuobUI0-i5kD13rMrHPN_hxsqONlrdNBmz6_vs0Bk3zLS1N_o4EroR2qeefvfZEC1Bzn4xm0BUCH-p_ax0uldO5Ix5g6XXxXPMqK1lIplvOBKIM1OF0Iy84TtoriD5GCRPxuLlM6arTI9-YV_UwhS3A7taaDIFEEgD4dWENLo_zZBGc8A1Isp9tg1zKv5zqMt1EFqNVExq5nyZe9baoN1KFXB8TJ7NaP4UgUk0rcTD7z1ypNeLnwnPG836gx99lpF9hIQnSnK2bt_OQeg6UmgE1hKyBF2ix-QFgn2chNjJDLWIruyByukn3ldbb-_mImJIzzNp3YWxQqgkxTuVfnohHWvjDY9LWlaQOjrxqiKL6kKUfJ7ZMVTSXs6tLYnbsA9UUqWgJOFwd7JV8ol4ULyup28oTfZ2mEMGLsWIx0nS_nRrKvwgwp1j2O7zQRmNKGRVO3UaSQ-xOBRSHZ1_7hrHKlqwNifrfpfsNsbvU5oym1amIupcQKY481s7YBh3hjoqBfq0Bdm5_FmjLST-PAOoMo6s7K9jCoHo8irotOlTjCH9M7ZR8l9Sp3d3fJ3JKaHldHuFr6f0LreGDm5lbeSdk06g1z-j9d-ngP2CzDH0QsLbuf-xZuyeH5X1QEX2PqMBqns9sUlnAdj4AunSq-T_YujpqL6V8Jg=w529-h194-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ところで僕は先日&lt;code&gt;textlint&lt;/code&gt;を使ってみようといった内容の記事を書いています。そのときはコマンドラインから確認するのみで、このようにエディター上で確認できるようにはしていませんでした。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-07-23-textlint-ja-for-blog/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/CLwfUprE2KrR0yjxGFFtAgHgYOW_PeH59O6YQhb1P-QlPijiqFpiL258Y98_tBfodN6zCRAi3wYOr5RIhPF0-wM1T_fAwOIIUDiPcSRkPedfLs-4l8a7HYzxDZ0ClUlZhjgVifHxZC9j0dstANPdm0rtk2_Ppkhrzk7n4SJeDlz-jkN_gEt1caDsYVsS3ZFWY6xABGa8qIWmAh9h7h04eElCY6doJtI2XmTQDsZW3ZH_wVKnthHJk_60EfuDfRpkW475jiLzWMpcoV1ZM4DIogolDSu-wDP2mQaXoQ1-3uP4rro-vYT-527U3L513w7nkR_wRWkTIcYbeGUdCM6w8qIORcpTcsJH5j9GBwB1e_HOK9kFaOHLqVFW4OP6g6c2nzNNrrZccLpt2olFtoyUBZU5TMHI0bi1jI1BP_n1QiJnkVzebGVXVWSMrMwvvapVMdLvx5CGV-LRHU0q3bbUy3fJvtPLXw2yv8nQ-vbsyeeliV0B6Ta_4dnsvfugZ1fLsW4_6gF8Qe96C4_MH3aTO8yCxwFDgkNcZhFwib65eFX-K-Cx5Nvf7cZVeq0EQTmY7w-2odr1zxWS--8aGogOud1964CaoMySv5eKtevyO3mUS8E6SWpio6foRxUd2QEImBWC10ZGn0sCNDEnoogUR9GbQt-w5gdzpvE8NA5RPV8oaQQP5qj4MxIJ6w=w1200-h500-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;文書を自動チェックするtextlintを日本語の技術ブログにも使おう - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;日本語にtextlintをかけると便利、という話をチラっと聞いたのでブログに応用すべく導入してみました。 まず、textlint自体がこちら。 https://github.com/textlint/textlint そして、日本語技術文書用のルールプリセットがこちらです。 https://github.com/textlint-ja/textlint-rule-preset-ja-technical-writing ブログに応用するという観点で考えると、Hugoのルートディレクトリがよさそうです。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;コマンドラインで都度実行ですと、そもそも実行するのを忘れがちですし、指摘箇所を探すのも手間がかかります。手軽さと継続性に難ありです。&lt;/p&gt;
&lt;p&gt;テキスト校正くんのようにエディター上で確認できれば、すぐさま修正しようという気になるがとても良いです。&lt;/p&gt;
&lt;p&gt;Codeを常用していないのが唯一残念なところです。テキスト校正くんは内部では&lt;code&gt;textlint&lt;/code&gt;を使用しているはずなので工夫すれば僕が常用するEmacsでも使えるかもしれません。&lt;/p&gt;</description></item><item><title>Kindleの連続スクロールが最高！電子書籍の縦スクロールがかなりオススメです</title><link>https://blog.piyo.tech/posts/2018-10-08-kindle-continuous-scrolling/</link><pubDate>Mon, 08 Oct 2018 06:43:36 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-08-kindle-continuous-scrolling/</guid><description>&lt;p&gt;電子書籍はなんとなく読みにくくて、ネット記事なら読みやすいという感覚を持ったことがある人はいるでしょうか。僕は数年前にそのように思ったことがあって、1つの仮説に辿りつきました。&lt;/p&gt;
&lt;p&gt;それはページのめくり方（スクロール方向）です。&lt;/p&gt;
&lt;p&gt;ページめくり型の電子書籍は明示的にページ送りをしなければいけません。そもそもその動き自体、読む流れに対して抵抗があります。&lt;/p&gt;
&lt;p&gt;その上、ページをめくってしまうため少し前の内容をなんとなく参照するということができません。もう一度読み直したいときは前のページに戻って、また次のページに戻らねばなりません。&lt;/p&gt;
&lt;p&gt;それに対してネットの記事は縦に長いことが多いのですが、スマートフォンでは自然に読めます。目の動きに合わせて画面も同じ方向にスクロールしていけばいいので読む動きと実際のデバイスの操作との間に抵抗がありません。&lt;/p&gt;
&lt;p&gt;少し前の内容を確認したい場合、その部分は画面内にあることが多く、軽く目を動かすだけで参照できるでしょう。&lt;/p&gt;
&lt;p&gt;この仮説を証明するために縦スクロール型の電子書籍リーダーはないものか、と当時目を皿のようにしてWebやアプリストアを探し回った記憶があります。&lt;/p&gt;
&lt;p&gt;そのときに見つけたこちらのアプリ「Gerty」はepubのようなフォーマットを縦クスロールで読むことができる貴重なアプリでした。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://itunes.apple.com/us/app/gerty-ebook-reader-for-epub-journal-notes-photos-and-maps/id901817060?mt=8" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;itunes.apple.com →&lt;/span&gt;&lt;span&gt;https://itunes.apple.com/us/app/gerty-ebook-reader-for-epub-journal-notes-photos-and-maps/id901817060?mt=8&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;実際にこのアプリを使って読んでみて、仮説は正しいのだなと実感ができました。やはり縦スクロールのほうがスムーズに読めました。&lt;/p&gt;
&lt;p&gt;そんな中、KindleのiOS版アプリが縦スクロール（アプリ内では連続スクロールと表記）に対応していることを知りました。たまたま気がついたのがきっかけでしたが、更新履歴をふり返ってみると2018年の4月か5月ごろには対応されていたようです。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p lang="ja" dir="ltr"&gt;全然知らん間にiOSのKindleで縦スクロールできるようになってるーーー！！！最高じゃん&lt;/p&gt;&amp;mdash; Hiromasa Ohno（ぴー） (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/status/1048090584815030272?ref_src=twsrc%5Etfw"&gt;October 5, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;設定方法は、Kindleアプリの文字サイズなどを変更するボタンの中に。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Gk4oxaULmwqZ5CXkATCc8aB9bh2xNhiI2kjhFw9jWIAjScyy7BY-ZpjjU-KGaQg5ARGJrYzpgCRLHFnsFssSvPXqhchGT0jz-KDoRJofe-nXOCYOcWuKNGLTa1nninhjHoGkIGXC6FsnZoyXn0LXGlwgRDSB412N9_9lVnH8C9mFhihCVjScj31SQIJGvMF32LTjViiSH4lkPhe4iSTGW4YdwMojNxAoF3-xLa-VxfCZTIrKq_0hMRds0-brzTs4PI46w2A_Mk1sCZl4w8m4lOCV9Su4Gr5dbaWP0clq30Spa1d5LhaaRt1ZDt69rwSpDVxuQz56IKL86WD6R4bNiPebCNRcfdyddnlFUhh-5k04AN6j4EJZB4HxC-wJSBBPEKPLNMKnKDjzpW6NANsQEZRB3IIfuf8zWAR1VZJdwTUJTkyjI1fx3wucG-RJ8zIERy2evAGdQOJYHlSRxKyAG3p0pXq5vxweImZHYx-VC6CcP12t2Azpb76Hu-3w2VkieYNUOJPbDQCsg62id5EagXDWEelHzc7BAdSUpwpwJx1pBq1-URh_GN2-qNVGQQfQxmhs7jjP-w0Lx7Jwd9Buf2uXufLAkU1VVBRKCd4dn5BRCM1UlWznMq8gLiI1ubRjdkHwqxVDsn3gjNENcBDJE02aGYpjI9mD_kgWu9RhfxnGMMH8fqcXEjPB=w500-h533-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Gk4oxaULmwqZ5CXkATCc8aB9bh2xNhiI2kjhFw9jWIAjScyy7BY-ZpjjU-KGaQg5ARGJrYzpgCRLHFnsFssSvPXqhchGT0jz-KDoRJofe-nXOCYOcWuKNGLTa1nninhjHoGkIGXC6FsnZoyXn0LXGlwgRDSB412N9_9lVnH8C9mFhihCVjScj31SQIJGvMF32LTjViiSH4lkPhe4iSTGW4YdwMojNxAoF3-xLa-VxfCZTIrKq_0hMRds0-brzTs4PI46w2A_Mk1sCZl4w8m4lOCV9Su4Gr5dbaWP0clq30Spa1d5LhaaRt1ZDt69rwSpDVxuQz56IKL86WD6R4bNiPebCNRcfdyddnlFUhh-5k04AN6j4EJZB4HxC-wJSBBPEKPLNMKnKDjzpW6NANsQEZRB3IIfuf8zWAR1VZJdwTUJTkyjI1fx3wucG-RJ8zIERy2evAGdQOJYHlSRxKyAG3p0pXq5vxweImZHYx-VC6CcP12t2Azpb76Hu-3w2VkieYNUOJPbDQCsg62id5EagXDWEelHzc7BAdSUpwpwJx1pBq1-URh_GN2-qNVGQQfQxmhs7jjP-w0Lx7Jwd9Buf2uXufLAkU1VVBRKCd4dn5BRCM1UlWznMq8gLiI1ubRjdkHwqxVDsn3gjNENcBDJE02aGYpjI9mD_kgWu9RhfxnGMMH8fqcXEjPB=w500-h533-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;連続スクロールのスイッチをONにすればOK。対応している形式（一部の横書き形式）の場合は縦スクロールになってくれるはずです。&lt;/p&gt;
&lt;p&gt;オススメですのでぜひお試しを。&lt;/p&gt;</description></item><item><title>RubyMineでタブを分割したペイン間で移動するプラグインを発見してめちゃくちゃ捗る</title><link>https://blog.piyo.tech/posts/2018-10-07-rubymine-move-tab/</link><pubDate>Sun, 07 Oct 2018 06:05:51 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-07-rubymine-move-tab/</guid><description>&lt;p&gt;RubyMineのところはJetBrainsの各種エディターと読み替えてもらって大丈夫です。&lt;/p&gt;
&lt;p&gt;私、メインで使っているEmacsでたくさんペイン分割をする習性がありまして、RubyMine等々でも最大2x2ぐらいには分割して使っています。RubyMineではこれらの分割した部分のことをSplitterというらしいです。&lt;/p&gt;
&lt;p&gt;Splitter分割やSplitter間のフォーカス移動、Splitter間のファイルタブ移動などの操作はどうにかしてマウスを使わずに行いたいものです。Splitterの分割やSplitter間のフォーカス移動はRubyMineにメニューがあるため、設定からキーボードショートカットを設定すればOKです。&lt;/p&gt;
&lt;p&gt;それぞれ↓のようなメニューに対応しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Split Horizontally（上下に分割）&lt;/li&gt;
&lt;li&gt;Split Vertically（左右に分割）&lt;/li&gt;
&lt;li&gt;Goto Next Splitter（次のSplitterにフォーカスを移動）&lt;/li&gt;
&lt;li&gt;Goto Previous Splitter（前のSplitterにフォーカスを移動）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ですが、タブをSplitter間で移動する方法が用意されていません。タブを移動というのは、たとえば左右に分割していたときに、左側Splitterで開いているファイルを右側に移すというようなものです。&lt;/p&gt;
&lt;p&gt;僕はこれを頻繁に行います。複数ファイル見比べながらやりたいですし。&lt;/p&gt;
&lt;p&gt;で、調べてみるとどうやら3rd-partyのプラグインとしては存在しているらしいことがわかりましたので、導入してみました。&lt;/p&gt;
&lt;p&gt;まずは設定メニューからプラグインへ行き、「Browse Repositories」を選びます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/WBRMmSqBZUeH6YAaQUo67L0g2LYiRwxakh9-geyUEwXUuMhO1EBevGjIFWnnImhBBrspH2A-Hk5BAKui7hNGIWrSlV8XYeVzwoZ0poG7eD2C_jFAGpYd_yc2oPT3TP51OmewYGEL8BCKE0aQ-LpEAwTmCL3CwUVswd6painNhxJqjfzk0BZG6ihkoPC3yhX2MU0Y5kUEKkImHWfM-mGVFhGMkn8gDCEhrBmgyH_Zg8mrIgEYL4f5TGTGTOKNfbnWcxseK9TGNryZq3jNYr2QuI_bI6JU_BcDlR2zPGD-HVquXIoQR3EwHhn2AkA8w2XDzCeyrYHle8oKpk9gCgBp33mWFgfSquhqO3HyAmqx6kz88TOjR-G99Ul-7IHIZ3AnMdHTmNHxja7bPJFAlY9fhUjKy73khFXOxSAU937IUSjAKpN96XwdvViUjl5MQ2-SD6mGAQaXNv8ImKNBvrVnlUqfN8YFF_qGyg6wcsAbXPZmus2-nJEa_u1U_tY5o8HKx4M3HhLh8JDEuq-IfRwHyHoLM5Ksh6k2XyO0oyOYjpKreytuiD7lMpEgY2pAjNl7Hsup_6T4b0UnQSx09jU9-8VNIwoK8DP_8OyJ883BDG9dJs5jd7mjdfe5yVrRNRHl3byQUbMhelQ5djgNFoWQ5V2lWyUy3tZP6WiL7UMoyJA4L_tmg-YO0yT4=w832-h574-no"&gt;&lt;img src="https://lh3.googleusercontent.com/WBRMmSqBZUeH6YAaQUo67L0g2LYiRwxakh9-geyUEwXUuMhO1EBevGjIFWnnImhBBrspH2A-Hk5BAKui7hNGIWrSlV8XYeVzwoZ0poG7eD2C_jFAGpYd_yc2oPT3TP51OmewYGEL8BCKE0aQ-LpEAwTmCL3CwUVswd6painNhxJqjfzk0BZG6ihkoPC3yhX2MU0Y5kUEKkImHWfM-mGVFhGMkn8gDCEhrBmgyH_Zg8mrIgEYL4f5TGTGTOKNfbnWcxseK9TGNryZq3jNYr2QuI_bI6JU_BcDlR2zPGD-HVquXIoQR3EwHhn2AkA8w2XDzCeyrYHle8oKpk9gCgBp33mWFgfSquhqO3HyAmqx6kz88TOjR-G99Ul-7IHIZ3AnMdHTmNHxja7bPJFAlY9fhUjKy73khFXOxSAU937IUSjAKpN96XwdvViUjl5MQ2-SD6mGAQaXNv8ImKNBvrVnlUqfN8YFF_qGyg6wcsAbXPZmus2-nJEa_u1U_tY5o8HKx4M3HhLh8JDEuq-IfRwHyHoLM5Ksh6k2XyO0oyOYjpKreytuiD7lMpEgY2pAjNl7Hsup_6T4b0UnQSx09jU9-8VNIwoK8DP_8OyJ883BDG9dJs5jd7mjdfe5yVrRNRHl3byQUbMhelQ5djgNFoWQ5V2lWyUy3tZP6WiL7UMoyJA4L_tmg-YO0yT4=w832-h574-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そしてここで「Next Splitter」などと検索をすると、「Tab to Next Splitter」なるプラグインが現れます。これをインストールしてRubyMineを再起動しましょう。途中3rd-partyのプラグインを入れていいかい？みたいな確認が入るのでそれを許可してあげましょう。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/8Ju9oJePgoqBbkgZ-1J3ESmXNMieR8sPm9k3d_4nS2f4_0qDi8iktKWvV77NOGzM5KSg0D1KmeR2U9cnESupS_T3rOZ11mEoTxWwk4hBRQ63uCRhyKrxUwWpizYGMH2w8oUeyZfLw2vM2rNMurcot0BkVOiEdwRrzUt5vQvCKx1HzZRlUR3NxcAZF_3bKB1Fbg4j0Ne0hvgfl7nGRnloyf6jT0XQN43DJWeju6IsusFE-8tRWQNx02x4XYjEhRBtXT8vWCVzzKX7IKX1oEAzYnvzHl-jLk9HS2E4m4NRlItXxCFn4YyvR8_FN7Qq92FR8lVm4hR7sIdztHBucm0Ev98J22IJB9y70h6MHjCECLE19SLx0lxdBVoF39dL96Z10I0iub27tFreI02oO_jTfXsAoE1JiyWX_9qYW3VVYsbHQUcZu7c7Jhg1g4YK1-diORaVeBd10bKNl5NQzncqkOwrU4P9qsgo2ju296mzYsDmqq1UG6eJSXH9W1nAxwhvhTXvHM-qW4S4lkd3sI1xlhpEXh05tYPwp7Lp0Ue7vC6NhoGcgoVPleSSkssXxpj9YETS67FESSVIE904nLjAlLA79CwiGSDbLiQcMIHX-FZs93p7VQgP28jM835DrcNVRB54swCMf4aJLKPtMm-nzq1N9K_9Ey9DKMn07gUPMAUz3QThYIalr6_M=w1310-h926-no"&gt;&lt;img src="https://lh3.googleusercontent.com/8Ju9oJePgoqBbkgZ-1J3ESmXNMieR8sPm9k3d_4nS2f4_0qDi8iktKWvV77NOGzM5KSg0D1KmeR2U9cnESupS_T3rOZ11mEoTxWwk4hBRQ63uCRhyKrxUwWpizYGMH2w8oUeyZfLw2vM2rNMurcot0BkVOiEdwRrzUt5vQvCKx1HzZRlUR3NxcAZF_3bKB1Fbg4j0Ne0hvgfl7nGRnloyf6jT0XQN43DJWeju6IsusFE-8tRWQNx02x4XYjEhRBtXT8vWCVzzKX7IKX1oEAzYnvzHl-jLk9HS2E4m4NRlItXxCFn4YyvR8_FN7Qq92FR8lVm4hR7sIdztHBucm0Ev98J22IJB9y70h6MHjCECLE19SLx0lxdBVoF39dL96Z10I0iub27tFreI02oO_jTfXsAoE1JiyWX_9qYW3VVYsbHQUcZu7c7Jhg1g4YK1-diORaVeBd10bKNl5NQzncqkOwrU4P9qsgo2ju296mzYsDmqq1UG6eJSXH9W1nAxwhvhTXvHM-qW4S4lkd3sI1xlhpEXh05tYPwp7Lp0Ue7vC6NhoGcgoVPleSSkssXxpj9YETS67FESSVIE904nLjAlLA79CwiGSDbLiQcMIHX-FZs93p7VQgP28jM835DrcNVRB54swCMf4aJLKPtMm-nzq1N9K_9Ey9DKMn07gUPMAUz3QThYIalr6_M=w1310-h926-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これにより、「Tab to Next Splitter」というコマンド（？）が現れるので好みのショートカットを設定して完成です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/U8NhzLoVKsPkTTvav_Y5kKR0OhbeZSRRH8R5-4YJrf8Hsnq8UmNaQHNw3fY5A12ZrAQnmYOM16b7yo1-J6yszfXqNQ4Q-xL-rtD4qLWnBb13FIoEg2YwCHxSfCrZzD2biYHmbMdPuUHr-sVmelCOuCHa-k8M9CTeV6o3Odb22jt0UfejB5r9Pm20mfdJ_fLJcl-7fDyzeac67mT7lV-oG_SmukrSrNIondovxEbtiRbCjJPzxoedmhCHvcXvMITsl_yCwfiQn_u3zoBPKYIH3uERrWiofUxxThHhKmIQ7bpfwj_rITq-Yeyb-qUzpZI2hc5S9lnmptxU3chvVvJCLhkOjKjSlOHc1GyZMqWhMVJsMfdJ_baRRNQlbpEZzi-O9pqDrbuTm2S3QR5O6XfO7r1pmsTqW-sS83xDAuPEmsW_ZnuYj3SktzpSPkoo20DpMzvdOkGgvuDE62KmsuV4Yy6NrPoTD7_8FUgYDAbHVKYUB4RE3zOMT4sIQgzvPSonsttBhadOv6cBHq1dVk6U8VZNpXRkw_q0DZNW6042xyHekU3tn982Ry0JrE0vj5KZapKHk_lE1Tjw0RC5hRNBuDfvoljaqRdI1prhrTbibs9lrHmSYW_6Oie0AM2SzQfWV6D5L80-Yankud4Jj7C0vur2qQXoJ_3hC3BM9nDQ0vaMQnSGrGnj0vMQ=w510-h300-no"&gt;&lt;img src="https://lh3.googleusercontent.com/U8NhzLoVKsPkTTvav_Y5kKR0OhbeZSRRH8R5-4YJrf8Hsnq8UmNaQHNw3fY5A12ZrAQnmYOM16b7yo1-J6yszfXqNQ4Q-xL-rtD4qLWnBb13FIoEg2YwCHxSfCrZzD2biYHmbMdPuUHr-sVmelCOuCHa-k8M9CTeV6o3Odb22jt0UfejB5r9Pm20mfdJ_fLJcl-7fDyzeac67mT7lV-oG_SmukrSrNIondovxEbtiRbCjJPzxoedmhCHvcXvMITsl_yCwfiQn_u3zoBPKYIH3uERrWiofUxxThHhKmIQ7bpfwj_rITq-Yeyb-qUzpZI2hc5S9lnmptxU3chvVvJCLhkOjKjSlOHc1GyZMqWhMVJsMfdJ_baRRNQlbpEZzi-O9pqDrbuTm2S3QR5O6XfO7r1pmsTqW-sS83xDAuPEmsW_ZnuYj3SktzpSPkoo20DpMzvdOkGgvuDE62KmsuV4Yy6NrPoTD7_8FUgYDAbHVKYUB4RE3zOMT4sIQgzvPSonsttBhadOv6cBHq1dVk6U8VZNpXRkw_q0DZNW6042xyHekU3tn982Ry0JrE0vj5KZapKHk_lE1Tjw0RC5hRNBuDfvoljaqRdI1prhrTbibs9lrHmSYW_6Oie0AM2SzQfWV6D5L80-Yankud4Jj7C0vur2qQXoJ_3hC3BM9nDQ0vaMQnSGrGnj0vMQ=w510-h300-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これができなくてしばらく我慢してましたが、調べてみるもんですね。&lt;/p&gt;</description></item><item><title>Xcode 10へアップデート後にビルドできなくなったReact Nativeアプリへの対応</title><link>https://blog.piyo.tech/posts/2018-10-06-build-faild-after-xcode10-update/</link><pubDate>Sat, 06 Oct 2018 06:34:16 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-06-build-faild-after-xcode10-update/</guid><description>&lt;p&gt;Xcodeが10にアップデートされたあと、React Nativeの既存プロジェクトのビルドが通らなくなりました。&lt;/p&gt;
&lt;p&gt;たとえば↓のようなエラーがでました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Build input file cannot be found: &amp;#39;xxxx/node_modules/react-native/Libraries/WebSocket/libfishhook.a&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;そのときは、こちらのissueにあるようにリンクするファイルの再登録で直りました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/facebook/react-native/issues/19569" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/341ceb19fa7bb10321f228dee45755074ff6859d26d9cf29b35c759211b1b643/facebook/react-native/issues/19569" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Xcode 10 libfishhook.a cannot be found · Issue #19569 · facebook/react-native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Environment OS: macOS 10.14 Node: 10.0.0 Yarn: Not Found npm: 5.6.0 Watchman: 4.9.0 Xcode: Xcode 10.0 beta (10L176w) Android Studio: 3.1 AI-173.4720617 Packages: (wanted =&amp;gt; installed) react: 16.3.1...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://user-images.githubusercontent.com/637225/41004316-d626d112-68ef-11e8-8a5e-397a55777bc4.png"&gt;&lt;img src="https://user-images.githubusercontent.com/637225/41004316-d626d112-68ef-11e8-8a5e-397a55777bc4.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(issun内の投稿より)&lt;/p&gt;
&lt;p&gt;他にも似たようなリンクエラーに1、2個遭遇したのですが、どれもリンクするライブラリの再登録で直りました。&lt;/p&gt;
&lt;p&gt;Xcode後にReact Nativeのプロジェクトがビルドできない場合は、リンクファイルの再登録をしてみると良いかもしれません。&lt;/p&gt;</description></item><item><title>Railsのjs-routesをWebpackerでも使うには</title><link>https://blog.piyo.tech/posts/2018-10-05-js-routes-webpacker/</link><pubDate>Fri, 05 Oct 2018 06:28:27 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-05-js-routes-webpacker/</guid><description>&lt;p&gt;Railsの&lt;code&gt;js-routes&lt;/code&gt;gemはクライアントサイドでURLヘルパーを使えるようにできるgemで、大変便利です。&lt;/p&gt;
&lt;p&gt;Gemfileに&lt;code&gt;gem &amp;quot;js-routes&amp;quot;&lt;/code&gt;を書いてインストールしたうえで、asset pipelineの&lt;code&gt;application.js&lt;/code&gt;あたりで&lt;code&gt;require js-routes&lt;/code&gt;としておきます。すると、Rails側で使える&lt;code&gt;user_path(@user.id)&lt;/code&gt;みたいなヘルパーメソッドがJSでも使えるようになって、↓なふうに使えます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-coffee" data-lang="coffee"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Routes&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;user_path&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ハードコーディングしなくてよくなるのでなかなか便利です。&lt;/p&gt;
&lt;p&gt;ところでこの導入手順ではJSがSprocketsに乗っています。つまりWebpackerのみを使っているプロジェクトではこの方法での導入ができません。&lt;/p&gt;
&lt;h1 id="webpackerで使うには"&gt;Webpackerで使うには&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;js-routes&lt;/code&gt;gemにはRubyのクラス&lt;code&gt;JsRoutes&lt;/code&gt;というのがいます。これが&lt;code&gt;generate&lt;/code&gt;メソッドと&lt;code&gt;generate!&lt;/code&gt;メソッドを持っています。&lt;/p&gt;
&lt;p&gt;まずはわかりやすい方の&lt;code&gt;generate!&lt;/code&gt;から。こちらは&lt;code&gt;user_path&lt;/code&gt;などの定義を書いたJavaScriptのコードをファイルに書き出すというものです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;generate&lt;/code&gt;は、というとJavaScriptのコードを文字列として返すメソッドです。Webpackerではこちらを使うと良いです。&lt;/p&gt;
&lt;p&gt;というのはStack Overflowからの受け売りなのですが、実際に試してみました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/railsware/js-routes/issues/237" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/382eed2b6098bbf52f94c2abc0da96151cd806bf8c94fc7a2cee9f5f026ed2c3/railsware/js-routes/issues/237" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;How to make it works with webpacker? · Issue #237 · railsware/js-routes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Rails 5.2 introduce Webpacker gem which can help you to avoid using Sprockets. Is there any way to make JS-Routes usable with Webpacker?&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;まずは&lt;code&gt;js-routes&lt;/code&gt;gemを普通にインストールします。&lt;/p&gt;
&lt;p&gt;続いて&lt;code&gt;erb-loader&lt;/code&gt;を有効にしておきます。erbを使う方法についてはこちら↓の記事でも書いています。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-08-11-gem-with-js-on-webpacker/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/8w8SfiZTtrOc7c9P0cf7ls6oc5TOlZuwE2Ul37hLWPnFwfi06xbi3eFTgRqdkiisVaD_ucG1GK_HGw1gu3nQ1fMh2vZGGUOeAXDlPItU5n8wWtXKfJJ3zKLk2Qsl-ZVBsSajiH2zck2iXseLGjg9_CiP1yGUc2S6NvlSgpFHjDxfoGBEfwUYmJ3HO3SEviF89bh7ojIsmEoSYWKHB1VpADGgCEUt9K1zRpJtjKkr-uPYL7UBPwVjIzYYDR0OKBRIGpXqLqF8TUVU-GuprPoUcbGDBzxsMcXECzeEiCDRF60EsXxRRFUe4NvX1t_o2Z9CGZn_aTkuj_pinFzDKjc8gWs7xPt98icrJmU3ICir4a9L4kap68g-s8Jrsvkwsqnd_ePLHtWxsckV6luCpgahhlke4osGyByoxCw5DeOgdehn1vpQe8FOgmqZ17P6s-1Y2o_SzrQg_0FnfpnkeWR14pO05F3SV0CEt3lRzuZC3jhvWpXiFtqaQ9Vdm00z0jurQjoNSRtQM_dwlg7GhNMfVgJMCB9xxWR7ATltJEl8p3SEBYgLc8OeKImVx_vQO2MFAU4jU5-oseegi_ZN4PvJLFYfTn4wTSAgB88hg8uKPwUDOnN4nnwr7-HeqcPHeFW2_phfh6iURRliFbRLUpnB_p3QKPM-NuWk66UZQ437abS84_uBm7lu3EDyNQ=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;gemが持ってるJSをwebpackerで読み込むには - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;手持ちのレガシー目なRails案件をいい加減Webpackerに直す活動を始めていまして、まずは仕事以外のプロジェクトからやってます。 JS用のgemだったりrails-assetsあたりはyarn化の時点でだいたい撲滅できていいですね。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="routes用のファイルを用意"&gt;Routes用のファイルを用意&lt;/h2&gt;
&lt;p&gt;Webpackerのエントリポイントのファイルが&lt;code&gt;app/javascripts/packs/application.js&lt;/code&gt;だったとして、1つ上の階層に&lt;code&gt;js-routes.js.erb&lt;/code&gt;つまり（&lt;code&gt;app/javascripts/js-routes.js.erb&lt;/code&gt;)というファイルを作ります。&lt;/p&gt;
&lt;p&gt;中身はerbで&lt;code&gt;generate&lt;/code&gt;の結果がそのままJSになるように書いておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;%=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;JsRoutes&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;generate&lt;/span&gt; &lt;span style="color:#f92672"&gt;%&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ruby側のJsRoutesがJavaScriptコードを書き出してくれるので、それをそのままこの&lt;code&gt;js-routes.js.erb&lt;/code&gt;の内容としておくわけです。&lt;/p&gt;
&lt;h2 id="webpackerでimport"&gt;Webpackerでimport&lt;/h2&gt;
&lt;p&gt;あとはメインのファイル（&lt;code&gt;app/javascripts/packs/application.js&lt;/code&gt;）にて、このファイルをインポートします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Routes&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;../js-routes.js.erb&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 必要に応じてグローバルに
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;window.&lt;span style="color:#a6e22e"&gt;Routes&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Routes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Webpackerでも使えるようになりました。&lt;/p&gt;</description></item><item><title>RubyMineのJavaScriptをECMAScript6に変更</title><link>https://blog.piyo.tech/posts/2018-10-04-rubymine-js-version/</link><pubDate>Thu, 04 Oct 2018 06:28:09 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-04-rubymine-js-version/</guid><description>&lt;p&gt;Railsの個人プロジェクトにWebpackerとVueを入れてVueに移行していくぞーと思っています。EmacsっだとVueがつらそうなので眠っていたRubyMineを使ってみようと起動したのですが、JSのimport構文に警告がでていました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;import declarations are not supported by current javascript version
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/pkKbxwE7vANRb0Y_coB-E9Qc81LvW1ANEO-vXEPbwfzQ4hFgNcx9bPBQVBONZ3Cw-ptrISEB5ZbPg94aHZOa3xVMitoAyp1OZJxQkCX1olh98Xsj1JOzKecDqlS6pImfZBEAIc_Jq32Lt1jIrfFe36AtcIpg1MMxYC6JFznd2uk2LtgRhcRohoLncHnNYxVNtTEgXGBseLArAwUHGh1pvCCrr4dmeTu6LD6QOpElAtjjE4BxfHYzGSCLOB1g-eHVqKuMGrlLwjJyzwibjg7eEsXxBbOjreaUx6fMZcnsnFL0YHd1_Y-kk2D8LXuQBZ3L7PlTj6uEd9WaXaYjx5KO9BwqYp45DWkVrR9szpBqi2IUexYV5ykCAbuD8HVM0oYZw65UzznTXJalmD2d0CFBoMHKRbSyM6IOTqCkQ4LJfWd6NY7DcMY220w9IfQfuOUrvHZfQSbaQjpThQdJG0dKSt_4AkRDmvwR7CS0OPqINQEh4VGulfwTJravggO0eLV_hviIzcIjWESWc_NZE7x-Lav38wg6whyXKw1LE1P6iQN0jKEV0xH1OrJH7BwlR6ka7N3psb5s4zyjWarQasjYO1AvXk37Ios-b4N_NaL-s9oMnrfo91s02F4L3oB8BZou-ZAJGwq6Rw7QrNydLihMWVJAFfT6dYFbmldRW_Csi1rg0aSF-b7Wim3y=w762-h42-no"&gt;&lt;img src="https://lh3.googleusercontent.com/pkKbxwE7vANRb0Y_coB-E9Qc81LvW1ANEO-vXEPbwfzQ4hFgNcx9bPBQVBONZ3Cw-ptrISEB5ZbPg94aHZOa3xVMitoAyp1OZJxQkCX1olh98Xsj1JOzKecDqlS6pImfZBEAIc_Jq32Lt1jIrfFe36AtcIpg1MMxYC6JFznd2uk2LtgRhcRohoLncHnNYxVNtTEgXGBseLArAwUHGh1pvCCrr4dmeTu6LD6QOpElAtjjE4BxfHYzGSCLOB1g-eHVqKuMGrlLwjJyzwibjg7eEsXxBbOjreaUx6fMZcnsnFL0YHd1_Y-kk2D8LXuQBZ3L7PlTj6uEd9WaXaYjx5KO9BwqYp45DWkVrR9szpBqi2IUexYV5ykCAbuD8HVM0oYZw65UzznTXJalmD2d0CFBoMHKRbSyM6IOTqCkQ4LJfWd6NY7DcMY220w9IfQfuOUrvHZfQSbaQjpThQdJG0dKSt_4AkRDmvwR7CS0OPqINQEh4VGulfwTJravggO0eLV_hviIzcIjWESWc_NZE7x-Lav38wg6whyXKw1LE1P6iQN0jKEV0xH1OrJH7BwlR6ka7N3psb5s4zyjWarQasjYO1AvXk37Ios-b4N_NaL-s9oMnrfo91s02F4L3oB8BZou-ZAJGwq6Rw7QrNydLihMWVJAFfT6dYFbmldRW_Csi1rg0aSF-b7Wim3y=w762-h42-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Prz7yxfquEo4dM6GKdaJwhLvye4xzUM2Xh8QzZbthpmotwi5gHVvRfSxjBkiVCgoJerVPaV3PPlw6aLQP8yBb9DLjbGgOgGtOV1xvg6Nhzg-H1UKr9RIvN19KV8_wWN8zgOGuIzDWLC6gnCb8O_ff_dYz7uve0rsYRDSHjuJHJM3faqGzw1TeBCv9Su0LTE6Y3x0zY1J_7B1A2ELRtgxYEsA3KM3ppuCy2ok9rvnATyePSnE77XHvGA_PGE4JSLzLGfrXlnoC0NTeb1A7xFqhZbXFgYhVFz8jJd8JAcPZTJggQ-fX2CXedAg7I-rt7HeO6UfqhoihqlFsw-cbahudq-y6m_lwssiro_FQnnvouxTHJprUXgFwHiDul751w2aHvZmPMlyW0wXOCfUDBYK3dGmyAdxQCQ3_7Hxy2ukqMPecscM4QabXuN_vmBctZdtpuYQ39ubs5K3WsY_IEC0vGXqf3gV20uj5ZRg-OkguOD5a0U64MyGh6QE73avISbU6AqcvVUJkiXvvlh-zJpcBvIc_uFgkdGZFBRy0hJzf8YH-949YDEhmRPa33TOINW6AK3B8evXgHSlkOzg2c8-uc4wX7pp6Z1kAh4fvDe15A7Zo355RebhF94Dv95LTHBKhee6kQZGcacX47_CM6JLpE5pSQm3vqW_RnUuwkjFiAXfU_x38WttbqQP=w466-h368-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Prz7yxfquEo4dM6GKdaJwhLvye4xzUM2Xh8QzZbthpmotwi5gHVvRfSxjBkiVCgoJerVPaV3PPlw6aLQP8yBb9DLjbGgOgGtOV1xvg6Nhzg-H1UKr9RIvN19KV8_wWN8zgOGuIzDWLC6gnCb8O_ff_dYz7uve0rsYRDSHjuJHJM3faqGzw1TeBCv9Su0LTE6Y3x0zY1J_7B1A2ELRtgxYEsA3KM3ppuCy2ok9rvnATyePSnE77XHvGA_PGE4JSLzLGfrXlnoC0NTeb1A7xFqhZbXFgYhVFz8jJd8JAcPZTJggQ-fX2CXedAg7I-rt7HeO6UfqhoihqlFsw-cbahudq-y6m_lwssiro_FQnnvouxTHJprUXgFwHiDul751w2aHvZmPMlyW0wXOCfUDBYK3dGmyAdxQCQ3_7Hxy2ukqMPecscM4QabXuN_vmBctZdtpuYQ39ubs5K3WsY_IEC0vGXqf3gV20uj5ZRg-OkguOD5a0U64MyGh6QE73avISbU6AqcvVUJkiXvvlh-zJpcBvIc_uFgkdGZFBRy0hJzf8YH-949YDEhmRPa33TOINW6AK3B8evXgHSlkOzg2c8-uc4wX7pp6Z1kAh4fvDe15A7Zo355RebhF94Dv95LTHBKhee6kQZGcacX47_CM6JLpE5pSQm3vqW_RnUuwkjFiAXfU_x38WttbqQP=w466-h368-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;RubyMineが実行するわけではないので直接は問題ないのですが、いちいちこれが出るのも鬱陶しいのできちんと対応します。&lt;/p&gt;
&lt;p&gt;ソースコードから変更するには、警告箇所の電球マークを押すと出てくる提案メニューから「Change JavaScript language version to ECMAScript 6」を選択します。&lt;/p&gt;
&lt;p&gt;しばらくすると構文解析が終わって波線が消えると思います。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/wOMIKw7V3mhtZZofh197ytqJldL8bBh2gwQksMYzvR7x6JvhELDGf6eAeqi6g7ZgxKG_Zsdu0njWAN_EiPz6T40fs-awBpbj--7sUa7QqxHKAbhdZQB6WLwm1ov3jBTdeuSlFxzBrn8cHnmJVeP9NNw0JObFoUvQosRMv1ue9OwGEVeK49ospD4U1oV1blV3BxsRDzo1brh_1zvlMKv_WqZHm2Ur4N4WiRIamwTY6VmIPgbgxsW14_94YAMSn6ZaOyCJ-c5BNq8doOmzqAMpEFmDkpBLWWKAYdunYZte3Stpols_grc0N02t2CHh9Z9DwNT8Fsx83ctDQUFfjsHmkAlhnuo5EpWgq2cI3gqyKw-4WeS_73cWtD5glvaITsQP-p8DjYFSrYMxdv-tL8Wr99iXN9Sk0vMbNd7iibPrx3R7LL5vMcUYr7-szbFcQhc6XpX4A9dHfwIBYq_dew0mHAt7KRvJnY2oGOsjEKX-Wcc1bPVxJwFYCt-36vkROxPp7LX0HrP7KAWuufkdoaH6ZrhdeALKwCyQLdhdVTSz1yZMdjzo1QRYmmJlK-ptsWSLI_eZ5sixFC8AxZg6fJ2mzBaxNountzX2tmEdc3TrChBbNsJqh-Yj4LtTnzu5EmHKG3U0Aiw3u8lb6kWV6MlRyAaTOLGr64ubvuUPi1uSItlezq4j4jPIMXur=w876-h356-no"&gt;&lt;img src="https://lh3.googleusercontent.com/wOMIKw7V3mhtZZofh197ytqJldL8bBh2gwQksMYzvR7x6JvhELDGf6eAeqi6g7ZgxKG_Zsdu0njWAN_EiPz6T40fs-awBpbj--7sUa7QqxHKAbhdZQB6WLwm1ov3jBTdeuSlFxzBrn8cHnmJVeP9NNw0JObFoUvQosRMv1ue9OwGEVeK49ospD4U1oV1blV3BxsRDzo1brh_1zvlMKv_WqZHm2Ur4N4WiRIamwTY6VmIPgbgxsW14_94YAMSn6ZaOyCJ-c5BNq8doOmzqAMpEFmDkpBLWWKAYdunYZte3Stpols_grc0N02t2CHh9Z9DwNT8Fsx83ctDQUFfjsHmkAlhnuo5EpWgq2cI3gqyKw-4WeS_73cWtD5glvaITsQP-p8DjYFSrYMxdv-tL8Wr99iXN9Sk0vMbNd7iibPrx3R7LL5vMcUYr7-szbFcQhc6XpX4A9dHfwIBYq_dew0mHAt7KRvJnY2oGOsjEKX-Wcc1bPVxJwFYCt-36vkROxPp7LX0HrP7KAWuufkdoaH6ZrhdeALKwCyQLdhdVTSz1yZMdjzo1QRYmmJlK-ptsWSLI_eZ5sixFC8AxZg6fJ2mzBaxNountzX2tmEdc3TrChBbNsJqh-Yj4LtTnzu5EmHKG3U0Aiw3u8lb6kWV6MlRyAaTOLGr64ubvuUPi1uSItlezq4j4jPIMXur=w876-h356-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;設定メニューから変える場合は「Languages &amp;amp; Frameworks」の「JavaScript」から「JavaScript language version」を「ECMAScript 6」を選択して保存すればOK。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/7Kty5KNrEOf59nmjKcEFB_oo9tnvQDskLvCC5CAw-Nsc04k5ZecAe7LsJUAq09f4Levh69Ojeom8sc4JM5VSA8t8r8MkfghLBBdYXUQ7qdrG6rI_k1VqYGY5w_T3OoyphpfYH6Rgbsnhv9nLGbQkVjzV93xstWRrtEBTuYHQvuWJ6YbPyy4FCi6Lb9QRw9QXsCB-vZWrx__6wt4bouBGCXgK7q5IwxUrz9RVjKvZwe96UAKvDNmCCskFizUM_1me6Cg9O2GYIMeV1SbstMEbXFI5NDf7Ofh1hYNCvwxIMMerx6HuOaNggEbTbG_Gn6Fu6h-b-2xP4FRUG4Of3R79MnUdbEXbDTS-84XGBwu1QN8Dp4WJejVCsA1axPhhG6H9l--uVnE9rWh3k-zL3NZLb8-mZwhyS4Y-WG0pYA_vJV8wwaEQWd_xhdlWqgkSolIJ-q_6houpeu1Oq6L2t1thAVFHF7YyYn5QcDLmQcIbGp1jj_wGv_fgcYKLLYIpukMVbOHTZb0qBTrYZ1sBCOd8Pt-vo_UDDhjkzR9PIlftmZzeVrBTkA7BV-_VXEJ4JIL8Pu3fhePN3xUUL5VzFIf_XyoyV43bH8WWkvuguesVbRqiqqNY7WwBAqF414gdJajPR_fWcUwTnVHibYI5ILf_MTLJWsnGiEYS5fav6fVu4lOXL0QX7YBpMRhV=w944-h480-no"&gt;&lt;img src="https://lh3.googleusercontent.com/7Kty5KNrEOf59nmjKcEFB_oo9tnvQDskLvCC5CAw-Nsc04k5ZecAe7LsJUAq09f4Levh69Ojeom8sc4JM5VSA8t8r8MkfghLBBdYXUQ7qdrG6rI_k1VqYGY5w_T3OoyphpfYH6Rgbsnhv9nLGbQkVjzV93xstWRrtEBTuYHQvuWJ6YbPyy4FCi6Lb9QRw9QXsCB-vZWrx__6wt4bouBGCXgK7q5IwxUrz9RVjKvZwe96UAKvDNmCCskFizUM_1me6Cg9O2GYIMeV1SbstMEbXFI5NDf7Ofh1hYNCvwxIMMerx6HuOaNggEbTbG_Gn6Fu6h-b-2xP4FRUG4Of3R79MnUdbEXbDTS-84XGBwu1QN8Dp4WJejVCsA1axPhhG6H9l--uVnE9rWh3k-zL3NZLb8-mZwhyS4Y-WG0pYA_vJV8wwaEQWd_xhdlWqgkSolIJ-q_6houpeu1Oq6L2t1thAVFHF7YyYn5QcDLmQcIbGp1jj_wGv_fgcYKLLYIpukMVbOHTZb0qBTrYZ1sBCOd8Pt-vo_UDDhjkzR9PIlftmZzeVrBTkA7BV-_VXEJ4JIL8Pu3fhePN3xUUL5VzFIf_XyoyV43bH8WWkvuguesVbRqiqqNY7WwBAqF414gdJajPR_fWcUwTnVHibYI5ILf_MTLJWsnGiEYS5fav6fVu4lOXL0QX7YBpMRhV=w944-h480-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>VESAの変換アダプターでVESA200の壁掛け金具にVESA300のテレビを設置</title><link>https://blog.piyo.tech/posts/2018-10-02-tv-vesa-adapter/</link><pubDate>Tue, 02 Oct 2018 06:52:36 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-02-tv-vesa-adapter/</guid><description>&lt;p&gt;半年ほど前の話ですが、テレビを買い換えました。そのとき使っていた壁掛け金具を新しいテレビでも使えるように色々とがんばったのでそれを記録しておこうと思います。&lt;/p&gt;
&lt;p&gt;もともとのテレビは2010年頃に買ったTOSHIBAの37インチのテレビで壁掛けの金具にはこれを使っていました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.yodobashi.com/product/100000001001083930/"&gt;https://www.yodobashi.com/product/100000001001083930/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;首を左右に振れるのが気に入って使っていました。キッチン側からなんとなくサッカーやテニスを眺めるのに便利でした。&lt;/p&gt;
&lt;p&gt;耐荷重は20kgということで、当時のテレビが17kgぐらいで問題なく使えていました。というのが2年ほど前。&lt;/p&gt;
&lt;p&gt;テレビが古くなったので買い換えるとなったのが半年前なわけですが、買い替えにはLGの55インチのちょっと大きめのテレビにしました。重さは約16kgで壁掛け金具の耐荷重的にもOKでした。&lt;/p&gt;
&lt;p&gt;ところがこの新しいテレビ、壁掛け金具を取り付けるためのネジ穴の位置が旧テレビと異なりました。&lt;/p&gt;
&lt;p&gt;調べてみると、昔のテレビはVESA200x200という20cm幅、新しいテレビはVESA300x300という30cm幅。大きくなったので当然かもしれませんが、従来の金具が使えないとなると困ります。&lt;/p&gt;
&lt;p&gt;当初、サイズ変換のアダプターなんて山程あるだろと高をくくっていたのですが、これがまあ見つかりません。見つかっても100x100と200x200を変換とかね。&lt;/p&gt;
&lt;p&gt;そんななかやっと見つけたのが、これ。値段も約3000円とお手頃。金具より高くなっては意味がありませんので。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.yodobashi.com/product/100000001001083930/"&gt;https://www.yodobashi.com/product/100000001001083930/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;それで心配なのはこのアダプターがちゃんと取り付けられるかということなんですが、実際に実施した人が見つからず、商品ページのこの言葉（↓）を信じて購入しました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;VESA300×300、VASA400x300対応
MFシリーズなどのVESA200×200互換の取付プレートを持つ金具をVESA300×300、 又はVASA400x300の取付け穴のテレビに対応させるアダプターです。
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これ、取り付けた写真をみれば一目瞭然なんですが、元の金具とアダプターを繋げるためのネジが一緒に入っていました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/IuYC_0u8UCH9SbYlWfnhcO-aHqwnaolMUBUFPeo6zdx-33EEMER1r4Bzof1bZcyBz-8ltVvoiLSYbPI2tAdA6qW6qEsdM8QfD895IIhNbKQCWXNu8GI3GKSp-wyPz72txkcwtxEAIHBbaq2W2lyc1FewCuih7-3FR_ewAEePy0hfDlnvCiwfRmb3bqXp4hW9aPr5GFY-DzFFvXGNukK8BCL-ZmswSs6cN_-ZTANcX4ETYhXDpPhNCBoGPeRINTTIgF4y2cEoRgMw4qarSVvvCSn7d6ULL1dMv4unx-P1jWKorn53unQKCU8briR4Ho0Xe7C7hM4qmrSmAR7lE8pUG3K9j5-N4ASuXKjyhbi-w8fSHZJPdTC8Y7d8wwIVF2cG7kTZD_yzPU2kv1leLyOm49O33oamI-fuZGO1C5NgF8PF1KiPiCoeqyYRAfUnwCUqGwJxWBMXeDceFeZXlIkiMf1EYg4FTeqRdiCWVTKG4Axqzcfp1--lgh_F7W49QnO6j8TgJOfrUWxDGwh7U4kew9_tDZ-nFSN7eZOZSXTtverCgLan8_NK0yQUoDdIAgWh9efQ640ACHbRRq-gevp0bcHirlRF8B0tMykdM1_GVXW07Qi9gc5RHMAAHCpS-auEx6bz70zW49k9KkULd98wYahfUKFlT4g8B2RLaS5rWO3hNTZu0wUSv9ci=s915-no"&gt;&lt;img src="https://lh3.googleusercontent.com/IuYC_0u8UCH9SbYlWfnhcO-aHqwnaolMUBUFPeo6zdx-33EEMER1r4Bzof1bZcyBz-8ltVvoiLSYbPI2tAdA6qW6qEsdM8QfD895IIhNbKQCWXNu8GI3GKSp-wyPz72txkcwtxEAIHBbaq2W2lyc1FewCuih7-3FR_ewAEePy0hfDlnvCiwfRmb3bqXp4hW9aPr5GFY-DzFFvXGNukK8BCL-ZmswSs6cN_-ZTANcX4ETYhXDpPhNCBoGPeRINTTIgF4y2cEoRgMw4qarSVvvCSn7d6ULL1dMv4unx-P1jWKorn53unQKCU8briR4Ho0Xe7C7hM4qmrSmAR7lE8pUG3K9j5-N4ASuXKjyhbi-w8fSHZJPdTC8Y7d8wwIVF2cG7kTZD_yzPU2kv1leLyOm49O33oamI-fuZGO1C5NgF8PF1KiPiCoeqyYRAfUnwCUqGwJxWBMXeDceFeZXlIkiMf1EYg4FTeqRdiCWVTKG4Axqzcfp1--lgh_F7W49QnO6j8TgJOfrUWxDGwh7U4kew9_tDZ-nFSN7eZOZSXTtverCgLan8_NK0yQUoDdIAgWh9efQ640ACHbRRq-gevp0bcHirlRF8B0tMykdM1_GVXW07Qi9gc5RHMAAHCpS-auEx6bz70zW49k9KkULd98wYahfUKFlT4g8B2RLaS5rWO3hNTZu0wUSv9ci=s915-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そのかわり、元々金具とテレビを直接止めていた銀色のネジはアダプターとテレビを固定するために使われます。&lt;/p&gt;
&lt;p&gt;ですがこのアダプターすんなり装着できたわけではありません。↓の写真、わかるでしょうか？&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/mjDrkH_xAY-GHbpczhhzbGremKFvBtjAyFZNhu-ZhZe6Gk57dhTO-zjkqtGEdW9GjDxBiA1XiszF-mtrhpYSL-yfuVlHcNg22nyFUU_cTf9WydaWyWzWGFQ-nA6ZCnzU8JZpHQzSssAWR7U8N2xVJdSUcV5sCxOviglq4I1USJpetrEdI93HDEeK3HWjy2LC4_EvmqsGOk6iQ7tC7aSEzkrChUoacXi2mDkclnG2djAsFKurlLNT2Bo9tKkuDrocfnUBIGd3zofdNRs5bsGiKwbmtiYQ-K3oHPqZl42QVuvISOZtvWtTKdtDlE0qDys2IRIBhpPUMHCo2GmnYpBukupc_0TpDXaheoMESBvNvnXFECWkVX0FTGKC7o7-Uo855KRTroIrlYbtJYr3Sf4vY-mqddiB9_jEP893oNcyBZkEESMXs6zWFb8KtkupYbmDn60-qYD6b0cPLYhp_3MXSQurfxi9Zmflrtqheb3hunWO8L8F1o4hsNqbK_qZhXuBC0Ok1uFuHSiK1g_hBjqPoRde_8634AcEj_38pu0YrERcOUcWlLkTVITzHZvnlefpuOtH70-ZSoGIlDeXBZUddlWSWJEycVcPhXxr-I_iHrlI5_M0r-WgnquJaz52iR8nX5c1xn5lMZpGyN3LXY21TBSPqHsxPTx_s6DK1mOukQp0ALmlwa6_OUUU=s915-no"&gt;&lt;img src="https://lh3.googleusercontent.com/mjDrkH_xAY-GHbpczhhzbGremKFvBtjAyFZNhu-ZhZe6Gk57dhTO-zjkqtGEdW9GjDxBiA1XiszF-mtrhpYSL-yfuVlHcNg22nyFUU_cTf9WydaWyWzWGFQ-nA6ZCnzU8JZpHQzSssAWR7U8N2xVJdSUcV5sCxOviglq4I1USJpetrEdI93HDEeK3HWjy2LC4_EvmqsGOk6iQ7tC7aSEzkrChUoacXi2mDkclnG2djAsFKurlLNT2Bo9tKkuDrocfnUBIGd3zofdNRs5bsGiKwbmtiYQ-K3oHPqZl42QVuvISOZtvWtTKdtDlE0qDys2IRIBhpPUMHCo2GmnYpBukupc_0TpDXaheoMESBvNvnXFECWkVX0FTGKC7o7-Uo855KRTroIrlYbtJYr3Sf4vY-mqddiB9_jEP893oNcyBZkEESMXs6zWFb8KtkupYbmDn60-qYD6b0cPLYhp_3MXSQurfxi9Zmflrtqheb3hunWO8L8F1o4hsNqbK_qZhXuBC0Ok1uFuHSiK1g_hBjqPoRde_8634AcEj_38pu0YrERcOUcWlLkTVITzHZvnlefpuOtH70-ZSoGIlDeXBZUddlWSWJEycVcPhXxr-I_iHrlI5_M0r-WgnquJaz52iR8nX5c1xn5lMZpGyN3LXY21TBSPqHsxPTx_s6DK1mOukQp0ALmlwa6_OUUU=s915-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;アダプターの左下の箇所です。この位置に電源コードを挿すための端子が出ています。実はこのラインに沿って下側だけ切断しています。こうしないと電源コードに干渉してしまい取り付けられないのでした。。これはさすがに買ってからでないと気が付きませんでした。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/C8W3yslotO59j8MNRQk6ByP_NwcFGB4h4loMV77lG2D7OwJmPygZ0ZyjXoJYMCzD-rVn1eb8gfP26gaYGKed6-1yPnEIj5xjWUuN2BmznAUNpZCoJbcCwyUyM9XkJrEYDK7f74qXxMdg0h8m9ocgepuLapT8-bSJhwA2t3Z2IThyqUQIrGl-gNi9zq6D2SYeN2ieRHU17pyJ8IMZdC2PyrvB5L90q2RUesaoM0tw_46x7Ecp7Ey1Rnf3YwgXBbf7GTzr1s7ATX3CZm7Wlsr2uNUmsLVzc1dm5iHzJaptAxp-_NvtH_4Qzi5_sSUDGUedifPcc3jv9QIXReIcWsH1v7TMmmSOR1kLAzW90VKknQmStmi7S58NLLGlVJ73IeRhGUOOn7cuIm8Nu6KV_QR-plxuJmRCDrHLFm2ZBb1s76Y0rA07hdkbE1t7SAqyv7qFqTHvkH-35Du2ZOGXxcvwAri8p-6rPWxF4fiI1usiMAX0ly63HPVOGdr5T2oUtrE0qgyQClE8HM4m-HhfyO3JYIoNmpKnX0dLM3WRUAPtfHKkSewSgBtm5fCCknTjG6tXd1vGfBMlqYjpvTtyT4zaygpziah-iBfpHClZQU6350kep0Ixd9sUiefd2LD1HAuhL7zEtYHFBVxrPPDWtAdTwu9ktfRZkkW2yr_ysaMHV3TM7t1pM261ITA4=s915-no"&gt;&lt;img src="https://lh3.googleusercontent.com/C8W3yslotO59j8MNRQk6ByP_NwcFGB4h4loMV77lG2D7OwJmPygZ0ZyjXoJYMCzD-rVn1eb8gfP26gaYGKed6-1yPnEIj5xjWUuN2BmznAUNpZCoJbcCwyUyM9XkJrEYDK7f74qXxMdg0h8m9ocgepuLapT8-bSJhwA2t3Z2IThyqUQIrGl-gNi9zq6D2SYeN2ieRHU17pyJ8IMZdC2PyrvB5L90q2RUesaoM0tw_46x7Ecp7Ey1Rnf3YwgXBbf7GTzr1s7ATX3CZm7Wlsr2uNUmsLVzc1dm5iHzJaptAxp-_NvtH_4Qzi5_sSUDGUedifPcc3jv9QIXReIcWsH1v7TMmmSOR1kLAzW90VKknQmStmi7S58NLLGlVJ73IeRhGUOOn7cuIm8Nu6KV_QR-plxuJmRCDrHLFm2ZBb1s76Y0rA07hdkbE1t7SAqyv7qFqTHvkH-35Du2ZOGXxcvwAri8p-6rPWxF4fiI1usiMAX0ly63HPVOGdr5T2oUtrE0qgyQClE8HM4m-HhfyO3JYIoNmpKnX0dLM3WRUAPtfHKkSewSgBtm5fCCknTjG6tXd1vGfBMlqYjpvTtyT4zaygpziah-iBfpHClZQU6350kep0Ixd9sUiefd2LD1HAuhL7zEtYHFBVxrPPDWtAdTwu9ktfRZkkW2yr_ysaMHV3TM7t1pM261ITA4=s915-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このアダプターは厚さ3mmぐらいはある金属の板のなので自宅にあるものでは刃がたちませんで、ホームセンターに持っていって道具を借りて切断しました。グラインダーとかいう金属も切れるような道具で切るのですが、もう火花がすごくて腰が引けてしょうがありませんでした。&lt;/p&gt;
&lt;p&gt;結局あまりに僕がビビるので店員のおじさんが「特別ですよ」と言って切ってくれました。すみません。助かりました。&lt;/p&gt;
&lt;p&gt;こうして無事テレビをテレビ金具に取り付けることができました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/PXBuOtdJF5GQchErOH8loX8AIGJQiS3PmXVQQJZcguj0MimQZzWipM7BgXocBRubj1h3waZEcrJBvJpPOsYn677layOfsnFfJlT3egLA54o7hGZaFzocpKzWiXwfOz2PUBFUuVhkV88E2ERJIla0ijAwba6XYg6tpY-Wh1Y3A5as9AuWKcXrGDf4oX7xyqlXeX4IZAIIl1zM9oeE3Fz1jJ7zzuOmRyiiIFUJISDv_9GkUVKMLQ7MoOkQEZ3ZJn-oC81mDUW9urm5gUHPtKaB3YcCCmYjc-J7mHVva88ujQgjz-innAq427M3OmpHRPykcHEtBHLsFLBum2ZgzJ1sg-irNe5nVtLOtD12ITKr0trh0dCzJH5IN1KZZBaBANOPRP8hn_yoRqqt5DSkdwa7EaeGpi-S3pQOlfsFgKpkWARs8SzwZu_qufnIGNsVHCF3T68vzB5-nA5sXmdWSbO5LbPbqpNG0n40NlrVpYalNgGAROjzb3AM1wN0J6Iumr6mal5i3z3brBcM5rDhp-fkxtNyFqac2-kvctlRNX-lbMBuflYjudKX7-uBHdm1BTmSVyEl3iVgzqin8hVG2OhQ_xZlxTs13ulwVvHUYQvyasVbJN2iVeAIKxPEZ8Ce5aH6q8iUahwQbJGEmXQafY0l2aN73gs_oGEUEdyj9Irgz0DrAZQzUIaeKkoR=s915-no"&gt;&lt;img src="https://lh3.googleusercontent.com/PXBuOtdJF5GQchErOH8loX8AIGJQiS3PmXVQQJZcguj0MimQZzWipM7BgXocBRubj1h3waZEcrJBvJpPOsYn677layOfsnFfJlT3egLA54o7hGZaFzocpKzWiXwfOz2PUBFUuVhkV88E2ERJIla0ijAwba6XYg6tpY-Wh1Y3A5as9AuWKcXrGDf4oX7xyqlXeX4IZAIIl1zM9oeE3Fz1jJ7zzuOmRyiiIFUJISDv_9GkUVKMLQ7MoOkQEZ3ZJn-oC81mDUW9urm5gUHPtKaB3YcCCmYjc-J7mHVva88ujQgjz-innAq427M3OmpHRPykcHEtBHLsFLBum2ZgzJ1sg-irNe5nVtLOtD12ITKr0trh0dCzJH5IN1KZZBaBANOPRP8hn_yoRqqt5DSkdwa7EaeGpi-S3pQOlfsFgKpkWARs8SzwZu_qufnIGNsVHCF3T68vzB5-nA5sXmdWSbO5LbPbqpNG0n40NlrVpYalNgGAROjzb3AM1wN0J6Iumr6mal5i3z3brBcM5rDhp-fkxtNyFqac2-kvctlRNX-lbMBuflYjudKX7-uBHdm1BTmSVyEl3iVgzqin8hVG2OhQ_xZlxTs13ulwVvHUYQvyasVbJN2iVeAIKxPEZ8Ce5aH6q8iUahwQbJGEmXQafY0l2aN73gs_oGEUEdyj9Irgz0DrAZQzUIaeKkoR=s915-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>macOSの上書き再インストールでカーネルパニックから脱却</title><link>https://blog.piyo.tech/posts/2018-10-01-kernel-panic-apple-support/</link><pubDate>Mon, 01 Oct 2018 06:39:06 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-10-01-kernel-panic-apple-support/</guid><description>&lt;p&gt;ここ一ヶ月ほど夜間などの長時間のスリープ中にMacBookがカーネルパニックによって強制終了、朝には再起動された状態になっているという現象が頻発していました。&lt;/p&gt;
&lt;p&gt;再起動されちゃうと途中だった仕事用の環境をいちいち整えないといけないのでとても効率が悪くて困っていました。&lt;/p&gt;
&lt;p&gt;カーネルパニックに関するログは&lt;code&gt;/Library/Logs/DiagnosticReports&lt;/code&gt;にある末尾が&lt;code&gt;.panic&lt;/code&gt;で終わるファイルなのですが、読んでみても根本的なことはわかりません。&lt;/p&gt;
&lt;p&gt;Appleのサポートに相談しようとWebで手続きを進めるも、「お客様の製品は無償テクニカルサポートの対象ではないようです」と表示されてしまい相談できず。&lt;/p&gt;
&lt;p&gt;そこでまずはググってみつけた記事で解決するかもしれないと紹介されていた方法をいくつか試しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NVRAMリセット&lt;/li&gt;
&lt;li&gt;SMCコントローラリセット&lt;/li&gt;
&lt;li&gt;ディスクのFirstAid&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;やはり改善しないので次にログを元に会社の同僚に相談したところ、&lt;code&gt;UPSB(MacBookPro13,3): thunderbolt power on failed&lt;/code&gt; とあるから周辺機器が悪いんじゃない？とか昔外部ディスプレイをつないでいたら同じことが起こったという話を入手しました。&lt;/p&gt;
&lt;p&gt;確かに、普段から外部ディスプレイを2枚接続して、MacBookは閉じた状態（クラムシェルモード）で使用しています。&lt;/p&gt;
&lt;p&gt;最近この使い方に変えたわけではないので直接の原因ではなさそうだとは思いつつ、Mac側の何かと相性が悪くなってしまったというのは考えられます。ディスプレイを外した状態にして一晩スリープ状態でおいてみました。そして、問題なくスリープから復帰できました。&lt;/p&gt;
&lt;p&gt;ディスプレイの影響かもとわかったとしても、ディスプレイを毎晩外してスリープさせるという運用は実用的ではありません。&lt;/p&gt;
&lt;h1 id="サポートへ"&gt;サポートへ&lt;/h1&gt;
&lt;p&gt;さすがに困ったのでお金がかかってもいいからAppleの有償サポートに電話をしてみました。&lt;/p&gt;
&lt;p&gt;症状を話すと提案として返ってきたのが以下の2点でした。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;macOSを上書きインストールして様子見&lt;/li&gt;
&lt;li&gt;だめならOSを初期化&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ソフトなのかハードなのか問題を切り分けられるように対処していきましょうとのことでした。&lt;/p&gt;
&lt;p&gt;1つ目を実施して直ればOSがなんらかの理由で壊れていたということ、2つ目を実施して直った場合は使っているソフトウェアのせい、それでもだめならハードのせいという具合。&lt;/p&gt;
&lt;p&gt;1つめのmacOSの上書きインストールは既存のデータやソフトウェアなどは消えずそのまま使えるということです（※）。&lt;/p&gt;
&lt;p&gt;※厳密にはSIPを無効化してインストールするようなソフトはまた使えない状態になります。&lt;/p&gt;
&lt;p&gt;macOSの再インストール方法はリカバリーモード（復元モード？）で起動しなおしてから、macOSを再インストールするという方法です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/yGGXVF8KPQF_06yeyEzpR2EXqwb5yhnETP5crzcFYtjH8gkf82JAH7KIdERfN9bhbpKTcTOO_9oed8BQsFJ6UJnB22fbBDs2nE0S-RK7WDLNo7cM8At_en9jc3I6yCMQCf_d1WJCJEGuSihJtZIXO4Wrc2sgs9MapRLuqO9pgFrvKzxWgJE2alSCc-hJFnw3JgJ0n0NnHwzJAVQUoeezvcgtsdlySA_7KCQtTi4B8xsNPCFoKvynbdGGulnXMnYTk1_pf1_nlR20G0wbYKUYW5jZ-hV80rCMV0bml_MG7dilSmsJN5aAF81RkAK-O-6xs4oY2cy2I8m_3fNmukPTnWjq826BMNhqlFnR8KFv6jxGpYtHztsWS4jk7yoBqoH8sAo4i7T8JsOd6MRGZuIB2BAPoOJlnuuHrLV-7W_flNIPYhAyySfQfsdsNwdQKyYC1zncfjjQAlZhxYMGwsoHb2uunVjAlDh8UOMoDoYQ3ei4HWdb2CgEYIl7E25JAfx6Uz4oSprszS4xfFAC9RIdisCY6AlDLXIJxvMlPX1nus1lnwxSJkCu7wjXGkO61Uwj1O88yL3Az7nMp6G-bIlOq5FmErEZjwLoX9FViQmUw3hl301UBCNhM6Iu8SMn0MAbpvo83-dXcvJYOJz6xBoMIp8xtPBopuRL-qat20lnl6_YMdXRVLVUgzlF=w594-h404-no"&gt;&lt;img src="https://lh3.googleusercontent.com/yGGXVF8KPQF_06yeyEzpR2EXqwb5yhnETP5crzcFYtjH8gkf82JAH7KIdERfN9bhbpKTcTOO_9oed8BQsFJ6UJnB22fbBDs2nE0S-RK7WDLNo7cM8At_en9jc3I6yCMQCf_d1WJCJEGuSihJtZIXO4Wrc2sgs9MapRLuqO9pgFrvKzxWgJE2alSCc-hJFnw3JgJ0n0NnHwzJAVQUoeezvcgtsdlySA_7KCQtTi4B8xsNPCFoKvynbdGGulnXMnYTk1_pf1_nlR20G0wbYKUYW5jZ-hV80rCMV0bml_MG7dilSmsJN5aAF81RkAK-O-6xs4oY2cy2I8m_3fNmukPTnWjq826BMNhqlFnR8KFv6jxGpYtHztsWS4jk7yoBqoH8sAo4i7T8JsOd6MRGZuIB2BAPoOJlnuuHrLV-7W_flNIPYhAyySfQfsdsNwdQKyYC1zncfjjQAlZhxYMGwsoHb2uunVjAlDh8UOMoDoYQ3ei4HWdb2CgEYIl7E25JAfx6Uz4oSprszS4xfFAC9RIdisCY6AlDLXIJxvMlPX1nus1lnwxSJkCu7wjXGkO61Uwj1O88yL3Az7nMp6G-bIlOq5FmErEZjwLoX9FViQmUw3hl301UBCNhM6Iu8SMn0MAbpvo83-dXcvJYOJz6xBoMIp8xtPBopuRL-qat20lnl6_YMdXRVLVUgzlF=w594-h404-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;「macOSを再インストール」から進んでいって、適切なインストール場所を選びます。通常はMacintosh HDのはずです。ダウンロードやインストールに1時間程度かかります。&lt;/p&gt;
&lt;p&gt;インストールが終わって起動してみると確かにこれまでと同じように使えることがわかりました。仕事ができなくなる状態にはなってなくて一安心です。&lt;/p&gt;
&lt;p&gt;一晩スリープさせて問題が起こるかどうか様子みるため、ディスプレイに繋いだ状態でスリープさせました。そして今朝様子をみてみたらちゃんとスリープから復帰してくれました。&lt;/p&gt;
&lt;p&gt;ありがとうAppleサポート。そういえば有償サポートだったけど料金はどうやって請求されるんだろうか。。。そんな話はひとつもなかったぞ。&lt;/p&gt;</description></item><item><title>LeetCodeでプログラミングの練習問題にチャレンジ</title><link>https://blog.piyo.tech/posts/2018-09-29-leetcode/</link><pubDate>Sat, 29 Sep 2018 06:43:43 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-29-leetcode/</guid><description>&lt;p&gt;最近LeetCodeというサービスを発見したのでときたま遊んでいます。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://leetcode.com/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;leetcode.com →&lt;/span&gt;&lt;span&gt;https://leetcode.com/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;最近はフレームワークやSDKの作法にならってアプリケーションを書くことが多いので素のプログラミングというかアルゴリズムを意識して書くことが少なく、衰えた筋肉を鍛えているような感じがして気持ちがいいです。&lt;/p&gt;
&lt;p&gt;無料でも一部使えるのでとりあえず登録して問題一覧を見てみますと、&lt;/p&gt;
&lt;p&gt;&lt;a href="https://leetcode.com/problemset/all/"&gt;Problems - LeetCode&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;こんなふうに出ています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/PcT2BqNOXw02MfaMMTQyxCSoGo3_TnVO0MZX13HpVG-UROFLbaYj7R1WK8gqQqWmwQHFCGy8EVLy3YnKiZ4gtxPebrVoFrmJsjRIl8dOuZavu20ILGianRjuidPmRtFLVmqn99MfbDVbpv0NXT3NLiPH0ypC4rOkpnWuwt5g30NxSZ1-5u9JZcqx92HC7dDFvwECoEDxvhRbB-yQJlUDLE6Jlaqo2doolTlpCq-CJ4r76w2vzkzgq51tHnNMlz_XAXzFep1B8WiWqeFjC6YHwi2rzn2IP0qZ1sGoVIcSRA7RtBGFuhrnTbV00zNp-VW3DgjTK3jgu38evddSgr8lbrwLHdi12SoOsO9Vbz3hE1P5dfSCSHGr7cjxC-t4kMPIIRkb1BAVoWOGbbyuAl7WlYaZuZ0iMonvzvId_JKwfzEK6KRvnpFQeDRmehGtmnPk66WSQV6oiW9LwMczm0zUhhyHJzeB2W0zy78htpVy6V-sQr3fZDdSqV46k6nbiOUuUOasc9lCwpjJQdByvM1gzp3jRWV4YrX20xG36VOrL2DldguPQqFdPYMoEkYopI8IcDDm4DrE9c5NylAVIMObTx5mhmEP63XfO3rAEGkgbnW1xnNKbu20naVmPFJV5I-WBcU9yvxCTTbsOH_D3EiAYVjgipo3YVrkodnPGl9uovAgzy0W8GSLLX1p=w910-h335-no"&gt;&lt;img src="https://lh3.googleusercontent.com/PcT2BqNOXw02MfaMMTQyxCSoGo3_TnVO0MZX13HpVG-UROFLbaYj7R1WK8gqQqWmwQHFCGy8EVLy3YnKiZ4gtxPebrVoFrmJsjRIl8dOuZavu20ILGianRjuidPmRtFLVmqn99MfbDVbpv0NXT3NLiPH0ypC4rOkpnWuwt5g30NxSZ1-5u9JZcqx92HC7dDFvwECoEDxvhRbB-yQJlUDLE6Jlaqo2doolTlpCq-CJ4r76w2vzkzgq51tHnNMlz_XAXzFep1B8WiWqeFjC6YHwi2rzn2IP0qZ1sGoVIcSRA7RtBGFuhrnTbV00zNp-VW3DgjTK3jgu38evddSgr8lbrwLHdi12SoOsO9Vbz3hE1P5dfSCSHGr7cjxC-t4kMPIIRkb1BAVoWOGbbyuAl7WlYaZuZ0iMonvzvId_JKwfzEK6KRvnpFQeDRmehGtmnPk66WSQV6oiW9LwMczm0zUhhyHJzeB2W0zy78htpVy6V-sQr3fZDdSqV46k6nbiOUuUOasc9lCwpjJQdByvM1gzp3jRWV4YrX20xG36VOrL2DldguPQqFdPYMoEkYopI8IcDDm4DrE9c5NylAVIMObTx5mhmEP63XfO3rAEGkgbnW1xnNKbu20naVmPFJV5I-WBcU9yvxCTTbsOH_D3EiAYVjgipo3YVrkodnPGl9uovAgzy0W8GSLLX1p=w910-h335-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;一旦MediumやHardを飛ばしつつやっていますが、Easyでもなまった体には簡単じゃないという。。。&lt;/p&gt;
&lt;p&gt;僕が見た限りだとそれぞれの問題は、ある入力を受け取って正しい結果を返す関数を書くという形式になっています。&lt;/p&gt;
&lt;p&gt;例えば第一問目は、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Given an array of integers, return indices of the two numbers such that they add up to a specific target.&lt;/p&gt;
&lt;p&gt;You may assume that each input would have exactly one solution, and you may not use the same element twice.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;という問題で、↓のような例まで紹介されています。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;そういえば、英語です。が、この程度なら問題なく読みたいところ。&lt;/p&gt;
&lt;p&gt;LeetCodeにはエディタと判定機能がついているので、LeetCode上でコードを書いて試しに動かしたり、正式に回答として登録したりできます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/_g62HL5VeDJiEVviqYPBRc22LaM_Yqt1MPJt49dbM1hzlAvgTjn7xpBtr-rFlgGygOXen5aezd6dbCd10UGUIQtIlJxpBwyvbFyQulx-nI9AZloBhR-hX1NE8uNGi9VwzuD2SOH_3FIhHxjTdwi_lGZ4xM6cz4zS3F37ecoMnTStb2yke8yfbDfNOOZzSVX5uFCZAfji-kbdKWNcmB_QQQBORbf0Ymc5e2dfGCvbbVaf7ynZkCGz7Nycui4uh6nxJWwLnLb6Pv5SPLyvktQdNaWBPhnCDdXJxdUfCjKi6R-Skl8swaTWS46CDObNIxgcgjkQDyj8VLlTUWoC0oY8KB2C-rPKbG_wICVspmAab2t9Ac6Ei3s6swXeXCHhkmPSu31K-fw6sRd5d4WesZQVGk1NrKsIy7RzOsJB87ul-DFry3xpFwp57JV-2OEkaMbsD_9ajl8-IHk6yaKL8qz0TrFI0RDifN4rQBRAoDvNLi6VDbEPCmjGVzi_s27Ey9BuyrIJhiK1yoaQkAsJ5HgvzZRC8U97i5foQcK9GrMrS8tMghI6YQHkAe6m5ie5kczm5RVpQ3zgPPOWCmdW4pbNN8bVgwKLsAjsWhm0A6WAYNg4f5rGVW_fe00dURyUno4-zNGBDzYyBD7zog4SgEUByZ2dvNT1fUVQ815krW8CcxfS9raTxcAqxo73=w450-h287-no"&gt;&lt;img src="https://lh3.googleusercontent.com/_g62HL5VeDJiEVviqYPBRc22LaM_Yqt1MPJt49dbM1hzlAvgTjn7xpBtr-rFlgGygOXen5aezd6dbCd10UGUIQtIlJxpBwyvbFyQulx-nI9AZloBhR-hX1NE8uNGi9VwzuD2SOH_3FIhHxjTdwi_lGZ4xM6cz4zS3F37ecoMnTStb2yke8yfbDfNOOZzSVX5uFCZAfji-kbdKWNcmB_QQQBORbf0Ymc5e2dfGCvbbVaf7ynZkCGz7Nycui4uh6nxJWwLnLb6Pv5SPLyvktQdNaWBPhnCDdXJxdUfCjKi6R-Skl8swaTWS46CDObNIxgcgjkQDyj8VLlTUWoC0oY8KB2C-rPKbG_wICVspmAab2t9Ac6Ei3s6swXeXCHhkmPSu31K-fw6sRd5d4WesZQVGk1NrKsIy7RzOsJB87ul-DFry3xpFwp57JV-2OEkaMbsD_9ajl8-IHk6yaKL8qz0TrFI0RDifN4rQBRAoDvNLi6VDbEPCmjGVzi_s27Ey9BuyrIJhiK1yoaQkAsJ5HgvzZRC8U97i5foQcK9GrMrS8tMghI6YQHkAe6m5ie5kczm5RVpQ3zgPPOWCmdW4pbNN8bVgwKLsAjsWhm0A6WAYNg4f5rGVW_fe00dURyUno4-zNGBDzYyBD7zog4SgEUByZ2dvNT1fUVQ815krW8CcxfS9raTxcAqxo73=w450-h287-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;試しに動かすときに使われるテストケースと正式な回答として判定するときのテストケースはやはり回答時のほうが厳しくて、項目数が多かったりエッジケースだったりとより難しい入力値が与えられます。&lt;/p&gt;
&lt;p&gt;僕も第一問を素直に実装して解けたと思ったらタイムアウトで不正解になってしまいました。&lt;/p&gt;
&lt;p&gt;衰えたプログラミング筋の筋トレだと思ってちょっとずつやっていこうかなと思います。&lt;/p&gt;</description></item><item><title>Nokogiri was built against LibXML version 2.9.4, but has dynamically loaded 2.9.7</title><link>https://blog.piyo.tech/posts/2018-09-28-nokogiri-libxml-warning/</link><pubDate>Fri, 28 Sep 2018 06:54:12 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-28-nokogiri-libxml-warning/</guid><description>&lt;p&gt;&lt;code&gt;brew upgrade&lt;/code&gt;したあとあたりから、Rails起動時にタイトルの警告が出はじめて気持ち悪いので対応します。&lt;/p&gt;
&lt;p&gt;Nokogiriビルド時とはlibxmlのバージョンが食い違っているよ、と出ているので&lt;code&gt;brew upgrade&lt;/code&gt;時に勝手にlibxmlのバージョンがあがったのでしょう。&lt;/p&gt;
&lt;p&gt;対応方法とはしては（おそらく）2通りあって、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;libxmlのバージョンを下げる&lt;/li&gt;
&lt;li&gt;Nokogiriを入れ直す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;のどちらかだと思われます。&lt;/p&gt;
&lt;p&gt;せっかくバージョンがあがったlibxmlを下げるのはもったいないのでNokogiri入れ直しで対応します。&lt;/p&gt;
&lt;p&gt;今回のケースではNokogiriに新しいバージョンがあることがわかったので、単に&lt;code&gt;bundle update&lt;/code&gt;で対応しました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% bundle update nokogiri
...
Using nokogiri 1.8.4 (was 1.8.3)
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これで警告がなくなりましたー。&lt;/p&gt;</description></item><item><title>Chrome拡張「Proxy SwitchyOmega」でサイトごとにプロキシサーバーを切り替える</title><link>https://blog.piyo.tech/posts/2018-09-26-chrome-extension-proxy-switcher/</link><pubDate>Wed, 26 Sep 2018 06:11:41 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-26-chrome-extension-proxy-switcher/</guid><description>&lt;p&gt;テスト環境などで特定のIPからのリクエストしか受け付けないようにしている場合に、ブラウザからの接続をプロキシサーバー経由にすることがあると思います。&lt;/p&gt;
&lt;p&gt;システム設定でプロキシを切り替えることができますが、すべてのリクエストをプロキシサーバー経由にするのは抵抗があります。そこで特定のサイトでだけ特定のプロキシサーバーを使うようにできるChromeエクステンションを使います。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://chromewebstore.google.com/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/Ar6pRol9XdP7QSJdQPlWUngT111eg-HCjcavM7DVg3UUIuICRhvL6_v0UcIaNt3xLuBsP0_EUww2RftpnWzYgv_MFA=s128-rj-sc0x00ffffff" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Proxy SwitchyOmega - Chrome ウェブストア&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Manage and switch between multiple proxies quickly &amp;amp; easily.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://ssl.gstatic.com/chrome/webstore/images/icon_48px.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;chrome.google.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="使い方"&gt;使い方&lt;/h1&gt;
&lt;p&gt;プロキシサーバー設定と切り替えルール設定を行えばOKです。&lt;/p&gt;
&lt;p&gt;まずはプロキシサーバーの設定から。プロキシサーバーのURLとport、そして鍵マークのアイコンから認証情報を入力しておきます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Tq9l04QYWhogqvfcDtTgMpXQlnCrJHJ-uDqT_SdifDjm9MZ1jmF7uWXymQJogWsEL7L6Gg74mF2QRsEDMxnz4ujgVtlWIg5XEFmEBfwW3OFxtkAS6sy4oPgbiqurOSHNJJk6XlJ4NoWVbAkx914nuDytMK4bOhffNEJjltqZMWccm0h9kkrt-86dnun5dsN7lTS5M2B7VTal1jmICFU8Yq6VdAD24vRAQ49USoWCPN1SbY6CH9IBPnXUexJND63ArjbQewyKD3b0u4MPcL70JfJqxHJ0BlS9dUAbo5Cs6zNH1hVRyC9Z3XEK8zf_siHZ0e1oF0YmZ5jM9-i8VmQL5Cnkc_efKN8BdmCPkxaJF3b2102n9d5GvS-JDhH09-zfFyy8OOWR3RgTIU7VtV39bn1YXyMNxf9_kEWYE6MXXrv0zxzn4gV844T3_CW2e6OyNyF4T63m_KbXfrFAXj9vY9a6vGkGlhbd5wqq-JpXLa_7vEwo4b6Mvi34mG8bO-oyhEGC5FFcYIp4TQri_ne-COMuABAA4K6q16r6EVMYKe5FWHLYY1f_JiE3zzZPeRpHxbov3VIBe8NrfVrTs0u-JrhP4wr2n7Wpu4S3EEPZLp7m48egdkRbYJOhPmFPZLs=w617-h199-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Tq9l04QYWhogqvfcDtTgMpXQlnCrJHJ-uDqT_SdifDjm9MZ1jmF7uWXymQJogWsEL7L6Gg74mF2QRsEDMxnz4ujgVtlWIg5XEFmEBfwW3OFxtkAS6sy4oPgbiqurOSHNJJk6XlJ4NoWVbAkx914nuDytMK4bOhffNEJjltqZMWccm0h9kkrt-86dnun5dsN7lTS5M2B7VTal1jmICFU8Yq6VdAD24vRAQ49USoWCPN1SbY6CH9IBPnXUexJND63ArjbQewyKD3b0u4MPcL70JfJqxHJ0BlS9dUAbo5Cs6zNH1hVRyC9Z3XEK8zf_siHZ0e1oF0YmZ5jM9-i8VmQL5Cnkc_efKN8BdmCPkxaJF3b2102n9d5GvS-JDhH09-zfFyy8OOWR3RgTIU7VtV39bn1YXyMNxf9_kEWYE6MXXrv0zxzn4gV844T3_CW2e6OyNyF4T63m_KbXfrFAXj9vY9a6vGkGlhbd5wqq-JpXLa_7vEwo4b6Mvi34mG8bO-oyhEGC5FFcYIp4TQri_ne-COMuABAA4K6q16r6EVMYKe5FWHLYY1f_JiE3zzZPeRpHxbov3VIBe8NrfVrTs0u-JrhP4wr2n7Wpu4S3EEPZLp7m48egdkRbYJOhPmFPZLs=w617-h199-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/nbh8zWF-EvvlsJyoowvckqEVWpDWja5l6-nDWdPbitWgWQJD7yOGDVQxU_iAZS3eYKvQZBIpxRhmJAF0s-9EFFu3WpoHf0YRIfTTiUHZPzX6s9kQq4hdcl_zbe_wPyj17XwH2zurFF0fGyAn7PQyquzRdRwbOZvn9_tOo9NbRE5ETh_7Dy4JhX4EFnL6Ba8PIxJSRjmPBD9S7vK04jzfOjIQRmDb7OWSRSwvjHRv53lRUR84EVbZ5dZf8HK-_vO3EE0VX1P1olbprR3Afhvy0eQuFQQVp8R5MUZpQhLhyR2jr6rf5bP_qakCOnzBKCKQDptbPsJ8E1GZfx2IyjWwIeH9GO-huamNQW5Rph3tH5ptZkmYa5ViqRQsGik9AhjGRyZduWeYVg0dhngXZwpciRPpsmnE_QjjV3D2_VxK-1g2zbiXW0kirjEX3K3iyjMYA-ZnHFR8DLSvAAYws2Ppj4BEh1PVloP3YJospIIoAPxW-1cnEV7aB3X1fviu7UFSyBrMQytMQy58IErUToa-RgmAHzLMKNnH44VT429zB8uCYMnqsPdGTgld9Zfzuaw0nADBXmR-OHjZuJ8IMjF32xbiPE3hIrZmUTn0q-Sgck6IVyvjDSlOJHeCU2MnvbU=w682-h554-no"&gt;&lt;img src="https://lh3.googleusercontent.com/nbh8zWF-EvvlsJyoowvckqEVWpDWja5l6-nDWdPbitWgWQJD7yOGDVQxU_iAZS3eYKvQZBIpxRhmJAF0s-9EFFu3WpoHf0YRIfTTiUHZPzX6s9kQq4hdcl_zbe_wPyj17XwH2zurFF0fGyAn7PQyquzRdRwbOZvn9_tOo9NbRE5ETh_7Dy4JhX4EFnL6Ba8PIxJSRjmPBD9S7vK04jzfOjIQRmDb7OWSRSwvjHRv53lRUR84EVbZ5dZf8HK-_vO3EE0VX1P1olbprR3Afhvy0eQuFQQVp8R5MUZpQhLhyR2jr6rf5bP_qakCOnzBKCKQDptbPsJ8E1GZfx2IyjWwIeH9GO-huamNQW5Rph3tH5ptZkmYa5ViqRQsGik9AhjGRyZduWeYVg0dhngXZwpciRPpsmnE_QjjV3D2_VxK-1g2zbiXW0kirjEX3K3iyjMYA-ZnHFR8DLSvAAYws2Ppj4BEh1PVloP3YJospIIoAPxW-1cnEV7aB3X1fviu7UFSyBrMQytMQy58IErUToa-RgmAHzLMKNnH44VT429zB8uCYMnqsPdGTgld9Zfzuaw0nADBXmR-OHjZuJ8IMjF32xbiPE3hIrZmUTn0q-Sgck6IVyvjDSlOJHeCU2MnvbU=w682-h554-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;続いて切り替えルールを設定します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/UjNjdsD6a03Nc6LzDBjrf3vTG074NHQHBwoxl3GjUd1yG9vOwsgBeZmWTee1UjzbEbCf3SHUjA3o8MOBzNaN-MhWtyddiJy6gVb_GIrziQRhzP9RLuFYrBKXnH7mXdRTjbLwYHGNCjXORjNCdyx4YKdC4G9GLs-UguFJEateo5dvpMoLyeNFY_HA1P1krkJIQUi__tzQlWxauj5RhurcRnsGkpNNKIp4lgO8DRxd0yseazd23gxodPDWId7hK47ISP-RmtdcLIWGCKyDGLf2XQc3L80jIg1lhMJPRpFvQMdbwkud6UxhUyTwirqcgm7ms3DzvughB8XrHhm5EqSvID0cvOQV1QRHlA50H_BrkNdhNutzjFhIgGJoY-VH4fg0SPcdmZzlRLbc7KPu0JXJ-HK8T7yKoSwQ4bJFOAWTDkDXVrya5JXLRgyBz95irwQfoVGcn43NG9qPMmYmncm6prHQxZPagwm2_Ls-QoASO_wVg10XqK-B3QCmKJI0xNTXsAgdB6YE0ZWpBj9d5HE78hlSZfeZ414Z3VxGJ56Z0ClWMnPQKz4rYkN_yWicDHpkZSssq_-fNdHPDxEdhiAhY62GGc1Hrq2ttG4AkuZ63bchzx4CNXj6RJKGrVK94Vw=w1920-h268-no"&gt;&lt;img src="https://lh3.googleusercontent.com/UjNjdsD6a03Nc6LzDBjrf3vTG074NHQHBwoxl3GjUd1yG9vOwsgBeZmWTee1UjzbEbCf3SHUjA3o8MOBzNaN-MhWtyddiJy6gVb_GIrziQRhzP9RLuFYrBKXnH7mXdRTjbLwYHGNCjXORjNCdyx4YKdC4G9GLs-UguFJEateo5dvpMoLyeNFY_HA1P1krkJIQUi__tzQlWxauj5RhurcRnsGkpNNKIp4lgO8DRxd0yseazd23gxodPDWId7hK47ISP-RmtdcLIWGCKyDGLf2XQc3L80jIg1lhMJPRpFvQMdbwkud6UxhUyTwirqcgm7ms3DzvughB8XrHhm5EqSvID0cvOQV1QRHlA50H_BrkNdhNutzjFhIgGJoY-VH4fg0SPcdmZzlRLbc7KPu0JXJ-HK8T7yKoSwQ4bJFOAWTDkDXVrya5JXLRgyBz95irwQfoVGcn43NG9qPMmYmncm6prHQxZPagwm2_Ls-QoASO_wVg10XqK-B3QCmKJI0xNTXsAgdB6YE0ZWpBj9d5HE78hlSZfeZ414Z3VxGJ56Z0ClWMnPQKz4rYkN_yWicDHpkZSssq_-fNdHPDxEdhiAhY62GGc1Hrq2ttG4AkuZ63bchzx4CNXj6RJKGrVK94Vw=w1920-h268-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;特定のURLのときだけ特定のProfile（先程作ったプロキシサーバーの設定）を使うというふうに割リ当てます。&lt;/p&gt;
&lt;p&gt;最後にブラウザの拡張機能の欄から「Auto Switch」が選択されていることが確認できけばOK。表示するサイトごとに勝手に切り替えてくれるようになります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/8ul9O8aGddt8oCc0DtIsJ4HAQ856n_f-7AvolD_atqZWtjMmlxKksmZ4ZT6vaquRAfeDBVulZjDqXrANnbQ_jeDIGRm53UQUs1t20beIaE6RfYVyVoM7FtPQ5IZ_QFvmUq9mV0zMJm9aCUihyY5WqBnphdxCtmPRmOGidvVwVWqNnVzpCEJomiXC2ng0X39_lR8i-1a39Ap_TbTmRi3lN8NCL1Zq5P47SC4hyCuJwaGWXO98VXuFys5LTkEQzPRcCvHJcYBlbM62rPK7QtBt-I1zw6lDJd1KWFKUlyDzQ5Bjddp9O7NcCpi90IKYPchssy-n7lj91VYg2TrY17WFwkNQgNA3IN9Ik-RHO9OCOco9C-itGOgYX7rE2O4LCjkM7lgbFKhr88RWqUtldvWN1PG3BZieYJS-4FurteiTtqRNdbnKF9DkOCuvDQpcdAUA_sUIF778wquUALAwFDbwoUl1rGq-bGiWP2x9PBxXfXh1H_Vy5pDuYVZuoidnXmhf5x3G_aAVisEvXLBY56-wwEe7nHN3trArWZFGRh8AslqcRtP_qFJ3KEBBPiLyYWUxCGrC9KwQtZ2u5pAXdnDsbSMxRLjkDku1wP8mQoyFWZ6qYrLTPxZcRXgrKPREBHM=w352-h470-no"&gt;&lt;img src="https://lh3.googleusercontent.com/8ul9O8aGddt8oCc0DtIsJ4HAQ856n_f-7AvolD_atqZWtjMmlxKksmZ4ZT6vaquRAfeDBVulZjDqXrANnbQ_jeDIGRm53UQUs1t20beIaE6RfYVyVoM7FtPQ5IZ_QFvmUq9mV0zMJm9aCUihyY5WqBnphdxCtmPRmOGidvVwVWqNnVzpCEJomiXC2ng0X39_lR8i-1a39Ap_TbTmRi3lN8NCL1Zq5P47SC4hyCuJwaGWXO98VXuFys5LTkEQzPRcCvHJcYBlbM62rPK7QtBt-I1zw6lDJd1KWFKUlyDzQ5Bjddp9O7NcCpi90IKYPchssy-n7lj91VYg2TrY17WFwkNQgNA3IN9Ik-RHO9OCOco9C-itGOgYX7rE2O4LCjkM7lgbFKhr88RWqUtldvWN1PG3BZieYJS-4FurteiTtqRNdbnKF9DkOCuvDQpcdAUA_sUIF778wquUALAwFDbwoUl1rGq-bGiWP2x9PBxXfXh1H_Vy5pDuYVZuoidnXmhf5x3G_aAVisEvXLBY56-wwEe7nHN3trArWZFGRh8AslqcRtP_qFJ3KEBBPiLyYWUxCGrC9KwQtZ2u5pAXdnDsbSMxRLjkDku1wP8mQoyFWZ6qYrLTPxZcRXgrKPREBHM=w352-h470-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>chrome拡張のAutofillで市のゴミ受付フォームの入力を省く</title><link>https://blog.piyo.tech/posts/2018-09-25-chrome-extension-autofill/</link><pubDate>Tue, 25 Sep 2018 06:14:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-25-chrome-extension-autofill/</guid><description>&lt;p&gt;いや、別に市のフォームに限らないんですがｗ&lt;/p&gt;
&lt;p&gt;浜松市の連絡ゴミフォームに毎度毎度住所とか名前を入れるのが面倒なのでいよいよフォーム自動入力系の拡張機能であるAutofillを導入しました。&lt;/p&gt;
&lt;p&gt;こういうのを毎回入れるの、面倒なんですよね。1年に1回使うかどうかだから余計に使うときに面倒くさいという。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/5VyRlpDig4ldCXg89jvqpyvUg1eFd_QLKtkdhUtzuW3-mGuA16rZNFs5ngoGmAFxnG6vGrj9UNS6qG_G-5oA6g_6-i0LhvQF5R1Wb-rR-N4M8QdcqlcCFIzT7fWCJa_7eFsM9O7j2NPArn-3Ivu9W7YHdd0HZ1DpYJK1R_SoWZlEE9nNZ3dH1D2T6WdijTk9GyTdAK4dgiRXXQi-Ts8Aiv9GuH-GLGHBa0Nc6t5bOoDvquXPX11v9bvMd7F008waY7bqmWqTC0o-4znKw5-fvZytO4geh6XINVOAxoGXw2dhE-PBArkCDHZS8rCmNmMFNAsWbmpMmKr_A0FSzSRk4kbAPGA7RcSu3mLlVdcM0HD_RW4T8YOGWXxz6C2STw3mLFAwERwDVaDM107MNJmhaAEvn2mXPm7JOtcVi0fH0vfFPUba8q9kA2OSkE0SB7o_7cCimtIv4-IxjCL3_FMiRwOH1XrzJ9f6CdbIhENlHHhCPpWrrNfqM9iMa3PAptd71rqt5jmgPzH6HOwB6ij_Q6WRiquU7mG2uGw2AqsnmLIhIe9I9rdkeiS8BbNvf7L2H-rMe_pA95WarGsZaVXDZ-L_eaTf47d8xEs2Jd_x7ZtY2DXT39VJwiO5CD_h4CL5VHVxn-8624cSZEOWgNwLxzA9mtnsFJ6VXKxX93jP7mSsOmCWUx37tW4B=w751-h680-no"&gt;&lt;img src="https://lh3.googleusercontent.com/5VyRlpDig4ldCXg89jvqpyvUg1eFd_QLKtkdhUtzuW3-mGuA16rZNFs5ngoGmAFxnG6vGrj9UNS6qG_G-5oA6g_6-i0LhvQF5R1Wb-rR-N4M8QdcqlcCFIzT7fWCJa_7eFsM9O7j2NPArn-3Ivu9W7YHdd0HZ1DpYJK1R_SoWZlEE9nNZ3dH1D2T6WdijTk9GyTdAK4dgiRXXQi-Ts8Aiv9GuH-GLGHBa0Nc6t5bOoDvquXPX11v9bvMd7F008waY7bqmWqTC0o-4znKw5-fvZytO4geh6XINVOAxoGXw2dhE-PBArkCDHZS8rCmNmMFNAsWbmpMmKr_A0FSzSRk4kbAPGA7RcSu3mLlVdcM0HD_RW4T8YOGWXxz6C2STw3mLFAwERwDVaDM107MNJmhaAEvn2mXPm7JOtcVi0fH0vfFPUba8q9kA2OSkE0SB7o_7cCimtIv4-IxjCL3_FMiRwOH1XrzJ9f6CdbIhENlHHhCPpWrrNfqM9iMa3PAptd71rqt5jmgPzH6HOwB6ij_Q6WRiquU7mG2uGw2AqsnmLIhIe9I9rdkeiS8BbNvf7L2H-rMe_pA95WarGsZaVXDZ-L_eaTf47d8xEs2Jd_x7ZtY2DXT39VJwiO5CD_h4CL5VHVxn-8624cSZEOWgNwLxzA9mtnsFJ6VXKxX93jP7mSsOmCWUx37tW4B=w751-h680-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そういうわけで、Autofillを入れます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://chromewebstore.google.com/detail/lightning-autofill/nlmmgnhgdeffjkdckmikfpnddkbbfkkk" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/IqqO4JXw6efABawzokq_Tn36Xp3K2h0dw9R7trEi6KXxPXWcM6LWz3qqlOUKtsIrXxKZA7DczH9trqAXu4JyoEG7=s128-rj-sc0x00ffffff" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Lightning Autofill - Chrome ウェブストア&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;The most popular autofill extension, boosting productivity since 2010.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://ssl.gstatic.com/chrome/webstore/images/icon_48px.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;chrome.google.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;これを入れると稲妻みたいなアイコンが拡張機能のところに入ります。&lt;/p&gt;
&lt;p&gt;目的のフォームがある画面で稲妻アイコンを押すと↓のような案内が現れます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/q6W6wZWkg8ZmZ2Ax63BH4cmdgtiNZR9rscwAOoF7ycnF8bbcvD2Z73IEPybRtDfacz76TVeUlwz4JAjfm-QicbDjbbhrZbAlX7P3WEkz_UzBAtV9YDjUq6woAVXY1GVgg5_43aiq4kW29V-Bh2jjT3m10skux-Z98ftITVfgmFYnZcNYqsi-bEl2p3KXK-anvItHbT6nKkK3cSBRHNfET1PnX0F3Li5_JfP8wmU8I3sdXA2L4zp9WpMb5WvDjP_yWYEIvN2kmFR3wiBaXha207c-ArN7nPEtCny8BulEZ3HWrfdj66uTJ6Mc3j6dSQGSEcH9gLq9Gxp8o45oL3Zpx7qGi6v0jlGbPV5_o8kABctd7jnus3yMp_OiTxJDihzYIsa90hUA_PQ_BqFRG3O5AENgxJYqiJtBA_gFpcY4xS6Z6Ktx381SSGWaEOWs4Bot1MqPDOu04yyUZyA9EPqYQeDoUlFzTrcQOX8BslPHBLlDGppbBXUIWJBIwUOlQPM58LL4NbCz_ZO519m2EmzPKEADXb8ykQaWOT8oWUbY-93KQooQiepRu0vMeP14xJN1MXPLjAIgqttJ8wrWrFlcrg7p5P3Ii4Wai4qZnpxiGPhkRC16W9vsZTf2XEqcgPPFL2U7l5717m99V0EepkMO9kEHh5-oUJuiyxCzNTzZ6fM0bnG9S0vkVwzu=w562-h101-no"&gt;&lt;img src="https://lh3.googleusercontent.com/q6W6wZWkg8ZmZ2Ax63BH4cmdgtiNZR9rscwAOoF7ycnF8bbcvD2Z73IEPybRtDfacz76TVeUlwz4JAjfm-QicbDjbbhrZbAlX7P3WEkz_UzBAtV9YDjUq6woAVXY1GVgg5_43aiq4kW29V-Bh2jjT3m10skux-Z98ftITVfgmFYnZcNYqsi-bEl2p3KXK-anvItHbT6nKkK3cSBRHNfET1PnX0F3Li5_JfP8wmU8I3sdXA2L4zp9WpMb5WvDjP_yWYEIvN2kmFR3wiBaXha207c-ArN7nPEtCny8BulEZ3HWrfdj66uTJ6Mc3j6dSQGSEcH9gLq9Gxp8o45oL3Zpx7qGi6v0jlGbPV5_o8kABctd7jnus3yMp_OiTxJDihzYIsa90hUA_PQ_BqFRG3O5AENgxJYqiJtBA_gFpcY4xS6Z6Ktx381SSGWaEOWs4Bot1MqPDOu04yyUZyA9EPqYQeDoUlFzTrcQOX8BslPHBLlDGppbBXUIWJBIwUOlQPM58LL4NbCz_ZO519m2EmzPKEADXb8ykQaWOT8oWUbY-93KQooQiepRu0vMeP14xJN1MXPLjAIgqttJ8wrWrFlcrg7p5P3Ii4Wai4qZnpxiGPhkRC16W9vsZTf2XEqcgPPFL2U7l5717m99V0EepkMO9kEHh5-oUJuiyxCzNTzZ6fM0bnG9S0vkVwzu=w562-h101-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この状態でフォームを入力したあと、プロファイルを分けたい場合は選んで、「Generate Autofill Rules」を押すと情報が登録されます。&lt;/p&gt;
&lt;p&gt;これでフォームと内容が紐づくので、同じページに再度訪れたときには自動入力が完了しているはずです。&lt;/p&gt;
&lt;p&gt;確認したければ、autofillのオプション画面で確認可能です。&lt;/p&gt;
&lt;p&gt;注意点としてはhiddenフォームすら自動入力してしまうらしい（ソース見つからず）ということがあるみたいで、その仕組みを使って情報を盗もうとするケースがありえるらしいので、重要な情報はautofill対象外にしておくのが良いと思います。パスワードとかカード番号とか。&lt;/p&gt;</description></item><item><title>モバイルアプリ用の全アイコンサイズを1枚の画像から書き出せるサイト</title><link>https://blog.piyo.tech/posts/2018-09-24-make-mobile-app-icon/</link><pubDate>Mon, 24 Sep 2018 06:36:16 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-24-make-mobile-app-icon/</guid><description>&lt;p&gt;モバイルアプリのアイコンを全部用意するの面倒ですよね。毎度必要なサイズが変わるし。&lt;/p&gt;
&lt;p&gt;僕は大きめの正方形画像を用意して、それを元に一括で縮小して生成してくれるサイトを使っています。ちゃんと調べていないので他にもあるのかもしれないですけど、僕はここを使ってます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://makeappicon.com/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="http://makeappicon.com/static/images/social-icon.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Developer Tool - App Icon Resizer&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;MakeAppIcon is an app icon resizer that helps developers and project managers generate the app icons required by App Store &amp;amp; Google Play Store.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://makeappicon.com/_astro/favicon.EytxFxZo.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;makeappicon.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;1536x1536&lt;/code&gt;の画像を渡すと、メールで処理結果を送ってくれます。&lt;/p&gt;
&lt;p&gt;結果画像には↓が入ってます。長いです。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% tree
.
├── android
│   ├── mipmap-hdpi
│   │   └── ic_launcher.png
│   ├── mipmap-ldpi
│   │   └── ic_launcher.png
│   ├── mipmap-mdpi
│   │   └── ic_launcher.png
│   ├── mipmap-xhdpi
│   │   └── ic_launcher.png
│   ├── mipmap-xxhdpi
│   │   └── ic_launcher.png
│   ├── mipmap-xxxhdpi
│   │   └── ic_launcher.png
│   └── playstore-icon.png
├── imessenger
│   ├── icon-messages-app-27x20@1x.png
│   ├── icon-messages-app-27x20@2x.png
│   ├── icon-messages-app-27x20@3x.png
│   ├── icon-messages-app-iPadAir-67x50@2x.png
│   ├── icon-messages-app-iPadAir-74x55@2x.png
│   ├── icon-messages-app-iPhone-60x45@1x.png
│   ├── icon-messages-app-iPhone-60x45@2x.png
│   ├── icon-messages-app-iPhone-60x45@3x.png
│   ├── icon-messages-app-store-1024x768.png
│   ├── icon-messages-transcript-32x24@1x.png
│   ├── icon-messages-transcript-32x24@2x.png
│   └── icon-messages-transcript-32x24@3x.png
└── ios
├── AppIcon.appiconset
│   ├── Contents.json
│   ├── Icon-App-20x20@1x.png
│   ├── Icon-App-20x20@2x.png
│   ├── Icon-App-20x20@3x.png
│   ├── Icon-App-29x29@1x.png
│   ├── Icon-App-29x29@2x.png
│   ├── Icon-App-29x29@3x.png
│   ├── Icon-App-40x40@1x.png
│   ├── Icon-App-40x40@2x.png
│   ├── Icon-App-40x40@3x.png
│   ├── Icon-App-57x57@1x.png
│   ├── Icon-App-57x57@2x.png
│   ├── Icon-App-60x60@1x.png
│   ├── Icon-App-60x60@2x.png
│   ├── Icon-App-60x60@3x.png
│   ├── Icon-App-72x72@1x.png
│   ├── Icon-App-72x72@2x.png
│   ├── Icon-App-76x76@1x.png
│   ├── Icon-App-76x76@2x.png
│   ├── Icon-App-76x76@3x.png
│   ├── Icon-App-83.5x83.5@2x.png
│   ├── Icon-Small-50x50@1x.png
│   ├── Icon-Small-50x50@2x.png
│   └── ItunesArtwork@2x.png
├── README.md
├── iTunesArtwork@1x.png
├── iTunesArtwork@2x.png
└── iTunesArtwork@3x.png
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;たとえばiOSの場合はこの中にある&lt;code&gt;AppIcon.appiconset&lt;/code&gt;をXcodeにドラッグ&amp;amp;ドロップすると&lt;code&gt;AppIcon-1&lt;/code&gt;というアセットとして登録できます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/JohMpLJ-Zb3AsK5paqoXTJEy-BY2cC_dDJMScsxh6NEK30BeZZcoI8mDRuh-VVHqLiyouUS_c1w59vb8ESZnHEyrDrlN7vN0tlwg5ugmc4cWcKFAHi3_qwwofmWyayoBxj17wubS2kEnYqfeocgE2LXh1PiMHhMpcaQPC6fF-8NLbs0NJohWs06N3zSRuz4ZtgEy14T9Pth6wro95sOF3bTAnSq3ckBypxU9Y1UuwoJAmNwSNCqYXEF1g4oIbw9JoWA2EY--XsGAhy-x_7N9XR2UzYu73Q3hcilngMiBfPpHqjQtBVZ4pSNScau3bme7h4x1iMUK_QzzP08yTpi9xbG6G1OB53MLeXSEXoIQbKUsbYROr1urEB9awum0wwujPg5m0QpeLwkkv2L-rfclPZO0jwoEK4ru2WkIqPDZer-apBEO3YhqHRUNXqeggJNBN36j1snmLKME80-E9csg0sBI-vzK_92bTNdcuLL0cefT-UCQRdURZoVVyADOVBi17NB00N9QhimGVYeUi9QnvRyqGxcP1FzLHlNIdm5lzjv0Qs4tElKmTb-XiyM3Ek-GOVVmF9PWNHhdeODoW2WUR9DYuhUArj7LCcHTUJWompLQvB6vYaufTQbVafJo8lFdMGo2GSiKVJeNTzkjM4CKg4SG_1aRZQpK02ZQuG-QVmMJ4WB1vP_uZEGH=w422-h490-no"&gt;&lt;img src="https://lh3.googleusercontent.com/JohMpLJ-Zb3AsK5paqoXTJEy-BY2cC_dDJMScsxh6NEK30BeZZcoI8mDRuh-VVHqLiyouUS_c1w59vb8ESZnHEyrDrlN7vN0tlwg5ugmc4cWcKFAHi3_qwwofmWyayoBxj17wubS2kEnYqfeocgE2LXh1PiMHhMpcaQPC6fF-8NLbs0NJohWs06N3zSRuz4ZtgEy14T9Pth6wro95sOF3bTAnSq3ckBypxU9Y1UuwoJAmNwSNCqYXEF1g4oIbw9JoWA2EY--XsGAhy-x_7N9XR2UzYu73Q3hcilngMiBfPpHqjQtBVZ4pSNScau3bme7h4x1iMUK_QzzP08yTpi9xbG6G1OB53MLeXSEXoIQbKUsbYROr1urEB9awum0wwujPg5m0QpeLwkkv2L-rfclPZO0jwoEK4ru2WkIqPDZer-apBEO3YhqHRUNXqeggJNBN36j1snmLKME80-E9csg0sBI-vzK_92bTNdcuLL0cefT-UCQRdURZoVVyADOVBi17NB00N9QhimGVYeUi9QnvRyqGxcP1FzLHlNIdm5lzjv0Qs4tElKmTb-XiyM3Ek-GOVVmF9PWNHhdeODoW2WUR9DYuhUArj7LCcHTUJWompLQvB6vYaufTQbVafJo8lFdMGo2GSiKVJeNTzkjM4CKg4SG_1aRZQpK02ZQuG-QVmMJ4WB1vP_uZEGH=w422-h490-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;元あった&lt;code&gt;AppIcon&lt;/code&gt;を削除して&lt;code&gt;AppIcon-1&lt;/code&gt;を&lt;code&gt;AppIcon&lt;/code&gt;としてリネームすれば（もしくはプロジェクト設定でAppIconsSourceの参照を変更すれば）、アプリのアイコンとして設定完了となります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/f70jQp2ZItcNgyJ78z7uq5zstIymu-zd2Y3ujbboYkr8B-VgT3urz1GMTEeJVgw_8uLLLZWuTMFUe8uOujr8WkVWgiPT6ovVZvjj7-e-FFnWYCcsvHykH_uZdNaOCJyOpa7U_DxqA5i1AKhl-56pr3nqT-xcZ6cB3fvVglxp-ttg3fkuaNugXU3oygR1bgc9yYdiIa15CVJbsG0i2SnM9Vs7fpkzRYC_FY0St4_HjkqDaPdEqNmQ8gZ52tcAOnmr3id0E4k6yFaMnH5r4aD2TE8wU0DscmROs3aDyqdJaquX3CH99yv-fx3ToaRLbJLRmYETZrRp4VAZ7spny3lqfmZuveIG1p9cscsfSOPim-F8S41A5culX_8fbot7HoE3l5fj_MlJ_z6NXfJukWUwP77hTPTXlYU0LKF-cJZKzc8FmSZ55cNx8X4fk_VDk1jvr7nb_eSY3PZep5pdXR2s2z_i09t9vs59F1qN-HBnUMIrptIu0kvNCSYpuXlNAr-4cP8syrhm7e7K17_frcdBzwrj-82p4icZMOpCu1mn7M0IFVOenRr7rjUWhEQdnniJqZJhmKi6cM8caiqTd8Rb4M89rsATEPbdJotAAVtjK5S8LdQLPegzcckMrI4_xxs=w1046-h504-no"&gt;&lt;img src="https://lh3.googleusercontent.com/f70jQp2ZItcNgyJ78z7uq5zstIymu-zd2Y3ujbboYkr8B-VgT3urz1GMTEeJVgw_8uLLLZWuTMFUe8uOujr8WkVWgiPT6ovVZvjj7-e-FFnWYCcsvHykH_uZdNaOCJyOpa7U_DxqA5i1AKhl-56pr3nqT-xcZ6cB3fvVglxp-ttg3fkuaNugXU3oygR1bgc9yYdiIa15CVJbsG0i2SnM9Vs7fpkzRYC_FY0St4_HjkqDaPdEqNmQ8gZ52tcAOnmr3id0E4k6yFaMnH5r4aD2TE8wU0DscmROs3aDyqdJaquX3CH99yv-fx3ToaRLbJLRmYETZrRp4VAZ7spny3lqfmZuveIG1p9cscsfSOPim-F8S41A5culX_8fbot7HoE3l5fj_MlJ_z6NXfJukWUwP77hTPTXlYU0LKF-cJZKzc8FmSZ55cNx8X4fk_VDk1jvr7nb_eSY3PZep5pdXR2s2z_i09t9vs59F1qN-HBnUMIrptIu0kvNCSYpuXlNAr-4cP8syrhm7e7K17_frcdBzwrj-82p4icZMOpCu1mn7M0IFVOenRr7rjUWhEQdnniJqZJhmKi6cM8caiqTd8Rb4M89rsATEPbdJotAAVtjK5S8LdQLPegzcckMrI4_xxs=w1046-h504-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;警告マークがでてますが、割り当てられていない画像が含まれているというだけなので、それらを削除すれば警告はなくなります。&lt;/p&gt;
&lt;p&gt;一括生成してくれる上に設定も一括で終わるので大変重宝しています。&lt;/p&gt;</description></item><item><title>Vue コンポーネントのデータを初期値にリセットしたいとき</title><link>https://blog.piyo.tech/posts/2018-09-22-vue-reinitialize-data/</link><pubDate>Sat, 22 Sep 2018 06:53:56 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-22-vue-reinitialize-data/</guid><description>&lt;p&gt;どうやって書くのがいいのかなーと迷いました。&lt;/p&gt;
&lt;p&gt;例として適切ではないですが、例えば↓のようなコンポーネントがあったとして、なにかのタイミングですべてのデータをリセットしたいとします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;App&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Hello World&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;message&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;your todo app&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;todos&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;何も考えずに書くと、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;title&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Hello World&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;message&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;your todo app&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;todos&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;みたいになりますが、項目が増えたときに破綻するのは目に見えています。&lt;/p&gt;
&lt;p&gt;そこでこちらの&lt;code&gt;$data&lt;/code&gt;を使います。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://jp.vuejs.org/v2/api/#vm-data" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;jp.vuejs.org →&lt;/span&gt;&lt;span&gt;https://jp.vuejs.org/v2/api/#vm-data&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;この&lt;code&gt;$data&lt;/code&gt;にデータオブジェクトが入っているので、まとめて値をセットするときには&lt;code&gt;$data&lt;/code&gt;へのアサインで代用できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 外に関数を1つつくっておく
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;initialState&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Hello World&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;message&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;your todo app&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;todos&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;App&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 初期値として関数呼び出しの結果を返す
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;initialState&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;methods&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;reset&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// リセット時は`$data`にアサイン
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; Object.&lt;span style="color:#a6e22e"&gt;assign&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;$data&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;initialState&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで一応動いてくれました。&lt;/p&gt;
&lt;p&gt;もっといい方法があるとか、これだとだめな理由があるとかの場合はお知らせしてもらえると嬉しいです。&lt;/p&gt;
&lt;h1 id="追記"&gt;追記&lt;/h1&gt;
&lt;p&gt;↑の方法では、途中で新しいプロパティを&lt;code&gt;this.data&lt;/code&gt;追加した場合にそのプロパティが残ったままになってしまいます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;memo&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;hogehoge&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;その場合、一度すべてのプロパティを一度削除してから上記の&lt;code&gt;assign&lt;/code&gt;のコードを実行するのが無難です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;methods&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;reset&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; Object.&lt;span style="color:#a6e22e"&gt;keys&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;$data&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;forEach&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;key&lt;/span&gt; =&amp;gt; &lt;span style="color:#66d9ef"&gt;delete&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;$data&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; Object.&lt;span style="color:#a6e22e"&gt;assign&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;$data&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;initialState&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Electronアプリでvue-devtoolを使えるようにする</title><link>https://blog.piyo.tech/posts/2018-09-21-electron-vue-devtool/</link><pubDate>Fri, 21 Sep 2018 06:28:29 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-21-electron-vue-devtool/</guid><description>&lt;p&gt;ElectronアプリでVueを使うようにしたらコンソールにこんなのが出ていました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Download the Vue Devtools extension for a better development experience:
https://github.com/vuejs/vue-devtools
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;vue-devtoolを入れると便利だよ、ということらしいので調べてみました。&lt;/p&gt;
&lt;p&gt;Vueを使ったWebサイトの場合はブラウザ側にvue-devtoolを入れることでDeveloperToolを拡張できるんですが、Electronでは勝手が異なります。&lt;/p&gt;
&lt;p&gt;devtoolに関するドキュメントがあったので読んでみました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://electronjs.org/docs/latest/tutorial/devtools-extension" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;DevTools Extension | Electron&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Electron supports Chrome DevTools extensions, which can be used to extend the ability of Chrome&amp;#39;s developer tools for debugging popular web frameworks.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://electronjs.org/assets/img/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;electronjs.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ここで紹介されているやり方を整理すると&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;chromeに対象のdevtoolを入れて&lt;/li&gt;
&lt;li&gt;その拡張のextension IDを調べて&lt;/li&gt;
&lt;li&gt;ファイルシステム上で場所を特定して&lt;/li&gt;
&lt;li&gt;Electronのready後に&lt;code&gt;BrowserWindow.addDevToolsExtension&lt;/code&gt;する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ということでした。&lt;/p&gt;
&lt;p&gt;めんどくさいなーと思ってよくよく読んでいたら&lt;code&gt;electron-devtools-installer&lt;/code&gt;というのを使ってもいいよという記述がありましたので、こちらを試してみました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/MarshallOfSound/electron-devtools-installer" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/59011b45e6e68c504ca40f9665984480d9308a97ac0bce64f6d922f7e70d1e5d/MarshallOfSound/electron-devtools-installer" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - MarshallOfSound/electron-devtools-installer: An easy way to ensure Chrome DevTools extensions into Electron&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;An easy way to ensure Chrome DevTools extensions into Electron - MarshallOfSound/electron-devtools-installer&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;まず対象のElectronのプロジェクトでこのパッケージを導入します。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;npm i -S electron-devtools-installer
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;つぎにmainプロセスにて以下のコードを追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;installExtension&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;VUEJS_DEVTOOLS&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;electron-devtools-installer&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createWindow&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// いろいろ略
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ready後のコールバック内で呼ぶ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;installExtension&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;VUEJS_DEVTOOLS&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;on&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;ready&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;createWindow&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでアプリを起動し直すとDeveloperToolにVueタブが出てきてくれます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/TeZ4g9AR3rzqkqGorXmuDlJm80ChEV-oEJbHj79igeZN9D-qjkmH81amXuWIMhkqubK033PkE8yp72OL_QDLf1TdvRTgn_XftrW4fQLsFqkZcmmCslKFsolC125YYsUrg4uOOYqG0hUC7rqOcSjvJQsaohrtVpIWw7tCRHeTu6aiVnUjpdyZ4SormJO1iF58sgbA0iOFGiuSL1hFmVvGDa0FXegfIlEXw9cHV93g-3_-qbwxD8HRNghWcaT3KSwKeW8QbRk1KigJLSRhOIu_WSbj_grquuJgsJjvjvew9vK_EG7Cbi7pHsUQvnxD_PExVLufY4yIhbayXZPlibQJOF4M6DXKwGRf6dFYHuc20E4dWnClMd4jP6w-CcAdDgLxuzn_j588XiDe0OVQ5dwrWHHKx7Fdc0iytS3cUdRle9cmjH76MnovPCcsZ1GtsdbObIx34RRPPi-IuMs3EJPL-vvSBl48k_kQCFXmo_k3wcFGS45-lK37Yko4D531Wh_NUBgo_-SsuhIWB9sEKzB1HntN03rL7cmVdOLGiXrEKjuqQFZi7Kad6jDQIQqMXmYRI8fkSyH-kennNlWKYE66A8Y8vJz579uvE_YX2xVgrSxgZXzb6pqu_s8GjEKx173wrCicme7nN1tI9YR-Z4ecElTd8Tt-uUBNgYBIBZSmHNLvoV9vX9t4Kz5t=w810-h188-no"&gt;&lt;img src="https://lh3.googleusercontent.com/TeZ4g9AR3rzqkqGorXmuDlJm80ChEV-oEJbHj79igeZN9D-qjkmH81amXuWIMhkqubK033PkE8yp72OL_QDLf1TdvRTgn_XftrW4fQLsFqkZcmmCslKFsolC125YYsUrg4uOOYqG0hUC7rqOcSjvJQsaohrtVpIWw7tCRHeTu6aiVnUjpdyZ4SormJO1iF58sgbA0iOFGiuSL1hFmVvGDa0FXegfIlEXw9cHV93g-3_-qbwxD8HRNghWcaT3KSwKeW8QbRk1KigJLSRhOIu_WSbj_grquuJgsJjvjvew9vK_EG7Cbi7pHsUQvnxD_PExVLufY4yIhbayXZPlibQJOF4M6DXKwGRf6dFYHuc20E4dWnClMd4jP6w-CcAdDgLxuzn_j588XiDe0OVQ5dwrWHHKx7Fdc0iytS3cUdRle9cmjH76MnovPCcsZ1GtsdbObIx34RRPPi-IuMs3EJPL-vvSBl48k_kQCFXmo_k3wcFGS45-lK37Yko4D531Wh_NUBgo_-SsuhIWB9sEKzB1HntN03rL7cmVdOLGiXrEKjuqQFZi7Kad6jDQIQqMXmYRI8fkSyH-kennNlWKYE66A8Y8vJz579uvE_YX2xVgrSxgZXzb6pqu_s8GjEKx173wrCicme7nN1tI9YR-Z4ecElTd8Tt-uUBNgYBIBZSmHNLvoV9vX9t4Kz5t=w810-h188-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;よかった。入りました。&lt;/p&gt;
&lt;p&gt;他のDevtool系も同様の方法で入れられるようなので覚えとくと便利そうです。&lt;/p&gt;</description></item><item><title>ElectronのDeveloper Toolでコピーやペーストを有効にする</title><link>https://blog.piyo.tech/posts/2018-09-20-electron-copy-paste-on-developer-tool/</link><pubDate>Thu, 20 Sep 2018 06:34:45 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-20-electron-copy-paste-on-developer-tool/</guid><description>&lt;p&gt;ElectronってDeveloper Toolでのコピペがそのままじゃできないんですね。&lt;/p&gt;
&lt;p&gt;メニューにコピーペーストなど、必要な「編集」機能は実施しておかないといけないみたいです。&lt;/p&gt;
&lt;p&gt;よくある「編集メニュー」にある機能というと、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;コピー&lt;/li&gt;
&lt;li&gt;ペースト&lt;/li&gt;
&lt;li&gt;カット&lt;/li&gt;
&lt;li&gt;アンドゥ&lt;/li&gt;
&lt;li&gt;リドゥ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;あたりでしょうか。Developer Toolの用途だけでもあったほうがよさそうなのでこれを実装してみます。&lt;/p&gt;
&lt;h1 id="普通に実装してみる"&gt;普通に実装してみる&lt;/h1&gt;
&lt;p&gt;メニューのテンプレートに編集メニューとサブメニューを実装します。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;label&lt;/code&gt;とか&lt;code&gt;accelerator&lt;/code&gt;を指定するやり方ですね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;template&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;label&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Electron&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;submenu&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;label&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;編集&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;submenu&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; { &lt;span style="color:#a6e22e"&gt;label&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;コピー&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;accelerator&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;CmdOrCtrl+C&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;selector&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;copy:&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; { &lt;span style="color:#a6e22e"&gt;label&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ペースト&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;accelerator&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;CmdOrCtrl+V&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;selector&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;paste:&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;menu&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Menu&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;buildFromTemplate&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;template&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Menu&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setApplicationMenu&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;menu&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/PDmEpIt546SdyXPfo-ZGMLi0hBjgS4SC02Fe4cl1APSnkLsL1BzhoETAyFrMf05DGfwGR5gd-k-BAW0vbae093JVW74_8XPlb3NNNZHj_bUjP0GPSsffz5MrMcDg_7Unir0CXlcYjGnms7oBYayreJTk4-TsBwSXcKT-5rgPwg8hakFJIUG0c3sYUM2vb00X6vKkFozhHzVaKITWMJrN_vVv6yGC1rS7zgcvsy3LUwVR_3JOWo1vu1ZkHcJVB8AYy9FFs5QRBwL66g0fzXEGpGn6KAYqNfPozyBWIZpL2nU8yaOJd2mBxD_ZaTwgt2mgtF2VlEQD51m27yg7Zp_AwpZ_enDZfn-ATTzL4wAxl2RoDIP-Oaq-MAOtrsqEq4P7qUivy9RB-G3Lql04F8F3dYAf8k5Xj_UyVy3mquuntu6QsKTJ0lmtSKbDeJCXvscbR7chVzbt7-QQfQZLLpZPEuztdHtYNlSiVqN9i2lqZt8zveBa0dARK78zfmImd_EAU63zrVpABjURJ4YJiUbh_R1ETEGrlso4-bsZie8tQiNXwiwAbcX2iiP0jkssMGSyQ9OPSzA0LcbJhLzTh6AmE4xE2j57JuXu1YCHbGzUWXH3ioZByyiBzp10QtjOyeKWXWWr_3c2hwOrJ6UK8eDl43Oys91t1Cpp4gVH7lioxfzOctgxRAd5YDb4=w301-h121-no"&gt;&lt;img src="https://lh3.googleusercontent.com/PDmEpIt546SdyXPfo-ZGMLi0hBjgS4SC02Fe4cl1APSnkLsL1BzhoETAyFrMf05DGfwGR5gd-k-BAW0vbae093JVW74_8XPlb3NNNZHj_bUjP0GPSsffz5MrMcDg_7Unir0CXlcYjGnms7oBYayreJTk4-TsBwSXcKT-5rgPwg8hakFJIUG0c3sYUM2vb00X6vKkFozhHzVaKITWMJrN_vVv6yGC1rS7zgcvsy3LUwVR_3JOWo1vu1ZkHcJVB8AYy9FFs5QRBwL66g0fzXEGpGn6KAYqNfPozyBWIZpL2nU8yaOJd2mBxD_ZaTwgt2mgtF2VlEQD51m27yg7Zp_AwpZ_enDZfn-ATTzL4wAxl2RoDIP-Oaq-MAOtrsqEq4P7qUivy9RB-G3Lql04F8F3dYAf8k5Xj_UyVy3mquuntu6QsKTJ0lmtSKbDeJCXvscbR7chVzbt7-QQfQZLLpZPEuztdHtYNlSiVqN9i2lqZt8zveBa0dARK78zfmImd_EAU63zrVpABjURJ4YJiUbh_R1ETEGrlso4-bsZie8tQiNXwiwAbcX2iiP0jkssMGSyQ9OPSzA0LcbJhLzTh6AmE4xE2j57JuXu1YCHbGzUWXH3ioZByyiBzp10QtjOyeKWXWWr_3c2hwOrJ6UK8eDl43Oys91t1Cpp4gVH7lioxfzOctgxRAd5YDb4=w301-h121-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="もっと楽に書く"&gt;もっと楽に書く&lt;/h1&gt;
&lt;p&gt;ドキュメントを見たら&lt;code&gt;role&lt;/code&gt;というのを使えることがわかりました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://electronjs.org/docs/latest/api/menu" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Menu | Electron&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Create application menus and context menus.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://electronjs.org/assets/img/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;electronjs.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;例えば&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;template&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;label&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Edit&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;submenu&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;role&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;undo&amp;#39;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;role&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;redo&amp;#39;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;separator&amp;#39;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;role&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;cut&amp;#39;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;role&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;copy&amp;#39;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;role&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;paste&amp;#39;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;role&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;pasteandmatchstyle&amp;#39;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;role&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;delete&amp;#39;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;role&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;selectall&amp;#39;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;menu&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Menu&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;buildFromTemplate&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;template&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Menu&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setApplicationMenu&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;menu&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とすると、こんなメニューになります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/CpXmmjMjuRgunpHe14U7KIiyEVLSG3cGRX94-H8O6TP9a8Hn8Dv3lImsV9bwde5dgmgRjPPwoiFNyhlnXdcfFH2elx-a8a4FjpwKTFmC4Tva7FpRJKQSasV3ZM-5BDSK7cS5IvdOF3xVGPiRThH-YVLmCctz0jFBxHDVOG_nYJbci-DZl3b07pKQRgWEjXhlK8lxYSGzwVjYn0k9VH7sz39XYbGEyAxgIZdHUJmg2nBld_V_kASWuyIAe60hWHJ1M10W8X2SU6WQ2VKsPOiN695-aX5VPsFNcn_-iKQVrHGk4x6inVdiRPeqXQi2gWPtSqh2BvODHxS_snoOyGeXj8MJmHPYMb7xbFS5aEj2I8qS_2gij4VRT8zJV4cO2mv1al816u13ezXAJJkPEugQpmQfy_bVqTVbdbmRqz9-QARAXETRnapc5PKP87zUtA-ziXPF3tO57Ko97DVaZiO3ltkJ9tZXbVkPGEwuHwjFpCKQ8hnV4lb_X5cJ4TXSN20TnvXFLLu-5pwMJmAny1jIlOojgDv8lOjKY4Hd8wTrAv01gwKcjnZfRNOC-oOJz1MKAd9oEiGb9f9PzRMwmgeow9jylIBsSzv9AB69HGW_5XxK2PDn4O-GftiMKi4-7ENUQrq0GMddivnIE7CFTTTOUxsqTn4oqDLvqai89GzP2Fn3ZBoBeAvUeMGM=w279-h263-no"&gt;&lt;img src="https://lh3.googleusercontent.com/CpXmmjMjuRgunpHe14U7KIiyEVLSG3cGRX94-H8O6TP9a8Hn8Dv3lImsV9bwde5dgmgRjPPwoiFNyhlnXdcfFH2elx-a8a4FjpwKTFmC4Tva7FpRJKQSasV3ZM-5BDSK7cS5IvdOF3xVGPiRThH-YVLmCctz0jFBxHDVOG_nYJbci-DZl3b07pKQRgWEjXhlK8lxYSGzwVjYn0k9VH7sz39XYbGEyAxgIZdHUJmg2nBld_V_kASWuyIAe60hWHJ1M10W8X2SU6WQ2VKsPOiN695-aX5VPsFNcn_-iKQVrHGk4x6inVdiRPeqXQi2gWPtSqh2BvODHxS_snoOyGeXj8MJmHPYMb7xbFS5aEj2I8qS_2gij4VRT8zJV4cO2mv1al816u13ezXAJJkPEugQpmQfy_bVqTVbdbmRqz9-QARAXETRnapc5PKP87zUtA-ziXPF3tO57Ko97DVaZiO3ltkJ9tZXbVkPGEwuHwjFpCKQ8hnV4lb_X5cJ4TXSN20TnvXFLLu-5pwMJmAny1jIlOojgDv8lOjKY4Hd8wTrAv01gwKcjnZfRNOC-oOJz1MKAd9oEiGb9f9PzRMwmgeow9jylIBsSzv9AB69HGW_5XxK2PDn4O-GftiMKi4-7ENUQrq0GMddivnIE7CFTTTOUxsqTn4oqDLvqai89GzP2Fn3ZBoBeAvUeMGM=w279-h263-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Developer Toolでエラーメッセージを一部コピーするとか、コードを貼り付けて確認するとかは絶対すると思うので、開発効率のためにも編集メニューは必要そうですね〜&lt;/p&gt;</description></item><item><title>ElectronアプリをVue化する</title><link>https://blog.piyo.tech/posts/2018-09-19-introduce-vue-to-electron-app/</link><pubDate>Wed, 19 Sep 2018 06:59:27 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-19-introduce-vue-to-electron-app/</guid><description>&lt;p&gt;jQueryでベタっと書いていたElectronアプリがあるのですが、Electronに多少慣れたこともあってアプリ側のコードをきれいにしたくなりました。Vue.jsを使いたい（正確に言うとVueはまだ触ったことがないので使ってみたい）ので、その下準備としてひとまずVueコンポーネント1個だけの形に持っていきましたので、その過程を残しておこうと思います。&lt;/p&gt;
&lt;h1 id="依存ライブラリや設定を追加"&gt;依存ライブラリや設定を追加&lt;/h1&gt;
&lt;p&gt;まずは関連するパッケージを追加しました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# vue 本体
$ npm install -S vue
# vue 関連
$ npm install -D vue-loader vue-style-loader vue-template-loader vue-template-compiler
# ついでにcss 関連
$ npm install -D css-loader sass-loader
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;vue用のloaderを書いたり、警告が出ないように一部追記があります。警告の件は後述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;diff --git a/webpack.config.js b/webpack.config.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;index 9d3856c..0976ca8 100644
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;--- a/webpack.config.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+++ b/webpack.config.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;@@ -18,12 +18,15 @@ module.exports = {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; resolve: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+ alias: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+ &amp;#39;vue$&amp;#39;: &amp;#39;vue/dist/vue.esm.js&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+ },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; modules: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; path.resolve(__dirname, &amp;#34;src&amp;#34;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &amp;#34;node_modules&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; module: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;@@ -49,7 +52,12 @@ module.exports = {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; test: /\.node$/,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; use: &amp;#39;node-loader&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+ },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+ {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+ test: /\.vue$/,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+ use: &amp;#39;vue-loader&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="vueコンポーネント化"&gt;Vueコンポーネント化&lt;/h1&gt;
&lt;p&gt;HTMLとレンダラー用のJSをVueコンポートネントにまとめました。&lt;/p&gt;
&lt;h2 id="html"&gt;HTML&lt;/h2&gt;
&lt;p&gt;まず、元々&lt;code&gt;index.html&lt;/code&gt;に書いてあった内容をVueコンポーネントの&lt;code&gt;template&lt;/code&gt;に移動します。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt; の一部&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;container&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;色々&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;index.htmlの一部&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;App.vue&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
&amp;lt;div id=&amp;#34;app&amp;#34;&amp;gt;
&amp;lt;div class=&amp;#34;container&amp;#34;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="js"&gt;JS&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;index.js&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(document).&lt;span style="color:#a6e22e"&gt;ready&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;#button&amp;#34;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;(() =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 色々やる
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;index.js&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;vue&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;App&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;./App.vue&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Vue&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;el&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;#app&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;components&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;App&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;template&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;app&amp;gt;&amp;lt;/app&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;App.vue&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-vue" data-lang="vue"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;色々&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;App&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;methods&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;button&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="コンパイラ警告の件"&gt;コンパイラ警告の件&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;webpack.config.js&lt;/code&gt;の↓のオプションについて。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;resolve&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// これ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;alias&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;vue$&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;vue/dist/vue.esm.js&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今回はコンパイラが必要な形式↓でコードを書いています。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;new Vue({
el: &amp;#34;#app&amp;#34;,
components: { App },
template: &amp;#34;&amp;lt;app&amp;gt;&amp;lt;/app&amp;gt;&amp;#34;
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;すると、このような警告が表示されます。実行時のコンパイラが含まれないよという意味合いの警告ですね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今プロジェクトではwebpackで&lt;code&gt;vue-loader&lt;/code&gt;を使用して事前にコンパイルしていますので本来はコンパイラは不要です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://jp.vuejs.org/v2/guide/installation.html#%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0-%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E3%81%A8%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0%E9%99%90%E5%AE%9A%E3%81%AE%E9%81%95%E3%81%84"&gt;ランタイム-コンパイラとランタイム限定の違い — Vue.js&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;vue-loader や vueify を利用する場合、 *.vue ファイルに中のテンプレートはビルド時に JavaScript に事前コンパイルされます。最終成果物の中にコンパイラは本当に必要なく、したがってランタイム限定ビルドを利用することが出来ます。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;そこで先ほどの設定を追加することでこの警告を回避できるというわけです。&lt;/p&gt;</description></item><item><title>RubyでGmail風プロフィール画像を生成するinitial_avatarでユーザーを識別しやすくする</title><link>https://blog.piyo.tech/posts/2018-09-18-initial-avatar-gem/</link><pubDate>Tue, 18 Sep 2018 06:19:08 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-18-initial-avatar-gem/</guid><description>&lt;p&gt;ユーザーにアバター画像（プロフィール画像）を登録してもらうサービスの場合、画像未登録のユーザー用にデフォルトの画像を用意することがあると思います。&lt;/p&gt;
&lt;p&gt;グレー背景のシルエットとか、Googleのイニシャル（漢字なら最初の一文字）、Twitterのたまごとか、Slackの模様とか、いろいろなパターンがありますね。&lt;/p&gt;
&lt;p&gt;そんななか、Googleのイニシャルの画像と同じような画像を一行で使えるようにするgemを同僚が作ったということで、ここで代わりに紹介したいと思います。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/aki77/initial_avatar" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/290aad1fbb443aad841001ad5fb1f875a3a0188307cc1c74185a44e122fa25da/aki77/initial_avatar" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - aki77/initial_avatar: Create Gmail like text avatars for profile pictures using SVG.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Create Gmail like text avatars for profile pictures using SVG. - aki77/initial_avatar&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Rubyのgemなので&lt;code&gt;gem install initial_avatar&lt;/code&gt;またはGemfileへの&lt;code&gt;gem 'initial_avatar'&lt;/code&gt;の追記で導入できます。&lt;/p&gt;
&lt;p&gt;実際の用途としてはRailsなどのWebフレームワークで使用することが多いと思いますが、シンプルに紹介するためにRubyのコンソールのみで動かしてみました。&lt;/p&gt;
&lt;p&gt;基本となるのは、以下の&lt;code&gt;InitialAvatar.avatar_data_uri&lt;/code&gt;です。これによりSVGの情報がBase64エンコードされたData URIとして返ってきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;base64&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;initial_avatar&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;InitialAvatar&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;avatar_data_uri(&lt;span style="color:#e6db74"&gt;&amp;#39;あ&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;size&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;font_size&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;70&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICMyZWNjNzE7IHdpZHRoOiAxMDBweDsgaGVpZ2h0OiAxMDBweDsiPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB5PSI1MCUiIHg9IjUwJSIgZHk9IjAuMzVlbSIgcG9pbnRlci1ldmVudHM9ImF1dG8iIGZpbGw9IiNmZmZmZmYiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2FOZXVlLUxpZ2h0LEhlbHZldGljYSBOZXVlIExpZ2h0LEhlbHZldGljYSBOZXVlLEhlbHZldGljYSwgQXJpYWwsTHVjaWRhIEdyYW5kZSwgc2Fucy1zZXJpZiIgc3R5bGU9ImZvbnQtd2VpZ2h0OiA0MDA7IGZvbnQtc2l6ZTogNzBweDsiPuOBgjwvdGV4dD4KPC9zdmc+Cg==&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このData URIを&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;タグの&lt;code&gt;src&lt;/code&gt;に渡すとこんな風になります。&lt;/p&gt;
&lt;img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICMyZWNjNzE7IHdpZHRoOiAxMDBweDsgaGVpZ2h0OiAxMDBweDsiPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB5PSI1MCUiIHg9IjUwJSIgZHk9IjAuMzVlbSIgcG9pbnRlci1ldmVudHM9ImF1dG8iIGZpbGw9IiNmZmZmZmYiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2FOZXVlLUxpZ2h0LEhlbHZldGljYSBOZXVlIExpZ2h0LEhlbHZldGljYSBOZXVlLEhlbHZldGljYSwgQXJpYWwsTHVjaWRhIEdyYW5kZSwgc2Fucy1zZXJpZiIgc3R5bGU9ImZvbnQtd2VpZ2h0OiA0MDA7IGZvbnQtc2l6ZTogNzBweDsiPuOBgjwvdGV4dD4KPC9zdmc+Cg==" /&gt;
&lt;p&gt;ちゃんと出ていますね。&lt;/p&gt;
&lt;h1 id="色々試してみる"&gt;色々試してみる&lt;/h1&gt;
&lt;h2 id="オプションなしだとデフォルト値に"&gt;オプションなしだとデフォルト値に&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;InitialAvatar&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;avatar_data_uri(&lt;span style="color:#e6db74"&gt;&amp;#39;あ&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICMyZWNjNzE7IHdpZHRoOiAxMDBweDsgaGVpZ2h0OiAxMDBweDsiPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB5PSI1MCUiIHg9IjUwJSIgZHk9IjAuMzVlbSIgcG9pbnRlci1ldmVudHM9ImF1dG8iIGZpbGw9IiNmZmZmZmYiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2FOZXVlLUxpZ2h0LEhlbHZldGljYSBOZXVlIExpZ2h0LEhlbHZldGljYSBOZXVlLEhlbHZldGljYSwgQXJpYWwsTHVjaWRhIEdyYW5kZSwgc2Fucy1zZXJpZiIgc3R5bGU9ImZvbnQtd2VpZ2h0OiA0MDA7IGZvbnQtc2l6ZTogNTBweDsiPuOBgjwvdGV4dD4KPC9zdmc+Cg==" /&gt;
&lt;h2 id="2文字以上"&gt;2文字以上&lt;/h2&gt;
&lt;p&gt;ちなみに、3文字以上にするとさすがにはみ出ます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;InitialAvatar&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;avatar_data_uri(&lt;span style="color:#e6db74"&gt;&amp;#39;AB&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;size&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;font_size&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICM4ZTQ0YWQ7IHdpZHRoOiAxMDBweDsgaGVpZ2h0OiAxMDBweDsiPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB5PSI1MCUiIHg9IjUwJSIgZHk9IjAuMzVlbSIgcG9pbnRlci1ldmVudHM9ImF1dG8iIGZpbGw9IiNmZmZmZmYiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2FOZXVlLUxpZ2h0LEhlbHZldGljYSBOZXVlIExpZ2h0LEhlbHZldGljYSBOZXVlLEhlbHZldGljYSwgQXJpYWwsTHVjaWRhIEdyYW5kZSwgc2Fucy1zZXJpZiIgc3R5bGU9ImZvbnQtd2VpZ2h0OiA0MDA7IGZvbnQtc2l6ZTogNjBweDsiPkFCPC90ZXh0Pgo8L3N2Zz4K" /&gt;
&lt;h2 id="漢字--サイズを大きく"&gt;漢字 + サイズを大きく&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;InitialAvatar&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;avatar_data_uri(&lt;span style="color:#e6db74"&gt;&amp;#39;水&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;size&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;font_size&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;150&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNlNzRjM2M7IHdpZHRoOiAyMDBweDsgaGVpZ2h0OiAyMDBweDsiPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB5PSI1MCUiIHg9IjUwJSIgZHk9IjAuMzVlbSIgcG9pbnRlci1ldmVudHM9ImF1dG8iIGZpbGw9IiNmZmZmZmYiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2FOZXVlLUxpZ2h0LEhlbHZldGljYSBOZXVlIExpZ2h0LEhlbHZldGljYSBOZXVlLEhlbHZldGljYSwgQXJpYWwsTHVjaWRhIEdyYW5kZSwgc2Fucy1zZXJpZiIgc3R5bGU9ImZvbnQtd2VpZ2h0OiA0MDA7IGZvbnQtc2l6ZTogMTUwcHg7Ij7msLQ8L3RleHQ+Cjwvc3ZnPgo=" /&gt;
&lt;h1 id="設定"&gt;設定&lt;/h1&gt;
&lt;p&gt;色の候補とかサイズのデフォルト値などは予めしていしておくことが可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 何も指定しなければデフォルト値が使われる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;InitialAvatar&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;configure &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;config&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;colors &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;%w[
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; #1abc9c #16a085 #f1c40f #f39c12 #2ecc71 #27ae60 #e67e22 #d35400 #3498db
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; #2980b9 #e74c3c #c0392b #9b59b6 #8e44ad #bdc3c7 #34495e #2c3e50 #95a5a6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; #7f8c8d #ec87bf #d870ad #f69785 #9ba37e #b49255 #b49255 #a94136
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;text_color &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#ffffff&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;size &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;font_weight &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;400&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;font_family &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;HelveticaNeue-Light,Helvetica Neue Light,Helvetica Neue,Helvetica, Arial,Lucida Grande, sans-serif&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;seed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="デフォルト画像として使う"&gt;デフォルト画像として使う&lt;/h1&gt;
&lt;p&gt;例えばRailsでよく使われるCarrierWaveではアップロード済のファイルがない場合にデフォルト値として使うURLを指定する方法があります。&lt;/p&gt;
&lt;p&gt;そのデフォルト用のURLでこの&lt;code&gt;InitialAvatar.avatar_data_uri&lt;/code&gt;の結果を返せば、ユーザーごとの頭文字を使ったアバターを初期設定値にできます。&lt;/p&gt;
&lt;p&gt;固定の画像だと多くの人が同じアバター画像になってしまうなどして見分けがつきにくくなってしまいますが、色付き頭文字になるだけでかなり見やすくなってオススメです。&lt;/p&gt;</description></item><item><title>scssじゃなくてsassのほうの文法を調べたいときに使っている方法</title><link>https://blog.piyo.tech/posts/2018-09-17-sass-not-scss/</link><pubDate>Mon, 17 Sep 2018 06:08:32 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-17-sass-not-scss/</guid><description>&lt;p&gt;SassはCSSの拡張言語です。&lt;/p&gt;
&lt;p&gt;Sassには&lt;code&gt;scss&lt;/code&gt;形式と&lt;code&gt;sass&lt;/code&gt;形式があって（形式って言うのかどうかわからないけど呼んじゃう）、&lt;code&gt;scss&lt;/code&gt;形式で紹介されていることのほうが多いように思います。ですが、個人的には&lt;code&gt;sass&lt;/code&gt;形式のほうが記述量が少なくて好きです。&lt;/p&gt;
&lt;p&gt;Sassのガイドページにはscssとsassとでそれぞれサンプルコードが用意されているので対比することが可能です。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://sass-lang.com/guide" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://www.netlify.com/v3/img/components/netlify-color-bg.svg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Sass: Sass Basics&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Syntactically Awesome Style Sheets&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://sass-lang.com/icon.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;sass-lang.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ところが、実践的な情報は使っている人が多いscss形式で見つかることが多く、そんなときにsassでどうやって書いたらいいのかわからないという状況になりがちです。公式ドキュメントを読んでもベーシックな箇所以外はscssでのみサンプルが書かれています。&lt;/p&gt;
&lt;p&gt;そこでよくやるのは、scssとsassを変換できるツールまたはサイトを使って、scssで見つけた情報をsassに変換してしまうというやり方です。&lt;/p&gt;
&lt;p&gt;Webが手軽なので僕はこの辺を使っています↓↓&lt;/p&gt;
&lt;p&gt;&lt;a href="https://scss2sass.herokuapp.com/"&gt;https://scss2sass.herokuapp.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;たとえば公式ガイドのMixinのサンプルを↑のサイトに入力してconvertしてみると&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-scss" data-lang="scss"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@mixin&lt;/span&gt;&lt;span style="color:#a6e22e"&gt; transform&lt;/span&gt;($property) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;-webkit-transform&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; $property;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;-ms-transform&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; $property;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;transform&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; $property;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;.box&lt;/span&gt; { &lt;span style="color:#66d9ef"&gt;@include&lt;/span&gt;&lt;span style="color:#a6e22e"&gt; transform&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;rotate&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;deg&lt;/span&gt;)); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↓↓ きちんと変換され、公式ガイドのsassバージョンとほぼ同じに変換されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sass" data-lang="sass"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;=transform&lt;/span&gt;($property)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt; &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;-webkit-transform&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; $property
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt; &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;-ms-transform&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; $property
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt; &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;transform&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; $property
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;.box&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#f92672"&gt;transform&lt;/span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#f92672"&gt;rotate&lt;/span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#f92672"&gt;30deg&lt;/span&gt;&lt;span style="color:#f92672"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;@mixin&lt;/code&gt;が&lt;code&gt;=&lt;/code&gt;に変わるのとか大体忘れてしまうので、scssから導出できると大変便利です。&lt;/p&gt;</description></item><item><title>Railsにてファイルのインポート処理をActiveJob化する</title><link>https://blog.piyo.tech/posts/2018-09-16-import-file-on-background/</link><pubDate>Sun, 16 Sep 2018 06:19:42 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-16-import-file-on-background/</guid><description>&lt;p&gt;元々はFormオブジェクトでインポートするだけだったんですが、ファイルサイズが大きすぎてHerokuのタイムアウトを食らうケースが現れたのでバックグラウンドに回しました。&lt;/p&gt;
&lt;p&gt;その際、ファイルActiveJobに渡す方法を考えなければなりません。ファイルのオブジェクトの形では当然渡せないし、かと言ってローカルにファイルを置いてそのPathを渡す形にしたとしても、dynoが複数ある場合には参照できなくなってしまいます。&lt;/p&gt;
&lt;p&gt;正攻法はどこか外部のストレージに一時的に配置すること、となります。今回対象だったアプリケーションではファイルのアップロード先としてS3を利用していましたので、ファイルインポート機能としてもS3を利用するのが良さそうです。&lt;/p&gt;
&lt;h1 id="formオブジェクトモデルへ"&gt;Formオブジェクト→モデルへ&lt;/h1&gt;
&lt;p&gt;もともとFormオブジェクトとしてControllerとViewだけで利用していたクラスをやめて、ActiveRecordにしてDBに保存させることにしました。&lt;/p&gt;
&lt;h2 id="変更前のコード"&gt;変更前のコード&lt;/h2&gt;
&lt;p&gt;概要程度に書くとこんな感じ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Formオブジェクト&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Importer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;include&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveModel&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Model&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;attr_accessor&lt;/span&gt; &lt;span style="color:#e6db74"&gt;:file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; validates &lt;span style="color:#e6db74"&gt;:file&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;presence&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;import&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;transaction &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; open(file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path, &lt;span style="color:#e6db74"&gt;&amp;#39;r:cp932:utf-8&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;undef&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:replace&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;f&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# インポート処理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Controller&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;create&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; @importer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Importer&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#e6db74"&gt;file&lt;/span&gt;: params&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:importer&lt;/span&gt;&lt;span style="color:#f92672"&gt;][&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:file&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; @importer&lt;span style="color:#f92672"&gt;.&lt;/span&gt;valid?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; @importer&lt;span style="color:#f92672"&gt;.&lt;/span&gt;import
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; redirect_to root_path
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; render &lt;span style="color:#e6db74"&gt;:new&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="変更後のコード"&gt;変更後のコード&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Importer&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ApplicationRecord&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; validates &lt;span style="color:#e6db74"&gt;:file&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;presence&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# carrier_waveでS3へ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; mount_uploader &lt;span style="color:#e6db74"&gt;:file&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;ImportFileUploader&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;import&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; transaction &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 実はこれでは動かない（後述）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; open(file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path, &lt;span style="color:#e6db74"&gt;&amp;#39;r:cp932:utf-8&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;undef&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:replace&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;f&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# インポート処理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Controller&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;create&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; @importer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Importer&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#e6db74"&gt;file&lt;/span&gt;: params&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:importer&lt;/span&gt;&lt;span style="color:#f92672"&gt;][&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:file&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; @importer&lt;span style="color:#f92672"&gt;.&lt;/span&gt;save
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; @importer&lt;span style="color:#f92672"&gt;.&lt;/span&gt;delay&lt;span style="color:#f92672"&gt;.&lt;/span&gt;import &lt;span style="color:#75715e"&gt;# delayed_jobで処理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; redirect_to root_path, &lt;span style="color:#e6db74"&gt;notice&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;受け付けたよ&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; render &lt;span style="color:#e6db74"&gt;:new&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;バックグラウンド処理としてはdelayed_jobを使っている想定です。Jobを作って&lt;code&gt;perform_later&lt;/code&gt;でも良いですね。&lt;/p&gt;
&lt;h1 id="インポート処理でハマる"&gt;インポート処理でハマる&lt;/h1&gt;
&lt;p&gt;さっきさらっと流したのですが、&lt;code&gt;open(file.path, ...)&lt;/code&gt;のところを変えないと動きません。そもそも&lt;code&gt;file&lt;/code&gt;はS3上のものを指す想定なので、&lt;code&gt;file.path&lt;/code&gt;だけわかってもファイルを特定できません。そのためS3から読み出すようなコードに変える必要があります。&lt;/p&gt;
&lt;p&gt;例えば&lt;code&gt;open&lt;/code&gt;は受け取る引数がローカルのパスなのかURLなのかで内部の挙動が異なります。URLの場合はopenに渡している&lt;code&gt;undef: :replace&lt;/code&gt;のオプションを受け付けられないため、やはり実装を変えざるをえませんでした。&lt;/p&gt;
&lt;p&gt;一方で、CarrierWaveのよくある実装だと、ローカルではファイルとしてアップロードさせ、本番環境ではS3を使うみたなパターンが頻出かと思います。&lt;/p&gt;
&lt;p&gt;ローカルに置いてあるファイルとURL指定とでは&lt;code&gt;open&lt;/code&gt;への渡し方が異なるため、&lt;code&gt;development&lt;/code&gt;かそうでないかでファイルの読み方を変える必要がでてきました。&lt;/p&gt;
&lt;p&gt;（もちろん開発時からS3を使えるようにするのも手ですが、利便性のためできれば残しておきたかったのです）&lt;/p&gt;
&lt;p&gt;また厄介なことにインポート用のファイルの文字コードがcp932であるため、何も考えずにopenしてreadしようとするとエンコーディング周りのエラーとなります。&lt;/p&gt;
&lt;p&gt;頑張ってreadしようとして少々ハマり過ぎたため、URLにあるファイルを一時的にTempfileとして保存し、ローカルファイルとすることでローカルと本番との差異をできるだけ減らすという作戦にでました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;file_path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;env&lt;span style="color:#f92672"&gt;.&lt;/span&gt;production?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; @temp_file &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Tempfile&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; @temp_file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;binmode
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; open(file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;url) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;file&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; @temp_file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;write(file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;read)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; @temp_file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;rewind
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; @temp_file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;import&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; transaction &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 実はこれでは動かない（後述）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; open(file_path, &lt;span style="color:#e6db74"&gt;&amp;#39;r:cp932:utf-8&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;undef&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:replace&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;f&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# インポート処理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;import&lt;/code&gt;の部分はファイルパスのみの変更とし、パスを得るところに分岐を入れました。&lt;code&gt;open(url)&lt;/code&gt;は一定サイズを超えると&lt;code&gt;StringIO&lt;/code&gt;が戻ってくるのですが、この際Tempfileにしたほうがコードがシンプルになるかなと考えTempfileを利用しています。&lt;/p&gt;
&lt;p&gt;こちらが大変参考になりました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://qiita.com/tearoom6/items/8d3cb67a1bc4e454e989" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkYwJTJGNTQ3NTAlMkZwcm9maWxlLWltYWdlcyUyRjE3NjY0ODE4OTM_aXhsaWI9cmItNC4wLjAmYXI9MSUzQTEmZml0PWNyb3AmbWFzaz1lbGxpcHNlJmJnPUZGRkZGRiZmbT1wbmczMiZzPWNkMzhiNTIyYmVjZjA5ZjU4ZjI5NTY3MjVjYmM4NzRj%26blend-x%3D120%26blend-y%3D467%26blend-w%3D82%26blend-h%3D82%26blend-mode%3Dnormal%26s%3D9057c4ed3e59a8569b5c9418700d33c6?ixlib=rb-4.0.0&amp;amp;w=1200&amp;amp;fm=jpg&amp;amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9UnVieSUyMG9wZW4tdXJpJTIwJUUzJTgxJUFFJTIwb3BlbiUyMCVFMyU4MSVBRSVFNiU4OCVCQiVFMyU4MiU4QSVFNSU4MCVBNCZ0eHQtYWxpZ249bGVmdCUyQ3RvcCZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTU2JnR4dC1wYWQ9MCZzPTVhMGE0ODBjMmUyNmFkODUzNjUwYmQ2MDYyMDkwNjJl&amp;amp;mark-x=120&amp;amp;mark-y=112&amp;amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDB0ZWFyb29tNiZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTM2JnR4dC1wYWQ9MCZzPTcyNzg0N2NjZGZiMDg4NmEwYjI5NzViM2E5YzYyMjRm&amp;amp;blend-x=242&amp;amp;blend-y=480&amp;amp;blend-w=838&amp;amp;blend-h=46&amp;amp;blend-fit=crop&amp;amp;blend-crop=left%2Cbottom&amp;amp;blend-mode=normal&amp;amp;s=422fe82cd34923ef96ef2d7cc141e402" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Ruby open-uri の open の戻り値 - Qiita&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Ruby open-uri の open の戻り値 Ruby open-uri ライブラリの open メソッド open メソッドは引数に URL を取り、通常呼び出し or ブロック呼び出しのいずれかのスタイルを取ります。 require &amp;#39;open-uri&amp;#39; f...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;qiita.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="後処理"&gt;後処理&lt;/h1&gt;
&lt;p&gt;インポート処理の最後にTempfileの削除と自身の削除を実施します。インポート履歴を残したい場合は別ですが、一時的に使うのであれば削除しちゃっても問題ないかなと思っています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;import&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; transaction &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; open(&lt;span style="color:#f92672"&gt;...&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ensure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; @tempfile&lt;span style="color:#f92672"&gt;.&lt;/span&gt;close &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; @tempfile
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; destroy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;p&gt;重たいインポート処理をバックグラウンドにするときに一例として紹介しました。&lt;/p&gt;
&lt;p&gt;今回Tempfileを用いていますが、きれいに処理できるならTempfileを使わないで、readしたものをそのまま使ったほうがよさそう。&lt;/p&gt;</description></item><item><title>WindowsでElectronでsharpを使うのにそこそこハマった</title><link>https://blog.piyo.tech/posts/2018-09-15-use-sharp-on-windows/</link><pubDate>Sat, 15 Sep 2018 06:58:34 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-15-use-sharp-on-windows/</guid><description>&lt;p&gt;ElectronでSharpを使って画像を処理したという話を書きましたが、&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-09-11-electron-image-processor/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/ZIyiHy4F_k4gPiRqkEEM1v5nMOnm0laSDgLsmcpfxKM8fmC5WCaWjf0pBFgTi40TMMLlgmbG8l1L1LTWzNtktHRnfNhgWwi-ATSXJt1TaQ1IiIwSdD1irS66RaZacV3QCG2-uOToNyoVvg1MlU6v_L8KFRce74itUZEV01KI0i2MBaCmOQAuDNDe1Cc7UrcQlaeq3dZvGbe5KK3VT4ebsoxkfS1ehwi1UbCy1oPuCCsPIiqtE1nZIu7le1HTuvCo1XUfBnuv12PakYQhNovpJiP8ENAu0NUWmRifrGcybTP63uAqm7hAiYc4P0xvrwmBzZEgdy5l4HptbCK63sNMNlHncc6pHr5RcXbg3qa9a15c7QNuaUlBQDWcoHd82kWKEc7tHm4fMdjXUY0R3Yo5bGxIoIzX5mSLxhGFVfyZMGxZqyZ1uferMkKz4oy1AAw9n97kJCJm-K6iseBxOlYez3zz6y2PA2KjkDWtCxfNthuZN3vHFC4Uf0yAVjMbT3qRvXgxI3595pa20lui4kId7Uy2P0oJ6WUDH64H8JkWsyC8hDCXflfcHKFWJXzTdGAWgogs9VIC1Dbd6NucktRehE17k8aucs_Dq6ybNlKFXkjzqNcKX3xKPxP9SW4W3KwujN-mG01gVzeS_o6A-BsMauExhMRXibX6rovT34cOMMOfhcgtSma_fRCY=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Electronでの画像処理にsharpを使いました - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Electronを触り始めました。 フォルダ選択をして、フォルダ内の画像を一括処理するアプリケーションを作りました。一括処理の中には画像のリサイズやトリミングも含まれます。 画像加工部分にはsharpというライブラリを使いました。ネイティブコードを使うため速いとのことです（そのせいかビルド時にハマリましたが、それはまた後日）。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;これをWindowsに持っていこうとしてそこそこハマりました。記憶を辿りつつ書いてみようと思います。&lt;/p&gt;
&lt;h1 id="nativeモジュール"&gt;Nativeモジュール&lt;/h1&gt;
&lt;p&gt;アプリケーション側で&lt;code&gt;npm install&lt;/code&gt;すると、sharpが依存するNativeのモジュールがインストールされると書いてあったような気がするんですが、そうはいきませんでした。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ ./node_modules/sharp
$ npm install
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;として、手動でインストールする必要がありました。&lt;/p&gt;
&lt;h1 id="webpackconfigjs"&gt;webpack.config.js&lt;/h1&gt;
&lt;p&gt;Webpackでビルドするとファイルが見つからない、というようなエラーが出て動かせなかったのでWebpackにexternalsの設定を追加しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;externals&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;sharp&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;commonjs sharp&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;関連Issueはこれなんですが、ちょっとちょっと根拠がよくわかってないんだよなー。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/lovell/sharp/issues/794" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/776c39371adc824e35e35fdf7b0606f63fe78ac9a7aacaacfed380bfd2508954/lovell/sharp/issues/794" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Use with Webpack 2 · Issue #794 · lovell/sharp&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Hey, I raised this issue on StackOverflow but have had no responses, so I thought I would go straight to the horse&amp;#39;s mouth :) I am trying to create an app in Electron which uses React, Webpack 2, S...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Macでは気にする必要なかったのが謎です。進まなくなっちゃうのもやなので一旦は動いたから良しとしています。&lt;/p&gt;
&lt;h1 id="他"&gt;他&lt;/h1&gt;
&lt;p&gt;あと何かあったかな。思い出したら追記します。&lt;/p&gt;</description></item><item><title>WindowsのNode.jsの管理にNodistを使う</title><link>https://blog.piyo.tech/posts/2018-09-14-node-manager-nodist/</link><pubDate>Fri, 14 Sep 2018 06:45:50 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-14-node-manager-nodist/</guid><description>&lt;p&gt;調べたところWindowsではNodist一択のように見えたのでNodistを導入しました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/nodists/nodist" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/35ffb8e2f72b67047e455166842dcbce3f564f1230c9c27ca8f2fc206e81db80/nodists/nodist" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - nodists/nodist: Natural node.js and npm version manager for windows.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Natural node.js and npm version manager for windows. - nodists/nodist&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;[LOOKING FOR A MAINTAINER :) ]&lt;/code&gt;とあるので、今後のメンテナンスはちょっと怪しいかもですね。&lt;/p&gt;
&lt;p&gt;READMEを見てみるとインストーラー経由、もしくはChocolateyを使うと書いてありまして、Chocolateyって何？と疑問に思うに至りました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://chocolatey.org/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://img.chocolatey.org/social-share/facebook-share.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Chocolatey - The package manager for Windows&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Chocolatey is software management automation for Windows that wraps installers, executables, zips, and scripts into compiled packages. Chocolatey integrates w/SCCM, Puppet, Chef, etc. Chocolatey is trusted by businesses to manage software deployments.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://img.chocolatey.org/favicons/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;chocolatey.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;調べてみた感じWindowsのパッケージマネージャということで、homebrewみたいなもんだと思っておけばいいのかなと思いました。&lt;/p&gt;
&lt;h1 id="chocolaty導入"&gt;Chocolaty導入&lt;/h1&gt;
&lt;p&gt;まずはChocolateyを導入しました。手順は↓。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://chocolatey.org/install"&gt;Installation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;いくつか方法があるようですが、僕は管理者として実行したPowerShellに以下を貼り付けて実行しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;Set-ExecutionPolicy Bypass -Scope &lt;span style="color:#66d9ef"&gt;Process&lt;/span&gt; -Force; iex ((New-Object System.Net.WebClient).DownloadString(&lt;span style="color:#e6db74"&gt;&amp;#39;https://chocolatey.org/install.ps1&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;choco&lt;/code&gt;コマンドをインストールできました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ choco
Chocolatey v0.10.11
Please run &amp;#39;choco -?&amp;#39; or &amp;#39;choco &amp;lt;command&amp;gt; -?&amp;#39; for help menu.
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="nodist導入"&gt;Nodist導入&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ choco install nodist
Chocolatey v0.10.11
Chocolatey detected you are not running from an elevated command shell
(cmd/powershell).
You may experience errors - many functions/packages
require admin rights. Only advanced users should run choco w/out an
elevated shell. When you open the command shell, you should ensure
that you do so with &amp;#34;Run as Administrator&amp;#34; selected. If you are
attempting to use Chocolatey in a non-administrator setting, you
must select a different location other than the default install
location. See
https://chocolatey.org/install#non-administrative-install for details.
Do you want to continue?([Y]es/[N]o):
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(↑Hugoの処理のせいか想定外の&lt;code&gt;{1}&lt;/code&gt;がなぜか入ってしまいます…)&lt;/p&gt;
&lt;p&gt;これでYを押して進めても管理者権限がないのでインストールを完了できませんでした。なのでConEmuを起動するときに右クリックメニューから「管理者として実行」し、再度同じコマンドを実行したらインストールが完了しました。&lt;/p&gt;
&lt;h1 id="nodeのインストール"&gt;Nodeのインストール&lt;/h1&gt;
&lt;p&gt;先程管理者として実行していたConEmuを閉じ、ユーザー権限でConEmuを開いておきます。&lt;/p&gt;
&lt;p&gt;この状態でnodistを実行すると↓となります。あれ、すでに7系が入っていますね…。Nodistと一緒に入るのかもしれないです。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ nodist
(x64)
&amp;gt; 7.2.1 (global: v7.2.1)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ではここに8系のバージョンを追加してみます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ nodist + 8
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;+&lt;/code&gt;というのがサブコマンドらしく、バージョンも一緒に指定するとインストールされます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ nodist + 8
8.11.4
$ nodist
(x64)
&amp;gt; 7.2.1 (global: v7.2.1)
8.11.4
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;8.11.4&lt;/code&gt;が入りました。&lt;/p&gt;
&lt;p&gt;最後にglobalとして使うバージョンを切り替えます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ nodist global 8
8
Default global pacakge update dsuccessful.
$ nodist
(x64)
7.2.1
&amp;gt; 8.11.4 (global: 8)
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>ConEmuとGit bashでWindowsのターミナル環境を簡易に整える</title><link>https://blog.piyo.tech/posts/2018-09-13-setup-termianl-on-windows/</link><pubDate>Thu, 13 Sep 2018 06:19:31 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-13-setup-termianl-on-windows/</guid><description>&lt;p&gt;普段はMacユーザーの僕ですが、Windows上でターミナルを使って作業する必要が出て、Windowsのセットアップをせまられました。&lt;/p&gt;
&lt;p&gt;本当にメインで使うのであればしっかりセットアップしたいところですが、今回にように片手間で環境を用意するのにいい方法は無いものかと、片手間に調べてみたところ、ConEmuというのが良さげというのを見つけて導入してみました。&lt;/p&gt;
&lt;p&gt;そもそもターミナルで何をやりたいかと言えば、今回絶対にやりたかったのはNodeの実行です。Git for Windowsを入れると一緒に入るGit Bashあたりで十分かなと最初思っていたんですが、やはりcmdベースではコピペ周りを筆頭にいろいろと使いにくいです。そこでConEmuを組み合わせるというのを↓で知りました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://qiita.com/CyberMergina/items/69cd5890f05d502716c8" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFtYXpvbmF3cy5jb20lMkYwJTJGNDUwODAlMkZwcm9maWxlLWltYWdlcyUyRjE1MTA3NjIzNzk_aXhsaWI9cmItNC4wLjAmYXI9MSUzQTEmZml0PWNyb3AmbWFzaz1lbGxpcHNlJmJnPUZGRkZGRiZmbT1wbmczMiZzPTgwMzM2NzI5NzAxM2NkZWM5NWQ1YzIwMmNiZDI4YTYw%26blend-x%3D120%26blend-y%3D462%26blend-w%3D90%26blend-h%3D90%26blend-mode%3Dnormal%26mark64%3DaHR0cHM6Ly9xaWl0YS1vcmdhbml6YXRpb24taW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnMzLWFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkZxaWl0YS1vcmdhbml6YXRpb24taW1hZ2UlMkY2Nzk1NTUzMTU3MDczNmQ2MThmNTlkZDVlNjE1YjAxMjg1YjIyMjE3JTJGb3JpZ2luYWwuanBnJTNGMTQ4NTMxNTIyNz9peGxpYj1yYi00LjAuMCZ3PTQ0Jmg9NDQmZml0PWNyb3AmbWFzaz1jb3JuZXJzJmNvcm5lci1yYWRpdXM9OCZiZz1GRkZGRkYmYm9yZGVyPTIlMkNGRkZGRkYmZm09cG5nMzImcz04OGYzZjJmZTkyNzU3NGUyYjZjOTYzOWQ0MDlmYjM4OQ%26mark-x%3D186%26mark-y%3D515%26mark-w%3D40%26mark-h%3D40%26s%3D63b23161430cc3cb8b4911f097229fb3?ixlib=rb-4.0.0&amp;amp;w=1200&amp;amp;fm=jpg&amp;amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9JUUzJTgxJThBJUUzJTgxJTk5JUUzJTgxJTk5JUUzJTgyJTgxJUUzJTgxJUFFQ1VJJUU3JTkyJUIwJUU1JUEyJTgzJUVGJUJEJTlFR2l0QmFzaCVFMyU4MSVBOENvbkVtdSVFRiVCRCU5RSZ0eHQtYWxpZ249bGVmdCUyQ3RvcCZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTU2JnR4dC1wYWQ9MCZzPTBmMGQyOGEyYTY3YThmZjFjMjUzMTEzNjE4NjRiMTFk&amp;amp;mark-x=120&amp;amp;mark-y=112&amp;amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDBDeWJlck1lcmdpbmEmdHh0LWNvbG9yPSUyMzFFMjEyMSZ0eHQtZm9udD1IaXJhZ2lubyUyMFNhbnMlMjBXNiZ0eHQtc2l6ZT0zNiZ0eHQtcGFkPTAmcz00YTcwOWU0NDkyYTNlMzUwNGFiZTVmZjU4Mzk0YTIzZA&amp;amp;blend-x=242&amp;amp;blend-y=454&amp;amp;blend-w=838&amp;amp;blend-h=46&amp;amp;blend-fit=crop&amp;amp;blend-crop=left%2Cbottom&amp;amp;blend-mode=normal&amp;amp;txt64=SW9UTFQ&amp;amp;txt-x=242&amp;amp;txt-y=539&amp;amp;txt-width=838&amp;amp;txt-clip=end%2Cellipsis&amp;amp;txt-color=%231E2121&amp;amp;txt-font=Hiragino%20Sans%20W6&amp;amp;txt-size=28&amp;amp;s=5b777dde77950d27b12982e7ec9467a2" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;おすすめのCUI環境～GitBashとConEmu～ - Qiita&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;「おすすめのCUI環境」と言いつつ覚書ですが。 個人的にWindowsが使い慣れていて好きですが、 Linuxコマンドの方が大好きだったりします。 ということで、 ・Git for Windows ・ConEmu 以上の２つをいれて快適なCUI環境を作っております。 Gi...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;qiita.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;このQiitaそのまま見てもらえば良いかもという気もしつつ、導入までを整理しておきます。&lt;/p&gt;
&lt;p&gt;まずはこちらかConEmuをダウンロードします。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://conemu.github.io/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://conemu.github.io/img/ConEmu-Maximus5.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;ConEmu - Handy Windows Terminal&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;ConEmu-Maximus5 is a full-featured local terminal for Windows devs, admins and users. Get better console window with tabs, splits, Quake style, copy&amp;#43;paste, DosBox and PuTTY integration, and much more.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://conemu.github.io/conemu.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;conemu.github.io&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;僕はPortable版にしました。ConEmuを入れて起動すると最初に起動時のshellを選べ、とあります。最初はコマンドプロンプととかPowerShellぐらいしか選べません。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/1kqzHzfIIKJM8FbLS_V7vPV5RovUIlM6UV7TIPy14Roz51G98KHit8cJszEbgJjuuzaARGSPzENQqX8Id6VV1wUvmoHBb2kf0gTMZTbXOcT7A4usUkZzWX77ZefBB6CU_Eaff9HOe9BFrPW5fO5brkXvoqWKPj-4mudUkunvHxnfy7elzp4VNj1voY6FpH3dxUtEsm2_1VI9rMpVXxdKk7gysrM1VRJ-g0pxPJaRFpslN9N6yCwq0KSC9uDWt4ckdvJJkKaAvP7vGAnkeM1P6w7OrS3prm76w9h45RWpn4zwuvGa13T9l1CvBdl9rI4N9XqrrD3Di8tCSaPf9ZXI6B15nMYYQzTxZ4MLjjtYubDJLskO_43zSrW-_1r4pxGEPlqxCSwXHsFS-gYKTg0JT_VYza72PBHcaK1eXpxN7_QwCM5rt42AKoXCUjc4UfG55G3l2VYqH7LjQzyhPCNoNqMLCMOGKGd-srUkGnTponekzN_KrNHsHvcQIcCWMfSMJKOOsdc-8Cz_FU54AvKvnhfAK-hC1fnHgBxuFOdlJROzKYfmjJCpyySxt5y-G1ykJ1MBlzgNwt_UU7JZ1OEcdl9lKp8RvDRRdw0HT7SURGEkeXc-3T60v-wrPUfYaRaNLqIzugvtrxtNh-e8EtQwm9PKKh9TsLmovMzxHBm-IjhLFQn7rG2F3bnW=w1044-h848-no"&gt;&lt;img src="https://lh3.googleusercontent.com/1kqzHzfIIKJM8FbLS_V7vPV5RovUIlM6UV7TIPy14Roz51G98KHit8cJszEbgJjuuzaARGSPzENQqX8Id6VV1wUvmoHBb2kf0gTMZTbXOcT7A4usUkZzWX77ZefBB6CU_Eaff9HOe9BFrPW5fO5brkXvoqWKPj-4mudUkunvHxnfy7elzp4VNj1voY6FpH3dxUtEsm2_1VI9rMpVXxdKk7gysrM1VRJ-g0pxPJaRFpslN9N6yCwq0KSC9uDWt4ckdvJJkKaAvP7vGAnkeM1P6w7OrS3prm76w9h45RWpn4zwuvGa13T9l1CvBdl9rI4N9XqrrD3Di8tCSaPf9ZXI6B15nMYYQzTxZ4MLjjtYubDJLskO_43zSrW-_1r4pxGEPlqxCSwXHsFS-gYKTg0JT_VYza72PBHcaK1eXpxN7_QwCM5rt42AKoXCUjc4UfG55G3l2VYqH7LjQzyhPCNoNqMLCMOGKGd-srUkGnTponekzN_KrNHsHvcQIcCWMfSMJKOOsdc-8Cz_FU54AvKvnhfAK-hC1fnHgBxuFOdlJROzKYfmjJCpyySxt5y-G1ykJ1MBlzgNwt_UU7JZ1OEcdl9lKp8RvDRRdw0HT7SURGEkeXc-3T60v-wrPUfYaRaNLqIzugvtrxtNh-e8EtQwm9PKKh9TsLmovMzxHBm-IjhLFQn7rG2F3bnW=w1044-h848-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;続いてこちらからGitを手に入れてインストールしてみます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://gitforwindows.org/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Git for Windows&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;We bring the awesome Git VCS to Windows&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://gitforwindows.org/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;gitforwindows.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;途中いろいろなオプションを聞かれるので、お好みで設定しておきます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/2fxr-nQHfwczd3Tgg5jWfPgxTwN9fkqQ3QZ0iaNgCs1hd1V7nfdQ1xLhiff16NbWhZu1PBlcSw04wWvyOonkhtOZJOKTr3gMOiVqmvhgpmGjZJZxh3drF6JOT5q8YWKm6KzMhk8ULZjDLhlrIbpvmVKP80s7lxaAiLBE18FgHeDGO22CT2uA1tfiPiYGqK_7cwvRGTYGgD30XyJbAi-fNPOQ_cMI0y06MvffT5mxcgdYG9r5t3PXhFqwLlaTG7-nQYT8prX8NNYY8Qq1wTjl-QEmvjtyAePoBD7x66sHEqkBNxTKc4HcLxRLf8Om2uqsWcl-ENkgLu61Si4Qsua3Y67AYGZRl3uSh1ec-12JchFi7V9C2T86V1mA6vORftstM3NceIFxqansKT_UqHUiVL3c2hjNUhOAgoGs18qVjS7ljZXBvQGWDzvFpvLOTerDk8yneYJY0QYejTxs3VpwoBWOyqpH4vOyK17FNrTauXqQsfrvDdo8Lp6L5A44wqgeRC7lg0T1jhqUOlTaLOlCbd3wXEG6OHxyPRnQXo2ukTEenIMYh_Tfs_LLHLHNvtE6oc6Slvl-xPmaOKvnWMc7LmV78YYl4Povkom5Oy4HWI4pnD7KWX-96PiOZy2rgBzQk2GcRY--tCzgSlJlmS2086Pa6WRYrlEZpa-NsWYYmQvp1p_i42oJq1oE=w918-h678-no"&gt;&lt;img src="https://lh3.googleusercontent.com/2fxr-nQHfwczd3Tgg5jWfPgxTwN9fkqQ3QZ0iaNgCs1hd1V7nfdQ1xLhiff16NbWhZu1PBlcSw04wWvyOonkhtOZJOKTr3gMOiVqmvhgpmGjZJZxh3drF6JOT5q8YWKm6KzMhk8ULZjDLhlrIbpvmVKP80s7lxaAiLBE18FgHeDGO22CT2uA1tfiPiYGqK_7cwvRGTYGgD30XyJbAi-fNPOQ_cMI0y06MvffT5mxcgdYG9r5t3PXhFqwLlaTG7-nQYT8prX8NNYY8Qq1wTjl-QEmvjtyAePoBD7x66sHEqkBNxTKc4HcLxRLf8Om2uqsWcl-ENkgLu61Si4Qsua3Y67AYGZRl3uSh1ec-12JchFi7V9C2T86V1mA6vORftstM3NceIFxqansKT_UqHUiVL3c2hjNUhOAgoGs18qVjS7ljZXBvQGWDzvFpvLOTerDk8yneYJY0QYejTxs3VpwoBWOyqpH4vOyK17FNrTauXqQsfrvDdo8Lp6L5A44wqgeRC7lg0T1jhqUOlTaLOlCbd3wXEG6OHxyPRnQXo2ukTEenIMYh_Tfs_LLHLHNvtE6oc6Slvl-xPmaOKvnWMc7LmV78YYl4Povkom5Oy4HWI4pnD7KWX-96PiOZy2rgBzQk2GcRY--tCzgSlJlmS2086Pa6WRYrlEZpa-NsWYYmQvp1p_i42oJq1oE=w918-h678-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;再度ConEmuを起動すると、shellの選択肢の中に&lt;code&gt;Git bash&lt;/code&gt;が現れますのでこちらを選択。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/7mQi_w5Kk2nVZ5XqXEgzogvNFnibh6s6F6OGvrhfV8REudn4EyELka3uxP040lNmV0xLUelftoHF7aRpaioaqcKDMMyn2EQUZHNF1o-mjij_kMR0kbKzDXZC3LwQ9EWgRPbcQFFe_4LbwNIr1YAeHmYaeUnUJU07S6WxR_OyJutcnAzmKV0W3mvWYGVUHyk0phUIlOVrYMokxVhqDQ2itX5aQkk8geEkeqRnQ621UwrH9BnrfIXbvPyFfRWxRW2jOThOtImYL8mp35pktM4JgtLl2olLDXKPGrNMtvN53RXhoGhM-YDw2_hg_DzC8kzBbw4X6dg07w9H-cxjzcchnuTzGq77ELaFjBpNHovVGoKq9bJad9nVCb-5P_1lBV-ob43c6zOfioEpqHMYM9FtSfwQUulAjHd5eo16nsb3pGMQq_sSesv7NekYJe5VABCkjzChBB_Obxmo8KdD3mRUXE7nrqPuH1pJwX5OgPVOh2ekadGXM-UY7aeOX01RCPUhSdMPtADwVZSUMNMk5jbkFe0-JG9lX6JkCXKFNkntxuV8S3N26aGdVbjLEPJNRR1G-3ykc0rzn6DKtlbKjqF6BS5-jT3-6DXLViiik-JSR9e49ZO_5b_zv0BkqIfFA3jODcCQ11EO72YqFKB7IzjIDoYXEOo6FvIcaZSXZTbWb3rBdG1Ycw84_rfC=w1046-h848-no"&gt;&lt;img src="https://lh3.googleusercontent.com/7mQi_w5Kk2nVZ5XqXEgzogvNFnibh6s6F6OGvrhfV8REudn4EyELka3uxP040lNmV0xLUelftoHF7aRpaioaqcKDMMyn2EQUZHNF1o-mjij_kMR0kbKzDXZC3LwQ9EWgRPbcQFFe_4LbwNIr1YAeHmYaeUnUJU07S6WxR_OyJutcnAzmKV0W3mvWYGVUHyk0phUIlOVrYMokxVhqDQ2itX5aQkk8geEkeqRnQ621UwrH9BnrfIXbvPyFfRWxRW2jOThOtImYL8mp35pktM4JgtLl2olLDXKPGrNMtvN53RXhoGhM-YDw2_hg_DzC8kzBbw4X6dg07w9H-cxjzcchnuTzGq77ELaFjBpNHovVGoKq9bJad9nVCb-5P_1lBV-ob43c6zOfioEpqHMYM9FtSfwQUulAjHd5eo16nsb3pGMQq_sSesv7NekYJe5VABCkjzChBB_Obxmo8KdD3mRUXE7nrqPuH1pJwX5OgPVOh2ekadGXM-UY7aeOX01RCPUhSdMPtADwVZSUMNMk5jbkFe0-JG9lX6JkCXKFNkntxuV8S3N26aGdVbjLEPJNRR1G-3ykc0rzn6DKtlbKjqF6BS5-jT3-6DXLViiik-JSR9e49ZO_5b_zv0BkqIfFA3jODcCQ11EO72YqFKB7IzjIDoYXEOo6FvIcaZSXZTbWb3rBdG1Ycw84_rfC=w1046-h848-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Git bashが起動して使えるようになりました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/uxKBJJE99iD5dz8fXftr1WBb2CyuOdOy5Om3FYqcALtmqmifWA0ceLfDsZ_aQPROvHVgBR5fz-tMSdm25nr_pTsXtuy5PPuwg-qBB0O_V5m-l6dsjgoxrIE8xPE_OKzt0Kf4FnoQUobJ2xql3jCDtVg__FTQOgWHkOeWLy_VlnlJx_sVCo90780sRhvvQceClhbVOmEHRcKjOScmHcTxRsKPcJCp8zK9RGbj1jmcVTKi9L_LgK55jIYVVHaWzG-Am2mdBj2h9faWY5D90KZPC7xTdvxgqLjiqhcxQq6mNdDH_MSt5uwmdKDj-86g-Q8ZnZJs1Ptc9b7ylftLLnWsevdGSb45DmQbGJ1vw3IVk-WY67xXi-KWPecKFHB_JpLF92pwN87VWcksXjut7x5XW5lrz_Z98JLJsbSiDns70ip1h_0SI_UMGC7nCQ8fLFNunR0SD4abgH1yY7Pzo7Bt2SPgxIimpag8VrCnO0ZAThi6zjejTAtKPE-4KhLM2gwSRUsfXlV2wjNbabVCj-3cmjpUm_q7AsFTG2aLNNuRpsMQPcfX2tHZoo_sJLMUpWiAgmfbYwly-0A480XaOZcELY2qNg6Fhoy--yDOJP2UCtwUx7Df5vucPUc1X991TfbA_yzK9rDWIfY_K0FissVzhU4gFxPSYtsYnMSY2vEJYKV5Kowz8mxGe1Em"&gt;&lt;img src="https://lh3.googleusercontent.com/uxKBJJE99iD5dz8fXftr1WBb2CyuOdOy5Om3FYqcALtmqmifWA0ceLfDsZ_aQPROvHVgBR5fz-tMSdm25nr_pTsXtuy5PPuwg-qBB0O_V5m-l6dsjgoxrIE8xPE_OKzt0Kf4FnoQUobJ2xql3jCDtVg__FTQOgWHkOeWLy_VlnlJx_sVCo90780sRhvvQceClhbVOmEHRcKjOScmHcTxRsKPcJCp8zK9RGbj1jmcVTKi9L_LgK55jIYVVHaWzG-Am2mdBj2h9faWY5D90KZPC7xTdvxgqLjiqhcxQq6mNdDH_MSt5uwmdKDj-86g-Q8ZnZJs1Ptc9b7ylftLLnWsevdGSb45DmQbGJ1vw3IVk-WY67xXi-KWPecKFHB_JpLF92pwN87VWcksXjut7x5XW5lrz_Z98JLJsbSiDns70ip1h_0SI_UMGC7nCQ8fLFNunR0SD4abgH1yY7Pzo7Bt2SPgxIimpag8VrCnO0ZAThi6zjejTAtKPE-4KhLM2gwSRUsfXlV2wjNbabVCj-3cmjpUm_q7AsFTG2aLNNuRpsMQPcfX2tHZoo_sJLMUpWiAgmfbYwly-0A480XaOZcELY2qNg6Fhoy--yDOJP2UCtwUx7Df5vucPUc1X991TfbA_yzK9rDWIfY_K0FissVzhU4gFxPSYtsYnMSY2vEJYKV5Kowz8mxGe1Em" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これではまだNodeは使えませんが、それはまた今度セットアップしていきたいと思います。&lt;/p&gt;</description></item><item><title>Windowsでキーボードレイアウトを変更する</title><link>https://blog.piyo.tech/posts/2018-09-12-change-keyboard-layout-windows/</link><pubDate>Wed, 12 Sep 2018 06:43:20 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-12-change-keyboard-layout-windows/</guid><description>&lt;p&gt;僕はMacではUSキーボードを使っています。&lt;/p&gt;
&lt;p&gt;MacのParallelsに入れていたゲストWindowsで、キーボードがあるときから日本語レイアウトとして認識されるようになってしまい困っていました。&lt;/p&gt;
&lt;p&gt;本気で調べたら対応方法がわかったので残しておきます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/3Lsk50GRuSuPoqtubl3WzxrjfAmnuGVjAbWyhtgZeHdu22_i5nrpTdXVUT2Y3t82LG4eI8a_9fMGz1jQorlI3tIOxFQ54ZqeJBPYCYPzlf5IGuqaZiWLxdfw8SBxsrdhRD3dT04gO-q9d2T-4PM6mJT8jRWEpEtufBfIRKHWWPZo3TLjwb2BvmWOa6JeH7izvBAbDO36GhnRwRCJpdTt6EF5Xowh_s5p3dlHpnu1OHvhULfFpuKl0dSlfmrVkJDMWiQyV-VhJpD2FOsP9tRRkmpvm2LxeW8YqbDrwMmlrcbkFqH5C3PkvvJVagwiTrTansF17nSx0zGTj1n3M0B7iYwjTVDVlvpF1ziDhDJqucY1if_qgyHEZM3ZmxCrRfd7UjwFVupBHO0b23IUqXwPlCvFYXxhorNl8EgU9LG8vo1qokLJPkmvpscu5rAs3LbqWXk-JREd0aeWNGZTIaQMz_IwWAk4cUGYDHyYDJ6uhYJ7yJXwj-0L3EnEv1jMtJCyXEithGpGYkiR20-ehPEXbVjAGg0L5MKd-_PqUft-26KE396HYwPWNf___G1kR1ODmX3LMCG9f6uIRCvjP1_UPmURf1GjdEoQXI4g87U7PfqUNalyuA1qM9jussI6aJ7rhSWvNosQOc6O87QmU2nyXQhX4opyf6BrmaYOvn5XbHhPhzpJ2ycJJlV-=w612-h592-no"&gt;&lt;img src="https://lh3.googleusercontent.com/3Lsk50GRuSuPoqtubl3WzxrjfAmnuGVjAbWyhtgZeHdu22_i5nrpTdXVUT2Y3t82LG4eI8a_9fMGz1jQorlI3tIOxFQ54ZqeJBPYCYPzlf5IGuqaZiWLxdfw8SBxsrdhRD3dT04gO-q9d2T-4PM6mJT8jRWEpEtufBfIRKHWWPZo3TLjwb2BvmWOa6JeH7izvBAbDO36GhnRwRCJpdTt6EF5Xowh_s5p3dlHpnu1OHvhULfFpuKl0dSlfmrVkJDMWiQyV-VhJpD2FOsP9tRRkmpvm2LxeW8YqbDrwMmlrcbkFqH5C3PkvvJVagwiTrTansF17nSx0zGTj1n3M0B7iYwjTVDVlvpF1ziDhDJqucY1if_qgyHEZM3ZmxCrRfd7UjwFVupBHO0b23IUqXwPlCvFYXxhorNl8EgU9LG8vo1qokLJPkmvpscu5rAs3LbqWXk-JREd0aeWNGZTIaQMz_IwWAk4cUGYDHyYDJ6uhYJ7yJXwj-0L3EnEv1jMtJCyXEithGpGYkiR20-ehPEXbVjAGg0L5MKd-_PqUft-26KE396HYwPWNf___G1kR1ODmX3LMCG9f6uIRCvjP1_UPmURf1GjdEoQXI4g87U7PfqUNalyuA1qM9jussI6aJ7rhSWvNosQOc6O87QmU2nyXQhX4opyf6BrmaYOvn5XbHhPhzpJ2ycJJlV-=w612-h592-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/z7P-sNTWKA0O2y0Wd8f2pHZ6NoINTOjkVUzyX0Op9AOjwpodgDNzhnigMB22c4D7Qk1uFdHeiNX5WSIJTMAQq6RbtwK87V0L-4aoeFF-_Np9grSUji-DKQeCqmqNOaMHOwBRbHY6Q75qKEc95_WkRFFlmZUA0lhbNkkeiJq4cIv9Q4DbLcdMHGf0kPSflBHUhtNGhHVbcRWV8oMihewZQfxTKqtF1oQ5ZWRuKOvXIjEc7JxCcznoyROM67jl2JIGMm-C4PBTdZ8BNmHeLq7Teaup4oFYeNry00O0YP1OCb1w_xZbijfqnQpy0-m_OXFMEs21ZYWETVJpTzaCFFNOUnEB4-MzbNcLKsiKtvpETpa319zVEwow6bldASSsVRZbPO1qkKyfAVogWpmKMIGDE1u8tUEJwwqDjB76gHbFTtLiWY3FYKL-OIM2l4IungUNgSvckqReSrmxl8VfXNj38vRNB0JGrx70IuSgNdbHc8r0bs5ylyuphpfEWu8vkFpy7OIMCCKdSmcAstPrGb7zt_32K32TTpas8T9oLd_A1NXgPS1xwjR6erc-YJqqo_nEI_WwtpEEH7xNUs7KScTz6EOhA4D4LSSStJ7lHMdJedvlHnPdL2fYv2qadYyLeF00kTPTgVKV3MFrFOOTdKOus3PKGhY9_6gNH1ftCb0eqa3pGjwyNTbmpWaW=w496-h333-no"&gt;&lt;img src="https://lh3.googleusercontent.com/z7P-sNTWKA0O2y0Wd8f2pHZ6NoINTOjkVUzyX0Op9AOjwpodgDNzhnigMB22c4D7Qk1uFdHeiNX5WSIJTMAQq6RbtwK87V0L-4aoeFF-_Np9grSUji-DKQeCqmqNOaMHOwBRbHY6Q75qKEc95_WkRFFlmZUA0lhbNkkeiJq4cIv9Q4DbLcdMHGf0kPSflBHUhtNGhHVbcRWV8oMihewZQfxTKqtF1oQ5ZWRuKOvXIjEc7JxCcznoyROM67jl2JIGMm-C4PBTdZ8BNmHeLq7Teaup4oFYeNry00O0YP1OCb1w_xZbijfqnQpy0-m_OXFMEs21ZYWETVJpTzaCFFNOUnEB4-MzbNcLKsiKtvpETpa319zVEwow6bldASSsVRZbPO1qkKyfAVogWpmKMIGDE1u8tUEJwwqDjB76gHbFTtLiWY3FYKL-OIM2l4IungUNgSvckqReSrmxl8VfXNj38vRNB0JGrx70IuSgNdbHc8r0bs5ylyuphpfEWu8vkFpy7OIMCCKdSmcAstPrGb7zt_32K32TTpas8T9oLd_A1NXgPS1xwjR6erc-YJqqo_nEI_WwtpEEH7xNUs7KScTz6EOhA4D4LSSStJ7lHMdJedvlHnPdL2fYv2qadYyLeF00kTPTgVKV3MFrFOOTdKOus3PKGhY9_6gNH1ftCb0eqa3pGjwyNTbmpWaW=w496-h333-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/thxwxCwL1zyaaRRaPw7UBXxcksiBC9phVzGRFbC4FcI-ugg6Pl-gFSd3f38p2mNGfHBeMsl1FFXyUYNbmiiJXwS046o4qVbVeD_OaSxgr__kH_puMsplEjO258tjXTGMdL52C38QZtrb0eGY8V3L8lVAbPtUr7TtkdWAUW3qQEH4jf1pCPqTuitADJN3xmMsSpkFUfemY4_2LV_Z3fQVjJwDQaDDId5O2lKxfHgBtEbzRC7CTAFZ80Dbu8zgJMdW-Rrykk8rPRuywrDUO2eb6zgdndmrKaKmhV5dk44cWXqnzGAUSWewowHZNg9slMln1A11t_FMPhCjjQTFki9lnSxcilMix6XuGqBvjk_yvUedvQi21kJjNKZsYMpbStTkNdDUxga9jFNZMx0IbP4v0JxkMuReOS6E3YzN9J51QXC8n8tL6QaojfIWzCQV8RrAlaRVam8--p2lRYT7TbEPnDGZlMGDrHDVYj6Iq5WXw4aFbPNmIBer0u3zYZ0sCO7d2UHuDhd3Sa5cH1WP9-1OqW1hZTqK9SqG4bfR5LcFJ9VDVEVVm6I_9oD-KhN6f_tQ07Q0uOzB-yAGNyF3i8wPG8xC8k5mrWEO9fO0uTCHZzcYS0PebuaWycAwr_iHJuvaikQ0kk9nQ0o4xB0v3E3r1OgMIcNXgs7YXV10tD1G5svxLVgt6WCCzi8f=w576-h596-no"&gt;&lt;img src="https://lh3.googleusercontent.com/thxwxCwL1zyaaRRaPw7UBXxcksiBC9phVzGRFbC4FcI-ugg6Pl-gFSd3f38p2mNGfHBeMsl1FFXyUYNbmiiJXwS046o4qVbVeD_OaSxgr__kH_puMsplEjO258tjXTGMdL52C38QZtrb0eGY8V3L8lVAbPtUr7TtkdWAUW3qQEH4jf1pCPqTuitADJN3xmMsSpkFUfemY4_2LV_Z3fQVjJwDQaDDId5O2lKxfHgBtEbzRC7CTAFZ80Dbu8zgJMdW-Rrykk8rPRuywrDUO2eb6zgdndmrKaKmhV5dk44cWXqnzGAUSWewowHZNg9slMln1A11t_FMPhCjjQTFki9lnSxcilMix6XuGqBvjk_yvUedvQi21kJjNKZsYMpbStTkNdDUxga9jFNZMx0IbP4v0JxkMuReOS6E3YzN9J51QXC8n8tL6QaojfIWzCQV8RrAlaRVam8--p2lRYT7TbEPnDGZlMGDrHDVYj6Iq5WXw4aFbPNmIBer0u3zYZ0sCO7d2UHuDhd3Sa5cH1WP9-1OqW1hZTqK9SqG4bfR5LcFJ9VDVEVVm6I_9oD-KhN6f_tQ07Q0uOzB-yAGNyF3i8wPG8xC8k5mrWEO9fO0uTCHZzcYS0PebuaWycAwr_iHJuvaikQ0kk9nQ0o4xB0v3E3r1OgMIcNXgs7YXV10tD1G5svxLVgt6WCCzi8f=w576-h596-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/9Xixz6SESp45fK31hxHzO6Z6lSSBTuDWwbNDsonO0JB5Sk4Y5XUFH0TqZwnhlRhTQbPppkJUQAiCs23UtXV21ev9RSNtqi3Houx_TVCQAJ7os1d4dR0HGfL_n1at9C8QOI6oIhAo87DgRuefBo0ekNA71bc_761ywDEf_qM5IqFI9wpJMxkPJlbtDRVsSfA59lvsQQulhzgzdAah1_NC1itpRFGqK8IuwqjAhOh0oGUY7BkfivV6SXpSkxJdRXoXUW936t1BBRyrnUMO04j1Ab2z5JDQgSyrv3K51E_JRvMhv9VE2jdCZXKFfpZEQuQSHwnEDjSOMfn22v94yMk8CcatQ3ZC2ygu3K-qBRUh5eJBfHpS3vqyypqzI9zF7_iD5v54_eEpPyzOSwMhk6R3AtGx9cJJY8iLyQxZo3MqPn5EdfZ6XcSjLsRLeq1D5I4rnJl39Mdc5WeSqqXja7ETGRfcYPY14khe0VY2UXUoEckMS2cqoNdvLAmOmasnq7DniHSm5lmjJT_m7f6nzC1FCt1FzpEFaSbEmlwSi5_HgOezAWlkbLPL9_HKfb7AmgWbhBLFoY6KdBphSEZ1yBNMgIynODzzRrd4mLOhXU94bByCuiM4f6JRsXQdb_oX-Ij3UopHMcBf3o3Qmz-cBTpJKBedgwTvNBPU6AfGHAv9Y-dtV8fTyFe-2z8P=w990-h590-no"&gt;&lt;img src="https://lh3.googleusercontent.com/9Xixz6SESp45fK31hxHzO6Z6lSSBTuDWwbNDsonO0JB5Sk4Y5XUFH0TqZwnhlRhTQbPppkJUQAiCs23UtXV21ev9RSNtqi3Houx_TVCQAJ7os1d4dR0HGfL_n1at9C8QOI6oIhAo87DgRuefBo0ekNA71bc_761ywDEf_qM5IqFI9wpJMxkPJlbtDRVsSfA59lvsQQulhzgzdAah1_NC1itpRFGqK8IuwqjAhOh0oGUY7BkfivV6SXpSkxJdRXoXUW936t1BBRyrnUMO04j1Ab2z5JDQgSyrv3K51E_JRvMhv9VE2jdCZXKFfpZEQuQSHwnEDjSOMfn22v94yMk8CcatQ3ZC2ygu3K-qBRUh5eJBfHpS3vqyypqzI9zF7_iD5v54_eEpPyzOSwMhk6R3AtGx9cJJY8iLyQxZo3MqPn5EdfZ6XcSjLsRLeq1D5I4rnJl39Mdc5WeSqqXja7ETGRfcYPY14khe0VY2UXUoEckMS2cqoNdvLAmOmasnq7DniHSm5lmjJT_m7f6nzC1FCt1FzpEFaSbEmlwSi5_HgOezAWlkbLPL9_HKfb7AmgWbhBLFoY6KdBphSEZ1yBNMgIynODzzRrd4mLOhXU94bByCuiM4f6JRsXQdb_oX-Ij3UopHMcBf3o3Qmz-cBTpJKBedgwTvNBPU6AfGHAv9Y-dtV8fTyFe-2z8P=w990-h590-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/1BacTdskS1d9aB06C-ag5uJ3PK3sw0J48gVKdtEQs6G5jOUd6gj1tY7NPeOg8i_pIcihGh4Jeo7dcizKjO7m3gqO9svwYEflpd-LFYkU3squKChMY0Y4qPWz3MhBxcguSSdGKCCKuzCeb-zXejlR72Hg_f2XN3K7GtdESJnGX0bOHqSo0y5gQvx3JgyPsG2zi3hx5qWqc0i8NXh0L6EkYh05Iv-3T3bJJhbbawJchUsF9_azocX3pMg0zxbpVxnNlM-i9WiTH-ah3yweG73voMEOUzsxOrqkeelm8mMAZbZ5AHANdKsiNXpLEHK4meb7OJLM9rMsu7a1UuE69pZO_I-oBQai-Xv_XFSd5ZQO39tlE7_1cEEsduYGIJN48Ek8RFSWAFIL9OEJJ2zpANaMJ5R_OpjaD2p7P7aw9WLPXtpvCZmWkhVS_CrEoN_glB2BX3DSuSoEYi6-ISgw9HUZZts1aFgrMsOFUJ_tQDCbg0JmDcfiPAG4-hKg8TOM33EAjSSqLeQ1_Qvzy14CwD-S1JwUbRsXqEHy0CBzJs2cIvWzy3Un7cYnjehX0QDGH89YH-o15VKTgw_VhMwVfxH-cS9n3uZgC90Lnur5auw0LgktdP9zUucA0V3l0zCeIGNSVdxCj8URKyjVXNBXf573JEnFtLVYY_BQUl0ReRbRhAmE1xht01WZBnu_=w838-h356-no"&gt;&lt;img src="https://lh3.googleusercontent.com/1BacTdskS1d9aB06C-ag5uJ3PK3sw0J48gVKdtEQs6G5jOUd6gj1tY7NPeOg8i_pIcihGh4Jeo7dcizKjO7m3gqO9svwYEflpd-LFYkU3squKChMY0Y4qPWz3MhBxcguSSdGKCCKuzCeb-zXejlR72Hg_f2XN3K7GtdESJnGX0bOHqSo0y5gQvx3JgyPsG2zi3hx5qWqc0i8NXh0L6EkYh05Iv-3T3bJJhbbawJchUsF9_azocX3pMg0zxbpVxnNlM-i9WiTH-ah3yweG73voMEOUzsxOrqkeelm8mMAZbZ5AHANdKsiNXpLEHK4meb7OJLM9rMsu7a1UuE69pZO_I-oBQai-Xv_XFSd5ZQO39tlE7_1cEEsduYGIJN48Ek8RFSWAFIL9OEJJ2zpANaMJ5R_OpjaD2p7P7aw9WLPXtpvCZmWkhVS_CrEoN_glB2BX3DSuSoEYi6-ISgw9HUZZts1aFgrMsOFUJ_tQDCbg0JmDcfiPAG4-hKg8TOM33EAjSSqLeQ1_Qvzy14CwD-S1JwUbRsXqEHy0CBzJs2cIvWzy3Un7cYnjehX0QDGH89YH-o15VKTgw_VhMwVfxH-cS9n3uZgC90Lnur5auw0LgktdP9zUucA0V3l0zCeIGNSVdxCj8URKyjVXNBXf573JEnFtLVYY_BQUl0ReRbRhAmE1xht01WZBnu_=w838-h356-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/prsfr0ljBRR6J5VuwE-urePFVlGsMhPhGwUL-VWyuBlyai7PVQJlfRauh9NkD2eYdkrRNWrmM8whA2Iit4-wCIDovCovgY45I5ebeJgsleE8OLP6Y82Pf09r0eIGRj41Bh-p4_DgcEEfgwMzan3QrUW_yq5ZimiMguDJT8X1zEr3dtFWjm1RoOD3omQPpOqldeRtcC9c85aLqZKYaf_6-s-NDZzV14Kbb86DKtGDyny0QmqZ80kfVocmF-cgs97pMNZQr58EDGYIo3DZ1ILHrs1c8LKJYvYXhOAIJCClZ77UAtwfbzQSokHeC9UhbsgghnkovuAkje5pQx1Q7w9L54_lpfaOPIcoQU5h1wNQdfFaQJHq7On810KDkAbNPf3ZFDCXGXzIdD7bYOho3Z8fck5MzFKC9QEs1hyZUF5WCOKZ-HFHFJADxjtfPG8R0NOFSCxCk8jIkAZs9oBXX_MYoJ4uCaCsl1Zh7keC_Cm5giRUnEAdhsqrBcItfEzKNm0qv9pSjkKJBx70SfITxbxz3nzFVWAzNWI-5Gp0-iHROO27f0dEPgNN4ID6hZhxbtTtY4KqySiQAIpQBBbEzmnObY-oHVL4AFiY7rgwDOMIl8znWT8dp89OWEJ3xLpm9I447LS_XmY_hmLIhPZMEYa7G-Fzc63CWAoK0xSdPdLhsK5NsM9BR4SPiWQY=w1394-h436-no"&gt;&lt;img src="https://lh3.googleusercontent.com/prsfr0ljBRR6J5VuwE-urePFVlGsMhPhGwUL-VWyuBlyai7PVQJlfRauh9NkD2eYdkrRNWrmM8whA2Iit4-wCIDovCovgY45I5ebeJgsleE8OLP6Y82Pf09r0eIGRj41Bh-p4_DgcEEfgwMzan3QrUW_yq5ZimiMguDJT8X1zEr3dtFWjm1RoOD3omQPpOqldeRtcC9c85aLqZKYaf_6-s-NDZzV14Kbb86DKtGDyny0QmqZ80kfVocmF-cgs97pMNZQr58EDGYIo3DZ1ILHrs1c8LKJYvYXhOAIJCClZ77UAtwfbzQSokHeC9UhbsgghnkovuAkje5pQx1Q7w9L54_lpfaOPIcoQU5h1wNQdfFaQJHq7On810KDkAbNPf3ZFDCXGXzIdD7bYOho3Z8fck5MzFKC9QEs1hyZUF5WCOKZ-HFHFJADxjtfPG8R0NOFSCxCk8jIkAZs9oBXX_MYoJ4uCaCsl1Zh7keC_Cm5giRUnEAdhsqrBcItfEzKNm0qv9pSjkKJBx70SfITxbxz3nzFVWAzNWI-5Gp0-iHROO27f0dEPgNN4ID6hZhxbtTtY4KqySiQAIpQBBbEzmnObY-oHVL4AFiY7rgwDOMIl8znWT8dp89OWEJ3xLpm9I447LS_XmY_hmLIhPZMEYa7G-Fzc63CWAoK0xSdPdLhsK5NsM9BR4SPiWQY=w1394-h436-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Electronでの画像処理にsharpを使いました</title><link>https://blog.piyo.tech/posts/2018-09-11-electron-image-processor/</link><pubDate>Tue, 11 Sep 2018 06:59:55 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-11-electron-image-processor/</guid><description>&lt;p&gt;Electronを触り始めました。&lt;/p&gt;
&lt;p&gt;フォルダ選択をして、フォルダ内の画像を一括処理するアプリケーションを作りました。一括処理の中には画像のリサイズやトリミングも含まれます。&lt;/p&gt;
&lt;p&gt;画像加工部分にはsharpというライブラリを使いました。ネイティブコードを使うため速いとのことです（そのせいかビルド時にハマリましたが、それはまた後日）。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/lovell/sharp" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://repository-images.githubusercontent.com/12226786/cf816100-9a08-11ea-8fc1-7af9d4bcbf9e" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - lovell/sharp: High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, AVIF and TIFF images. Uses the libvips library.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, AVIF and TIFF images. Uses the libvips library. - lovell/sharp&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;2018/09/10 時点でStar数9000越えですごいですね。&lt;/p&gt;
&lt;p&gt;昨日の記事でファイルパスを取得できたところから進めてみようと思います。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-09-10-electron-folder-select/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/ZIyiHy4F_k4gPiRqkEEM1v5nMOnm0laSDgLsmcpfxKM8fmC5WCaWjf0pBFgTi40TMMLlgmbG8l1L1LTWzNtktHRnfNhgWwi-ATSXJt1TaQ1IiIwSdD1irS66RaZacV3QCG2-uOToNyoVvg1MlU6v_L8KFRce74itUZEV01KI0i2MBaCmOQAuDNDe1Cc7UrcQlaeq3dZvGbe5KK3VT4ebsoxkfS1ehwi1UbCy1oPuCCsPIiqtE1nZIu7le1HTuvCo1XUfBnuv12PakYQhNovpJiP8ENAu0NUWmRifrGcybTP63uAqm7hAiYc4P0xvrwmBzZEgdy5l4HptbCK63sNMNlHncc6pHr5RcXbg3qa9a15c7QNuaUlBQDWcoHd82kWKEc7tHm4fMdjXUY0R3Yo5bGxIoIzX5mSLxhGFVfyZMGxZqyZ1uferMkKz4oy1AAw9n97kJCJm-K6iseBxOlYez3zz6y2PA2KjkDWtCxfNthuZN3vHFC4Uf0yAVjMbT3qRvXgxI3595pa20lui4kId7Uy2P0oJ6WUDH64H8JkWsyC8hDCXflfcHKFWJXzTdGAWgogs9VIC1Dbd6NucktRehE17k8aucs_Dq6ybNlKFXkjzqNcKX3xKPxP9SW4W3KwujN-mG01gVzeS_o6A-BsMauExhMRXibX6rovT34cOMMOfhcgtSma_fRCY=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Electronでフォルダ内のファイル一覧を取得して処理する - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Electronを触り始めました。 ファイルを指定する Electronではブラウザよりも柔軟なファイル選択が可能です。フォルダ選択が可能なため、今回は対象のファイルを一括で指定するためにフォルダ選択を用いました。 Electronのレンダラープロセス側のJSで、ボタンを押したらフォルダ選択ダイアログを表示して処理するみたいな部分をまず書いてみます。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;超基本的な使い方としては、ファイルパスを指定して、必要な処理をはさんで、ファイルに書き出すという流れでしょうか。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sharp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;sharp&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;sharp&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;filePath&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;resize&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;400&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;xxxx&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// ←いろいろな加工ができる
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;yyyy&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;toFile&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;outputPath&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;info&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;自分で使いそうかな？ってをリストするだけでもこれぐらい↓あるし、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;resize&lt;/li&gt;
&lt;li&gt;crop&lt;/li&gt;
&lt;li&gt;rotate&lt;/li&gt;
&lt;li&gt;extract&lt;/li&gt;
&lt;li&gt;flip&lt;/li&gt;
&lt;li&gt;blur&lt;/li&gt;
&lt;li&gt;extend&lt;/li&gt;
&lt;li&gt;background&lt;/li&gt;
&lt;li&gt;greyscale&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;他にもいろいろあります。&lt;/p&gt;
&lt;p&gt;これらを組み合わせて使います。&lt;/p&gt;
&lt;p&gt;例えば、300x300の画像の下100を切り取って300x200にしたいときは次のように書けます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;sharp&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;filePath&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;resize&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;crop&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;north&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;toFile&lt;/span&gt;(...)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;300x300の画像に上下左右に100の余白（黒）を入れたいとき、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;sharp&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;filePath&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;background&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;g&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;alpha&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;extend&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;left&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;top&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;right&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;bottom&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;toFile&lt;/span&gt;(...)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;のように組み合わせて使えるわけです。&lt;/p&gt;
&lt;p&gt;例えばの用途ですが、画像を決まったサイズに収まるように加工するみたいな処理を一括でかけられそうで良さそうです。&lt;/p&gt;
&lt;p&gt;同じような処理はコマンドラインで簡単にできそうですが、Electronなのでビルドして配布すればコマンドなど知らなくてもできるってのがやはりいいですね。&lt;/p&gt;
&lt;p&gt;ちょっとした便利機能でも人によってはかなり便利にできそう。&lt;/p&gt;
&lt;h1 id="他に検討した画像ライブラリ"&gt;他に検討した画像ライブラリ&lt;/h1&gt;
&lt;p&gt;ここからいくつか試そうと思いましたが、&lt;code&gt;lwip&lt;/code&gt;は最近メンテされていないこと、人気がありそうな&lt;code&gt;jimp&lt;/code&gt;はPure JSでパフォーマンスに難があるかも、ということで一番Starの多いsharpにしました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/sindresorhus/awesome-nodejs" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://repository-images.githubusercontent.com/21737266/d682a480-a5ae-11ea-806d-519d39d18e32" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - sindresorhus/awesome-nodejs: :zap: Delightful Node.js packages and resources [BECAUSE OF TOO MUCH SPAM AND LOW-QUALITY SUBMISSIONS, SUBMISSIONS ARE PAUSED UNTIL SEPTEMBER]&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;:zap: Delightful Node.js packages and resources [BECAUSE OF TOO MUCH SPAM AND LOW-QUALITY SUBMISSIONS, SUBMISSIONS ARE PAUSED UNTIL SEPTEMBER] - sindresorhus/awesome-nodejs&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>Electronでフォルダ内のファイル一覧を取得して処理する</title><link>https://blog.piyo.tech/posts/2018-09-10-electron-folder-select/</link><pubDate>Mon, 10 Sep 2018 06:46:18 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-10-electron-folder-select/</guid><description>&lt;p&gt;Electronを触り始めました。&lt;/p&gt;
&lt;h1 id="ファイルを指定する"&gt;ファイルを指定する&lt;/h1&gt;
&lt;p&gt;Electronではブラウザよりも柔軟なファイル選択が可能です。フォルダ選択が可能なため、今回は対象のファイルを一括で指定するためにフォルダ選択を用いました。&lt;/p&gt;
&lt;p&gt;Electronのレンダラープロセス側のJSで、ボタンを押したらフォルダ選択ダイアログを表示して処理するみたいな部分をまず書いてみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// index.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;remote&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;electron&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Dialog&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;remote&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;dialog&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(document).&lt;span style="color:#a6e22e"&gt;ready&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;#folder-select&amp;#34;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;(() =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Dialog&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;showOpenDialog&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;properties&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;openDirectory&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;フォルダ選択&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;defaultPath&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#a6e22e"&gt;folderNames&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;folder&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;folderNames&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;folder&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;画面側をざくっとjQueryで作ったのでアレですが、このコードによって対応したボタンを押したらダイアログが開いてくれて、フォルダパスを取得可能です。&lt;/p&gt;
&lt;h1 id="フォルダ内のファイルへアクセス"&gt;フォルダ内のファイルへアクセス&lt;/h1&gt;
&lt;p&gt;フォルダのパスがわかったなら中にあるファイルの一覧を取得します。&lt;/p&gt;
&lt;p&gt;例えば画像ファイルに限定すると仮定して、MIME-Typeが&lt;code&gt;image/&lt;/code&gt;から始まるものだけを対象に処理をします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fs&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;fs;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;import path from &amp;#39;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;import mime from &amp;#39;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;mime&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;types&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fs&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;readdir&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;folder&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;dir&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;file&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;dir&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ext&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;extname&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mime&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;lookup&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ext&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;type&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/^image\//&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;test&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// do something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;パスでファイルにアクセスできるの、めっちゃ便利ですねー。ブラウザだとセキュリティ的な理由でこうはいかないし。&lt;/p&gt;</description></item><item><title>Electron完全に理解したわー（棒）となるまでに学んだこと</title><link>https://blog.piyo.tech/posts/2018-09-08-learning-electron/</link><pubDate>Sat, 08 Sep 2018 06:25:11 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-08-learning-electron/</guid><description>&lt;p&gt;ここ3年ぐらいElectronでなんかデスクトップアプリ作りたい！と思って、でもなんとなくJSの環境周りが変わっていくので敬遠してました。&lt;/p&gt;
&lt;p&gt;今回機会があって触り始めたら、難しく考えなくていいことがわかったんで、完全に理解したわーという気持ちになりました。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p lang="ja" dir="ltr"&gt;Electron完全に理解したわー（棒）&lt;/p&gt;&amp;mdash; Hiromasa Ohno（ぴー） (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/status/1037346839052206080?ref_src=twsrc%5Etfw"&gt;September 5, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;まあ、実際にはメインプロセスとレンダラープロセスでどう処理を分けるべきなのかとか、データの永続化ってどうするの？とかいろいろ知らないことは当然あります。が、それはまあおいおい学んで行こうと思います。&lt;/p&gt;
&lt;h1 id="webページと何も変わらないよという理解"&gt;Webページと何も変わらないよという理解&lt;/h1&gt;
&lt;p&gt;僕がそもそもJS環境を整えることにそんなに慣れていないので、一番最初はElectronだけを入れました。いずれwebpackerだとかbabelだとか、あとで使いたくなりそうなものがたくさんありますが、最初はそちらに手を出さないほうが良いと思います。というか、僕は一気にやろうとしてハマリました。&lt;/p&gt;
&lt;p&gt;ミニマムで始めるにはこちらの公式ドキュメントが適切です。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://electronjs.org/docs/tutorial/first-app" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;electronjs.org →&lt;/span&gt;&lt;span&gt;https://electronjs.org/docs/tutorial/first-app&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;最低2つのファイルがあればElectronのアプリを動かすことができます。&lt;/p&gt;
&lt;p&gt;一つはメインプロセスを動かすためのJSのコードで、Windowを作ったりメニュー操作を定義したりとネイティブ側のためのコードだと思っとくとよさげです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; {&lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;BrowserWindow&lt;/span&gt;} &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;electron&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createWindow&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Create the browser window.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;win&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;BrowserWindow&lt;/span&gt;({&lt;span style="color:#a6e22e"&gt;width&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;800&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;height&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// and load the index.html of the app.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;win&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;loadFile&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;index.html&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;on&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;ready&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;createWindow&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑を見るとウィンドウを作ってHTMLを指定しているだけですね。&lt;/p&gt;
&lt;p&gt;そしてもう一つはHTMLファイルで、これは作ったWindowの中にレンダリングするHTMLファイルです。ちなみに、最低限の話にするために↓のHTMLは公式ドキュメントから内容を削っています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;meta&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;charset&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;title&lt;/span&gt;&amp;gt;Hello World!&amp;lt;/&lt;span style="color:#f92672"&gt;title&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;h1&lt;/span&gt;&amp;gt;Hello World!&amp;lt;/&lt;span style="color:#f92672"&gt;h1&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでウィンドウもできたし、内容も定義できることがわかりました。&lt;/p&gt;
&lt;h1 id="uiをつくる"&gt;UIをつくる&lt;/h1&gt;
&lt;p&gt;こっから先はUIを作っていくわけです。まずはメインプロセスのことは忘れて普通のWebサイトだとして、JSのコードをロードしてみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;./app.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// app.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;val&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;val&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コードとしてはなんの意味もないですが、これでアプリをリロードするとデベロッパーコンソールにちゃんとログが出るはずです。&lt;/p&gt;
&lt;p&gt;あとは通常のWebサイトと全く同じ作り方をすることができますので、例えばWeb APIを利用したGUIクライアントアプリみたなものであれば、本当にWeb開発と全く変わらないですね。HTMLにcssやjsをロードして、ボタンを押したらほにょほにょみたいなことができるわけです。&lt;/p&gt;
&lt;p&gt;bootstrapを入れたり、Reactを入れたり、なんら変わりがありません。なんとなく敬遠してたのよくなかったなーと思ったものの、今いろいろ試せるのでめちゃくちゃ楽しいです。&lt;/p&gt;</description></item><item><title>Railsで全文検索のSolrを使うのがやっぱり簡単だった</title><link>https://blog.piyo.tech/posts/2018-09-06-rails-solr/</link><pubDate>Thu, 06 Sep 2018 06:53:54 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-06-rails-solr/</guid><description>&lt;p&gt;Herokuで動いているRailaアプリに全文検索を導入しようとしてElasticsearchを検討したけどローカルですら導入につまづいてしまい、昔ちょっと触ったことがあるSolrにしたら余裕で導入できました。という話です。慣れの問題かも？&lt;/p&gt;
&lt;p&gt;（いやーElasticsearchむずかしかったと思うんだわ…）&lt;/p&gt;
&lt;h1 id="ローカル"&gt;ローカル&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% brew install solr
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;でおk。&lt;/p&gt;
&lt;h1 id="herokuへの導入"&gt;Herokuへの導入&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;heroku addons:create websolr:staging-20 -a yourappname
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;でおk。グレード？は必要に応じて。最安では20ドルです。&lt;/p&gt;
&lt;h1 id="railsへの導入"&gt;Railsへの導入&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;sunspot&lt;/code&gt; gemが大変便利です。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/sunspot/sunspot" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/932bda1db7b63645582dcb72f6396ea41affb851e702e3cd1ba8cad355fd1dd4/sunspot/sunspot" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - sunspot/sunspot: Solr-powered search for Ruby objects&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Solr-powered search for Ruby objects. Contribute to sunspot/sunspot development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;gemの追加と&lt;code&gt;bundle install&lt;/code&gt;して、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;sunspot_rails&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;sunspot_solr&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;generateして、&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% rails generate sunspot_rails:install
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;あ、ついでにローカルはSolrもスタートさせておきましょう。終わったら落としたいので&lt;code&gt;rake sunspot:solr:run&lt;/code&gt;でフォアグラウンドで動かしておきます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;bundle exec rake sunspot:solr:run
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="モデルの設定"&gt;モデルの設定&lt;/h2&gt;
&lt;p&gt;検索対象にしたいモデルに設定用のコードを書きます。どのカラムをどんなデータタイプとして検索対象にするかを指定できます。子レコードの内容も親の検索内容とすることも簡単です。&lt;/p&gt;
&lt;p&gt;Rubyのコードで書けるのでとても柔軟です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ユーザーの全員検索とかないかもしれないけど&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;User&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; searchable &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; text &lt;span style="color:#e6db74"&gt;:name&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:email&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Diary&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; belongs_to &lt;span style="color:#e6db74"&gt;:user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; searchable &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; text &lt;span style="color:#e6db74"&gt;:content&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; text &lt;span style="color:#e6db74"&gt;:user_name&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;みたいな感じですね。&lt;/p&gt;
&lt;h2 id="検索方法"&gt;検索方法&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Diary&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;search { fulltext &lt;span style="color:#e6db74"&gt;&amp;#39;こんにちは&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;search&lt;/code&gt;にブロックを渡して検索します。重み付けなどありますが、シンプルにやるなら&lt;code&gt;fulltext&lt;/code&gt;に検索ワードを渡すだけでOKです。&lt;/p&gt;
&lt;h2 id="solrへの登録"&gt;Solrへの登録&lt;/h2&gt;
&lt;p&gt;インデックシングと呼ぶのかな？データの登録をしないと検索しても何も返ってきません。&lt;/p&gt;
&lt;p&gt;初回の登録はモデルごとに&lt;code&gt;reindex&lt;/code&gt;するか、sunspotのrakeタスクでまとめて登録しちゃいましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;User&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;reindex
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Diary&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;reindex
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;みたいに&lt;code&gt;rails console&lt;/code&gt;から実行したり、&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% bundle exec rake sunspot:reindex
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;として、全体を対象にすればOKです。&lt;/p&gt;
&lt;p&gt;また、日々データが登録・更新されるような場合にはそのタイミングでデータを再度インデックスする必要がありますので、&lt;code&gt;after_save&lt;/code&gt;などのコールバックと&lt;code&gt;delayed_job&lt;/code&gt;などのジョブを活用して都度インデックスしてあげましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;User&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; after_save &lt;span style="color:#e6db74"&gt;:update_index&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;update_index&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Sunspot&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;index(self)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;すでにデータが存在する本番環境へのデプロイの場合には、デプロイ後にインデックス登録のrakeタスクを走らせたほうがいいでしょう。じゃないと何も検索にかかりません。ただし、データ量が多い場合は時間がそれなりにかかりますので利用者の少ない時間帯がよいかと。&lt;/p&gt;
&lt;p&gt;データ量にもよりますが、再インデックスのrakeタスクは夜間バッチで勝手に動くようにしておいてもよいと思います。&lt;/p&gt;</description></item><item><title>Railsでorder忘れを防止するためのgemを作りました</title><link>https://blog.piyo.tech/posts/2018-09-03-must-be-ordered-gem/</link><pubDate>Mon, 03 Sep 2018 06:53:05 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-03-must-be-ordered-gem/</guid><description>&lt;p&gt;order、つけ忘れがちですよね。環境が変わると思ってた順番に出なかったりします。&lt;/p&gt;
&lt;p&gt;更に厄介なのは、つけ忘れてもなんとなく正しい順番で動いているときで、何かのタイミングで思った順ではなくなってしまうことがあります。というかありました。&lt;/p&gt;
&lt;p&gt;多分僕の場合はDBのマイナーアップグレードの影響のように見えました。詳細は追っていないですが、確かに一部でOrder指定が漏れていたので順番が変わってしまったのです。&lt;/p&gt;
&lt;p&gt;そういう事態に開発中に気がつけるようにするため、&lt;code&gt;must_be_ordered&lt;/code&gt;というgemを作りました。勤めてる会社の社内ハッカソンが8/31にあったので、ちょうどいいネタとばかりにこれを作りました。&lt;/p&gt;
&lt;p&gt;gemはこちらにございます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/pi-chan/must_be_ordered" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/eb542213cdc2f59a527ad4ffbeb2c47a13504c0f840074789d8a58d4573d9584/pi-chan/must_be_ordered" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - pi-chan/must_be_ordered&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Contribute to pi-chan/must_be_ordered development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;現時点での使い方を紹介します（インターフェースはそのうち変わっている気がする）。&lt;/p&gt;
&lt;p&gt;Rails、というかActiveRecordで使うのでGemfileにこのgemを追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Gemfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;must_be_ordered&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;んで、&lt;code&gt;bundle install&lt;/code&gt;します。&lt;/p&gt;
&lt;p&gt;そしたら今度は&lt;code&gt;config/initializers/&lt;/code&gt;以下に1個ファイルを作って↓のように書きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# config/initializers/must_be_ordered.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;MustBeOrdered&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;enabled &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;env&lt;span style="color:#f92672"&gt;.&lt;/span&gt;production?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ↓はお好みでON/OFF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;MustBeOrdered&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;raise &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;MustBeOrdered&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;must_be_ordered_logger &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;MustBeOrdered&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;rails_logger &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとは使いたいクラスの先頭でDSLっぽく&lt;code&gt;must_be_ordered&lt;/code&gt;を呼び出せばOK。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Item&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ApplicationRecord&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; must_be_ordered
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;全モデルを監視したいなら、&lt;code&gt;ApplicationRecord&lt;/code&gt;につけると良さそうです。&lt;/p&gt;
&lt;p&gt;これでorderのない状態でRelationでクエリが実行されるとエラーなりログなりが出る状態になりました。&lt;/p&gt;
&lt;p&gt;試しに既存プロジェクトで上記のような設定を有効にして&lt;code&gt;rails console&lt;/code&gt;で試してみました。&lt;/p&gt;
&lt;p&gt;対象クラスは&lt;code&gt;User&lt;/code&gt;です。まずはOrder無し。こちらはエラーとなります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry(main)&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;User&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(&lt;span style="color:#e6db74"&gt;&amp;#34;id &amp;gt; ?&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;MustBeOrdered&lt;/span&gt; order &lt;span style="color:#f92672"&gt;not&lt;/span&gt; applied &lt;span style="color:#e6db74"&gt;User&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;bin&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#e6db74"&gt;rails&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:in&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`require&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;bin/rails:4:in `&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;main&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;続いてOrder有り。エラーは飛びませんね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry(main)&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;User&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(&lt;span style="color:#e6db74"&gt;&amp;#34;id &amp;gt; ?&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;order(&lt;span style="color:#e6db74"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;User&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Load&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;ms) &lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;users&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;* &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;users&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; (id &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;ORDER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt; id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry(main)&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;エラーではアグレッシブすぎるというのであればログだけにして使うと良いです。&lt;/p&gt;
&lt;p&gt;仕事のプロジェクトにも入れるぞー。&lt;/p&gt;</description></item><item><title>話題のHatchfulでロゴを作ったので配置してみました</title><link>https://blog.piyo.tech/posts/2018-09-02-create-logo-by-hatchful/</link><pubDate>Sun, 02 Sep 2018 06:07:50 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-02-create-logo-by-hatchful/</guid><description>&lt;p&gt;最近話題になったShopifyのロゴ生成ツール「Hatchful」でロゴを作り、置いてみました。ヘッダーロゴ置いてみたかったんですよね。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hatchful&lt;/strong&gt;&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.shopify.com/tools/logo-maker" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://cdn.shopify.com/shopifycloud/brochure/assets/shared/social-image-default-large-57a90e6a8ae96f7277e9664ebfede1f143995ce7663119c832f9a7d4dd51f7e1.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;FREE Logo Maker - Create Your Own Logo in Minutes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Design high-resolution logos with Shopify’s free logo maker, the only logo generator your business needs. Customizable modern templates, no experience needed.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://cdn.shopify.com/shopifycloud/web/assets/v1/favicon-default-6cbad9de243dbae3.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;hatchful.shopify.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;紹介記事&lt;/strong&gt;&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://gigazine.net/news/20180827-hatchful/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://i.gzn.jp/img/2018/08/27/hatchful/00.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;無料でわずか数クリックでハイクオリティなロゴが作成できるツール「hatchful」&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;ロゴに使用するフォントやアイコンを自分好みにカスタムし、自分だけのオリジナルロゴが作り出せる無料ツールが「hatchful」です。わずか数クリックでオリジナルロゴが作成でき、デザイン初心者でも気軽にハイクオリティなものが作れるとのことなので、実際に使ってみました。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://gigazine.net/apple-touch-icon.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;gigazine.net&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;結構遊べて楽しいです。&lt;/p&gt;
&lt;p&gt;条件を保存しておけないのがちょっと残念。いろいろ試してやっぱりさっきのにしたいな、と思っても設定が多すぎてほぼ再現できないのが難点です。&lt;/p&gt;
&lt;p&gt;置いて見た感想ですが、ちょっと線が細くて印象薄いかも。しばらくしたらまた変えます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/8PQ4m2waqATL8FxqJz8hSISCJPrMK7NZ3HaIu1wH9L3rJL1gKBdTsgBLG-FMnyte-iCIrT0zCifKrFdjoc7xKD5tLdV8xW4aO-gwi9q4EqB12BPaq7hYVdctRvhHF-wFF-_77b4Q11ByQB5xU5iXSkrkAf6lhOYAxmKsTAeu1cG8QcQ3eAsh0d7PIpIB7EgUJZrQ1gXip0RVftJiIBMRv-RqgFuSpj9M-JbpXCfFAYxKX719jNJ2injr_Rsn2993ikYGx7oQdPJGYO4peV7AJgDDrgcMdGk1SgHldznTn-CoMELgNo4RLc9JnkCrTmSKhXTxFD1UECmGokvy7Cr_l56mZSD32ZOI7AbobMDlqlmFYvHkfTeeMu7tuERzDBhSIEqP8QGNMU1PYFtJaQvhGWSXptDQs0Wzu2e9FbdeXqYcLvya8F9QjbsXYNhPNm3muuxgi2pbEi0O7gYNFyuanfxs6t4JIWNBziKJG6fDnW5kqIPi7b4xE401WAHQiePgVnXWME11S6pUsHF0p0bGvuggBbo4VJ8Tu0B_llbwmt93DsceKfcqeBBX35fk2jAjrS2PiLDx32DKV6qzdC8LX18nXmGqauMJ-wdYs-IiUpSiSCvoQV7AZPT-XyVs4lRkZAn-LtC_s0mlAGHXsG-E6-5FJlPYU8mBrHqfu7AwSuKIXWrE-7Zjvszm"&gt;&lt;img src="https://lh3.googleusercontent.com/8PQ4m2waqATL8FxqJz8hSISCJPrMK7NZ3HaIu1wH9L3rJL1gKBdTsgBLG-FMnyte-iCIrT0zCifKrFdjoc7xKD5tLdV8xW4aO-gwi9q4EqB12BPaq7hYVdctRvhHF-wFF-_77b4Q11ByQB5xU5iXSkrkAf6lhOYAxmKsTAeu1cG8QcQ3eAsh0d7PIpIB7EgUJZrQ1gXip0RVftJiIBMRv-RqgFuSpj9M-JbpXCfFAYxKX719jNJ2injr_Rsn2993ikYGx7oQdPJGYO4peV7AJgDDrgcMdGk1SgHldznTn-CoMELgNo4RLc9JnkCrTmSKhXTxFD1UECmGokvy7Cr_l56mZSD32ZOI7AbobMDlqlmFYvHkfTeeMu7tuERzDBhSIEqP8QGNMU1PYFtJaQvhGWSXptDQs0Wzu2e9FbdeXqYcLvya8F9QjbsXYNhPNm3muuxgi2pbEi0O7gYNFyuanfxs6t4JIWNBziKJG6fDnW5kqIPi7b4xE401WAHQiePgVnXWME11S6pUsHF0p0bGvuggBbo4VJ8Tu0B_llbwmt93DsceKfcqeBBX35fk2jAjrS2PiLDx32DKV6qzdC8LX18nXmGqauMJ-wdYs-IiUpSiSCvoQV7AZPT-XyVs4lRkZAn-LtC_s0mlAGHXsG-E6-5FJlPYU8mBrHqfu7AwSuKIXWrE-7Zjvszm" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>RailsのTimeHelpers#travel_toを開発時のデータ生成に使ってみる</title><link>https://blog.piyo.tech/posts/2018-09-01-use-travel-to-to-generate-data/</link><pubDate>Sat, 01 Sep 2018 06:28:27 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-09-01-use-travel-to-to-generate-data/</guid><description>&lt;p&gt;RailsというかActiveSupportのTimeHelpersには&lt;code&gt;travel_to&lt;/code&gt;みたいな、現在時刻を偽装？するメソッドがあります。主にテストで使うもので、例えば1ヶ月後に何かが無効になるのをテストするときなんかに使われたりします。&lt;/p&gt;
&lt;p&gt;その&lt;code&gt;travel_to&lt;/code&gt;を開発用に使ってみました。&lt;/p&gt;
&lt;p&gt;週次で集計するような時系列データのグラフを表示するような機能を作るにあたり、開発環境だとまともにデータがないためにグラフをまともに作れなかったためです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rails runner&lt;/code&gt;で起動するスクリプトとして以下のように書きました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;exit &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;env&lt;span style="color:#f92672"&gt;.&lt;/span&gt;development?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;active_support/testing/time_helpers&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;include&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveSupport&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Testing&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;TimeHelpers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ApplicationRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;transaction &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; initial &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Time&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;zone&lt;span style="color:#f92672"&gt;.&lt;/span&gt;local(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;..&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;52&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;i&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; time &lt;span style="color:#f92672"&gt;=&lt;/span&gt; initial &lt;span style="color:#f92672"&gt;+&lt;/span&gt; i&lt;span style="color:#f92672"&gt;.&lt;/span&gt;week
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#34;generating data for &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;time&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ここで時刻を移動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; travel_to time &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;MyModel&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;generate_data!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;まず、本番などで動かないように環境を&lt;code&gt;development?&lt;/code&gt;にのみ限定します。続いて必要なファイルのrequireやincludeなどをします。&lt;/p&gt;
&lt;p&gt;あとは適当にループを回しながら、1週間後、2週間後、、と時刻をずらしていき、その時点で生成したデータものとしてデータがDBに登録されていきます。&lt;/p&gt;
&lt;p&gt;これにより1年後までのデータを作れました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;created_at&lt;/code&gt;などのカラムにも、ちゃんとtravel_toした時点の時刻が入っています。&lt;/p&gt;</description></item><item><title>Android PでReact Nativeアプリの逆方向のリストのスクロールが引っかかる感じになった</title><link>https://blog.piyo.tech/posts/2018-08-31-react-native-android-inverted-list/</link><pubDate>Fri, 31 Aug 2018 06:02:19 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-31-react-native-android-inverted-list/</guid><description>&lt;p&gt;自社でも使っているツールのReact Native製のアプリを使っている同僚から、Androidを上げたらスクロールがおかしいよという連絡があったので調査をしました。&lt;/p&gt;
&lt;p&gt;問題が起こるのは、逆方向のリストを表示している箇所です。逆方向のリストとは画面一番したが要素の先頭で、上にスクロールしていくと追加読み込みが起こるという、チャットのような画面のことです。&lt;/p&gt;
&lt;p&gt;元々これを実現するために&lt;code&gt;ListView&lt;/code&gt;をベースにして逆向きリストを実現できるこちらのライブラリを使っていました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/expo/react-native-invertible-scroll-view" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/b75966167cd22644b85bb6573c325fffb6b2fab81fe56f8f71f7ba896aa35adc/expo/react-native-invertible-scroll-view" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - expo/react-native-invertible-scroll-view: An invertible ScrollView for React Native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;An invertible ScrollView for React Native. Contribute to expo/react-native-invertible-scroll-view development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;最初の調査の段階ではもしかしてこれが古いせいなのかな？と疑いました。&lt;/p&gt;
&lt;p&gt;ところで、1年ちょい前ぐらいからReact Nativeには&lt;code&gt;FlatList&lt;/code&gt;という新しいコンポーネントが用意されており、&lt;code&gt;ListView&lt;/code&gt;よりも&lt;code&gt;FlatList&lt;/code&gt;を使うほうが良いです。&lt;code&gt;FlatList&lt;/code&gt;にはリストを逆向きにするための&lt;code&gt;inverted&lt;/code&gt;というプロパティも用意されているため逆向きリストも簡単に実現できます。&lt;/p&gt;
&lt;p&gt;ということを知っていたのでライブラリを使わずに&lt;code&gt;FlatList&lt;/code&gt;に変更すれば直るかも、なんて簡単に考えていました。&lt;/p&gt;
&lt;p&gt;結果、&lt;code&gt;FlatList&lt;/code&gt;への置き換えは簡単に済んだのですが、スクロールの挙動は全く直りませんでした。&lt;code&gt;inverted&lt;/code&gt;オプションを無くすと（＝上から下に要素が並ぶようにすると）、スクロールの問題がありませんでしたので、何かのバグかな？と思い、React Nativeのissueにあたることにしました。&lt;/p&gt;
&lt;p&gt;早速こんなんが見つかりまして、&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/facebook/react-native/issues/19434" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/c93c815c76837b01c99e44b4f35e15b8d8ac9ac50bdf0f85d5a3b4affa0d6767/facebook/react-native/issues/19434" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Inverted FlatList doesn&amp;#39;t work on Android P · Issue #19434 · facebook/react-native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;[ Yes ] I have reviewed the documentation [ Yes ] I have searched existing issues [ Yes ] I am using the latest React Native version When using FlatList with inverted={true} the scrolling doesn&amp;#39;t w...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;どうやら今回と同じ問題について話しているようだぞ、というのがわかりました。ネイティブ側の実装をいじって回避できるという話もあるようですが、定かではないしあまりやりたくない感じだなーというところまでわかりました。&lt;/p&gt;
&lt;p&gt;Android側の実装が変わったのに対してReact Native側が対応しきれていないという風に見えるので、ちょっと対応待ちかなと思います。&lt;/p&gt;</description></item><item><title>Xcodeのビルド成功・失敗時に効果音や読み上げを鳴らす</title><link>https://blog.piyo.tech/posts/2018-08-30-xcode-play-sound-on-complete/</link><pubDate>Thu, 30 Aug 2018 06:31:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-30-xcode-play-sound-on-complete/</guid><description>&lt;p&gt;こんなツイートを見かけたので設定してみました。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p lang="ja" dir="ltr"&gt;Xcode、ビルド完了時に音が鳴るようにしとくと ついつい Twitter に夢中になって何してたかわからなくなるのを減らせる&lt;/p&gt;&amp;mdash; Kosuke Ogawa (@koogawa) &lt;a href="https://twitter.com/koogawa/status/1032257206337466370?ref_src=twsrc%5Etfw"&gt;August 22, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;Xcodeの設定（Preferences）を開き、左から3番目のBehaviorsタブへ。上にBuildという分類があるので、その中からSucceedssやFailsを選びます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/V2hmwnrMRR0CnBsYAO80mElCJI0FF4-jx_5W4ilTjB3wMFT43YTh-j01gGwNY1xSmqFquEa_j5tIc6Wf8e000iOAeqcLCtRlAWYQ8IuyVXqIHE43-c8RsP7Xtp94Vwsi6WQ0b5Wg1F_z_XqgrAHAveOxgfdUa-23HYEhRlQAB70lsT5FIB2tCfEotdOUX916rGzZWNVwnBdS0mh9v1tZszWONlUlDlWv7o9u2MWT-hogue18xRw3mjXPHG1AWbAaS41NH7EAth0lV4RHaKnGRTKjtvOK50SeTlzu_M89CTKotYEvWX7ihbi3puBuZoGR_F_HDo1PYi6xqbVWvkNX280hF9ETWMgN5Eoq2KwgS5hQhMTymEk-R8GnIbFoYbCEO1xklhp3kIlyKPqh4EWMSsiE0wka6mEPjFvRJgs7aRqWCC0AaGPzlgFQQj5GekRn5fR8we46N6mRhlViBV44iDA_c1G_NHOYsVZi2C6d1bELBxvXGb3AMba11MyrZXMnp9DbXq80X42klVkD378jla03yEl0cZ1Uj82fNasPsbpWwGFtk1_jRzeUOKTKHUP8-I-ysLxiBvjpDWXkIBUYjUhDH7OzpyOMpQjuLF2cl6Z0gBIxw9oH--nCZjvFvObsxIFBJEJEzN3U7zVv61eH6-ZC5NdCn6np5qK-a0EEQ6ac2rbkimdPs1mw=w1440-h440-no"&gt;&lt;img src="https://lh3.googleusercontent.com/V2hmwnrMRR0CnBsYAO80mElCJI0FF4-jx_5W4ilTjB3wMFT43YTh-j01gGwNY1xSmqFquEa_j5tIc6Wf8e000iOAeqcLCtRlAWYQ8IuyVXqIHE43-c8RsP7Xtp94Vwsi6WQ0b5Wg1F_z_XqgrAHAveOxgfdUa-23HYEhRlQAB70lsT5FIB2tCfEotdOUX916rGzZWNVwnBdS0mh9v1tZszWONlUlDlWv7o9u2MWT-hogue18xRw3mjXPHG1AWbAaS41NH7EAth0lV4RHaKnGRTKjtvOK50SeTlzu_M89CTKotYEvWX7ihbi3puBuZoGR_F_HDo1PYi6xqbVWvkNX280hF9ETWMgN5Eoq2KwgS5hQhMTymEk-R8GnIbFoYbCEO1xklhp3kIlyKPqh4EWMSsiE0wka6mEPjFvRJgs7aRqWCC0AaGPzlgFQQj5GekRn5fR8we46N6mRhlViBV44iDA_c1G_NHOYsVZi2C6d1bELBxvXGb3AMba11MyrZXMnp9DbXq80X42klVkD378jla03yEl0cZ1Uj82fNasPsbpWwGFtk1_jRzeUOKTKHUP8-I-ysLxiBvjpDWXkIBUYjUhDH7OzpyOMpQjuLF2cl6Z0gBIxw9oH--nCZjvFvObsxIFBJEJEzN3U7zVv61eH6-ZC5NdCn6np5qK-a0EEQ6ac2rbkimdPs1mw=w1440-h440-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Play sound&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;これにチェックをいれると成功時や失敗時に効果音を鳴らせます。自前でサウンドファイルを選べるので景気のいい効果音なんかを設定しておくと気持ちがノリそう。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Speak announcement using&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;指定した人の声で音声読み上げてくれるようになります。最初から指定してされている&lt;code&gt;Kyoko&lt;/code&gt;さんだと、日本語の棒読みで「ビルドサクシーデッド」などと言ってくれます。&lt;/p&gt;
&lt;p&gt;効果音にせよ音声にせよ、気づけるようにしておくとよさそうですね。&lt;/p&gt;</description></item><item><title>Android Pのエミュレータを作るときにAPI 28としか出てなくて困惑</title><link>https://blog.piyo.tech/posts/2018-08-29-avdmanager-android-null/</link><pubDate>Wed, 29 Aug 2018 06:22:10 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-29-avdmanager-android-null/</guid><description>&lt;p&gt;普段Androidユーザーではないんですが、React Nativeでアプリを作っているため開発環境は用意しています。&lt;/p&gt;
&lt;p&gt;今回Android P（バージョン9）でうまく動かないという報告を受けて環境を作ろうとしたら、Android StudioというかSDK Managerというか、どこにもPieとかPとかそういう記述がなかったので不慣れな僕としては困惑しました。&lt;/p&gt;
&lt;p&gt;まず、SDK Managerを見たら、&lt;code&gt;Android 8.1&lt;/code&gt;の上に&lt;code&gt;Android API 28&lt;/code&gt;というのがありまして、ひとまずこれを入れました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/q9F7C5EEancN-noXpfRxsbdqc4CFEXZlFSenIPtWR78XtoZtLH9qm1uXHhzvheJVqkZohja5bi4a_LZOu5-HOMVpmZ1tsVh8lB2QZ_lJHLObpck_HPKfxWknjYdfOcstcv4lSw33VblS13U8o7u4bjEYUNkkEMVSScqmRxf9chPdOsmrFy7kJLyGJRR5qA3hP_Vtp4KS9K82lro2iELUYZ5A-LJAlMLBNDomvDfyFZO5QCxFlik8DbgvHlFtM-OrhEXlbBXxss_IT_0ePA1vc6y2WnC68cM_v7iNFbwwszQjSnMVnzHHikSL4sBPxlF1uBGGyhcp1XStumwd4nnzcx8I_HR71BnrceB88qh_517ZLeeFpFT_qQlBdS1CDCX_A8ai98o2v8Q_llzKWMvat369kU6UJO0RYFmdne_1QXHTYjP2yKTX6YNrQww1xFBc_b1OyMXBWwSPJxnbJOY-VkX0PJzVOw1T6bI_BKnCajj0jQqxQdWjNt3oD7EtarJ9mqufMIH_w0eFk3JiT5s11v-rJdK4gzrzTugMT27Si97Ar_i3CYPDLDL1axkI-n0U4VVSgvktaxMcM0jSkKVH0XjcHY4svqqOSyD_tEPwQfkp_FbQh-AfQYEAtE1qLezT_Y7wQ4k2D3JT-eR76hre6VKYucmhfl8KV2UGG5NNhgwttMTUsDe2pcun"&gt;&lt;img src="https://lh3.googleusercontent.com/q9F7C5EEancN-noXpfRxsbdqc4CFEXZlFSenIPtWR78XtoZtLH9qm1uXHhzvheJVqkZohja5bi4a_LZOu5-HOMVpmZ1tsVh8lB2QZ_lJHLObpck_HPKfxWknjYdfOcstcv4lSw33VblS13U8o7u4bjEYUNkkEMVSScqmRxf9chPdOsmrFy7kJLyGJRR5qA3hP_Vtp4KS9K82lro2iELUYZ5A-LJAlMLBNDomvDfyFZO5QCxFlik8DbgvHlFtM-OrhEXlbBXxss_IT_0ePA1vc6y2WnC68cM_v7iNFbwwszQjSnMVnzHHikSL4sBPxlF1uBGGyhcp1XStumwd4nnzcx8I_HR71BnrceB88qh_517ZLeeFpFT_qQlBdS1CDCX_A8ai98o2v8Q_llzKWMvat369kU6UJO0RYFmdne_1QXHTYjP2yKTX6YNrQww1xFBc_b1OyMXBWwSPJxnbJOY-VkX0PJzVOw1T6bI_BKnCajj0jQqxQdWjNt3oD7EtarJ9mqufMIH_w0eFk3JiT5s11v-rJdK4gzrzTugMT27Si97Ar_i3CYPDLDL1axkI-n0U4VVSgvktaxMcM0jSkKVH0XjcHY4svqqOSyD_tEPwQfkp_FbQh-AfQYEAtE1qLezT_Y7wQ4k2D3JT-eR76hre6VKYucmhfl8KV2UGG5NNhgwttMTUsDe2pcun" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;それで次にAVD Managerでデバイスを作ろうと思ったんですが、一覧にはOreoの上には&lt;code&gt;API 28&lt;/code&gt;としかありません。ひとまずこれでエミュレータ環境を作ってみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/pAl_3Nl1en4r29REZ1ulJGOENLCgF6SuXzO4IMZJojibJArQ9Az6n3JNyX4C7cbXZ9KBaFjFHg-gDJg8P3ilRWu95nTlTebFXuNVY-YonjRUkVqIxzofTNcLwEUpj0y6PpkRm3F9qI1xsfr-26GK-9X5prvZfZ5bRmYwNdYEU5JbM8BwxDLyPsWUWjnaZC_961Q6GKzUvnihd2SdXcE9OSpZbtghLJHf9hMpdvBOT8q82lRT58t1CiE5BuOPmdzfMOoHXcNqlUR3__MHQutX6CnrtaoGR9Ix7-9gSe8iSIsMp52AQ0WDW9r89hlD_r-dYblWHK4Tiu551KmsnAzPYw2oGAuJZkEBnKvaiI2yTQjYn63-W6-iMwZxZ9GIrdFZ9HhzRK9bY-Z87sIWTXKBvCo0lrJUeB-YJ30H1Byl349IPyJIAa907MHlSkY9gDXVNfKUYuYC8NvJ9M7i1yQxVZ85_FYCt4dPocrddkHJ4y89HJ5EsbaR5we4oiGxqkWpkbdOpb6CCyzGSakR1-vyPskG61N9hEKaQdsu0gNo09yuU1gXA1gs1gzeYPAuGyy2YasI7KhbodbsYiwZsqORmMcv-RlfSo1ce5Hmv5JdU-zD4qKTPJfSkXGPcgvgoh4uYUuy8W7NAWAIEL1h79AzXyfhi6zTTNpQ3trsLSZludkNCfJrItFNwXn_"&gt;&lt;img src="https://lh3.googleusercontent.com/pAl_3Nl1en4r29REZ1ulJGOENLCgF6SuXzO4IMZJojibJArQ9Az6n3JNyX4C7cbXZ9KBaFjFHg-gDJg8P3ilRWu95nTlTebFXuNVY-YonjRUkVqIxzofTNcLwEUpj0y6PpkRm3F9qI1xsfr-26GK-9X5prvZfZ5bRmYwNdYEU5JbM8BwxDLyPsWUWjnaZC_961Q6GKzUvnihd2SdXcE9OSpZbtghLJHf9hMpdvBOT8q82lRT58t1CiE5BuOPmdzfMOoHXcNqlUR3__MHQutX6CnrtaoGR9Ix7-9gSe8iSIsMp52AQ0WDW9r89hlD_r-dYblWHK4Tiu551KmsnAzPYw2oGAuJZkEBnKvaiI2yTQjYn63-W6-iMwZxZ9GIrdFZ9HhzRK9bY-Z87sIWTXKBvCo0lrJUeB-YJ30H1Byl349IPyJIAa907MHlSkY9gDXVNfKUYuYC8NvJ9M7i1yQxVZ85_FYCt4dPocrddkHJ4y89HJ5EsbaR5we4oiGxqkWpkbdOpb6CCyzGSakR1-vyPskG61N9hEKaQdsu0gNo09yuU1gXA1gs1gzeYPAuGyy2YasI7KhbodbsYiwZsqORmMcv-RlfSo1ce5Hmv5JdU-zD4qKTPJfSkXGPcgvgoh4uYUuy8W7NAWAIEL1h79AzXyfhi6zTTNpQ3trsLSZludkNCfJrItFNwXn_" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そしたら出来上がったのがこれ。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Android null&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/FWXFTd7jZkas4UwNyQ9azTBxM7-5FKq-IQZ98FhJjfmPSeFGgbDK3vwNAIyYa83NuBEZbL-1TF8ihK0EJor2uYHqaR-FCblCiA5nTeFKw6B6IUby0gXl08waEaoyfH0gFOCcd-pN-HOgnVYsww6s_ZmrJgo1PB8gPP0LWhtadjzGprRnHTwvChnb49BJvKntZKisUjWZPl3Ax7wnis3UFDK8MuXcETUah1fR21RUQd-6j5ThS1ciklIXixLAo0hIvR38Fas4w5pQKyvo78Tej-LEquIzPzHlYYlLR9QsMHx6TJm3fM_1AEDd-VqiKW_9GVt_XmPlQDS8HeLbhna0i1iw1YwQVVsKT_ZxvrJ9nVv2EqymsekRDSb9SP-WD1g4TJ9gP7wnvSb7aDxSovF2opRNgDk3DhsD7kLwTOciVs9GTeTf1dG4I1lgecmnKk1HyhN2N7ZPHr_pQYHi5xOp-68WCM52h4-cNdUtBDEbsoQfQ6CqMhCvp-oyctWQkZaGbtg5CD9QkSV4ZuPifPEG5JWveurOkkzpQvXjSbKqkoY6TRhjgyW3-CKsq6GJXIHVAnwyObgRji-gG4xp2XbWfqegN-HS3LdeZlDvX-NZ9hMfHtdYg4bgINcFVafvLyOL-86fa3lnht4bZjzBM0PTywBxZH-H_ltPynLc4WtWtz7h4F_rUCwU2mZA=w1186-h197-no"&gt;&lt;img src="https://lh3.googleusercontent.com/FWXFTd7jZkas4UwNyQ9azTBxM7-5FKq-IQZ98FhJjfmPSeFGgbDK3vwNAIyYa83NuBEZbL-1TF8ihK0EJor2uYHqaR-FCblCiA5nTeFKw6B6IUby0gXl08waEaoyfH0gFOCcd-pN-HOgnVYsww6s_ZmrJgo1PB8gPP0LWhtadjzGprRnHTwvChnb49BJvKntZKisUjWZPl3Ax7wnis3UFDK8MuXcETUah1fR21RUQd-6j5ThS1ciklIXixLAo0hIvR38Fas4w5pQKyvo78Tej-LEquIzPzHlYYlLR9QsMHx6TJm3fM_1AEDd-VqiKW_9GVt_XmPlQDS8HeLbhna0i1iw1YwQVVsKT_ZxvrJ9nVv2EqymsekRDSb9SP-WD1g4TJ9gP7wnvSb7aDxSovF2opRNgDk3DhsD7kLwTOciVs9GTeTf1dG4I1lgecmnKk1HyhN2N7ZPHr_pQYHi5xOp-68WCM52h4-cNdUtBDEbsoQfQ6CqMhCvp-oyctWQkZaGbtg5CD9QkSV4ZuPifPEG5JWveurOkkzpQvXjSbKqkoY6TRhjgyW3-CKsq6GJXIHVAnwyObgRji-gG4xp2XbWfqegN-HS3LdeZlDvX-NZ9hMfHtdYg4bgINcFVafvLyOL-86fa3lnht4bZjzBM0PTywBxZH-H_ltPynLc4WtWtz7h4F_rUCwU2mZA=w1186-h197-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;でも起動してシステム情報を見てみたらちゃんとAndroid versionは9となっていました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/iw1qJ5hD1he3i4rEQE8ME4hKLPl4wkNYpKBCDKzrdPRMz2mkQh65RIrmm5sjwwB007csKEf5wvhmYPTGPWxob2_QArGdamx0qN1MvALGjEEYd42Msq-OhjfVrnpaWXE8gQL3ZtE7wvHpAuYzlH0NuZhve8foY-K1DpXtntJ9dkX4cNkxbImDf3Ya8mJljLWFXfLKskFvJTNWZjN1n1R8hq1Bb0-HQToqEEGyDuYHqzJhLAS9enURw_laf6hnwz4YjOPXrYcMdJgWlT2GRBWF1J9Goc3wVgeeG-vY5aRoNvbHS0czhJRWRRuTj3poEiYo4SF65_8ktJVH4W8Y7DFjSYMpd_mq0vWLKIYdg1UR_wBdVLuyAhBIJ6cc5w2Rw8NZKizAXGPx0ITjb_mOs0QFU8LzQmmFn-d5Y7Ii9Z3P4WiY0qTXNZm3ukrKdQPm-YSStgQTmX2BL2yPc1KHcpTzZwfP6FOfXJbajUQP2irsXGg5UdfgkZfVnYl-lNVso_ajGdP49icTA_oIBD0ai7f4rDlDjwfKLHcHfUj9d3SSo-RG-55DW9l37HxI_I4LlBUsRTIMr2P5McjiQSjPV9Gad5r3okVGpjPeNRqdwGMVRin_KOlauDk93ZC45JvWaxEi0gwLaKSFR55T2MRCIChAxql9or6KfP_tmAZBI_VWdpetvwF0sZ2OP9_L"&gt;&lt;img src="https://lh3.googleusercontent.com/iw1qJ5hD1he3i4rEQE8ME4hKLPl4wkNYpKBCDKzrdPRMz2mkQh65RIrmm5sjwwB007csKEf5wvhmYPTGPWxob2_QArGdamx0qN1MvALGjEEYd42Msq-OhjfVrnpaWXE8gQL3ZtE7wvHpAuYzlH0NuZhve8foY-K1DpXtntJ9dkX4cNkxbImDf3Ya8mJljLWFXfLKskFvJTNWZjN1n1R8hq1Bb0-HQToqEEGyDuYHqzJhLAS9enURw_laf6hnwz4YjOPXrYcMdJgWlT2GRBWF1J9Goc3wVgeeG-vY5aRoNvbHS0czhJRWRRuTj3poEiYo4SF65_8ktJVH4W8Y7DFjSYMpd_mq0vWLKIYdg1UR_wBdVLuyAhBIJ6cc5w2Rw8NZKizAXGPx0ITjb_mOs0QFU8LzQmmFn-d5Y7Ii9Z3P4WiY0qTXNZm3ukrKdQPm-YSStgQTmX2BL2yPc1KHcpTzZwfP6FOfXJbajUQP2irsXGg5UdfgkZfVnYl-lNVso_ajGdP49icTA_oIBD0ai7f4rDlDjwfKLHcHfUj9d3SSo-RG-55DW9l37HxI_I4LlBUsRTIMr2P5McjiQSjPV9Gad5r3okVGpjPeNRqdwGMVRin_KOlauDk93ZC45JvWaxEi0gwLaKSFR55T2MRCIChAxql9or6KfP_tmAZBI_VWdpetvwF0sZ2OP9_L" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;困惑しましたが、一応大丈夫そうですね…？&lt;/p&gt;</description></item><item><title>Safariでファイル選択があるフォームでファイルを選ばずにXHRリクエストすると固まる</title><link>https://blog.piyo.tech/posts/2018-08-27-safari-xhr-file-input-bug/</link><pubDate>Mon, 27 Aug 2018 06:59:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-27-safari-xhr-file-input-bug/</guid><description>&lt;p&gt;MacとiOSのSafariでのファイル選択有りのフォームの送信がうまくいかないケースがありました。&lt;/p&gt;
&lt;p&gt;Submitボタンを押したときにChromeのNetworkに何も現れないのでしばらくはまりましたが、そのものズバリのバグがSafariにあることがわかりました。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://stackoverflow.com/questions/49614091/safari-11-1-ajax-xhr-form-submission-fails-when-inputtype-file-is-empty" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;stackoverflow.com →&lt;/span&gt;&lt;span&gt;https://stackoverflow.com/questions/49614091/safari-11-1-ajax-xhr-form-submission-fails-when-inputtype-file-is-empty&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ファイルinputが空の状態のときはajaxの送信前に該当のinputを&lt;code&gt;disabled&lt;/code&gt;にしておき、送信データが作られたあとは&lt;code&gt;disabled&lt;/code&gt;を外して元に戻しておくとやると回避できる、というコードが紹介されていました。&lt;/p&gt;
&lt;p&gt;こちらのQiita記事のコードのほうが&lt;code&gt;data-safari-temp-disabled&lt;/code&gt;みたいにinputを限定するような工夫があるので良さそうに思い、こちらのコードで回避するに至りました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://qiita.com/yuya_presto/items/65be91b0255af49f0396" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFtYXpvbmF3cy5jb20lMkYwJTJGNDE1MyUyRnByb2ZpbGUtaW1hZ2VzJTJGMTQ3MzY4MzgxND9peGxpYj1yYi00LjAuMCZhcj0xJTNBMSZmaXQ9Y3JvcCZtYXNrPWVsbGlwc2UmYmc9RkZGRkZGJmZtPXBuZzMyJnM9MzA2ZjI3MzIyODdiMmY0NmQ0YjM0NWVmMTMxNWM5MGE%26blend-x%3D120%26blend-y%3D462%26blend-w%3D90%26blend-h%3D90%26blend-mode%3Dnormal%26mark64%3DaHR0cHM6Ly9xaWl0YS1vcmdhbml6YXRpb24taW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnMzLWFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkZxaWl0YS1vcmdhbml6YXRpb24taW1hZ2UlMkY1ODUyOGJkYjkwNzA3OTE0ZjY5OWU0ZGM2YTQ3NGQwNjUwNTQ1NWUwJTJGb3JpZ2luYWwuanBnJTNGMTQ5MjE0NzA5Mj9peGxpYj1yYi00LjAuMCZ3PTQ0Jmg9NDQmZml0PWNyb3AmbWFzaz1jb3JuZXJzJmNvcm5lci1yYWRpdXM9OCZiZz1GRkZGRkYmYm9yZGVyPTIlMkNGRkZGRkYmZm09cG5nMzImcz1hZjgzZjFmYmQzYzJmY2VkMjlkNzhlM2RjNTVmMjY3ZQ%26mark-x%3D186%26mark-y%3D515%26mark-w%3D40%26mark-h%3D40%26s%3D18e71cbc5654044248836c610789d3e2?ixlib=rb-4.0.0&amp;amp;w=1200&amp;amp;fm=jpg&amp;amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9aU9TJTIwMTEuMyUyMFNhZmFyaSVFMyU4MSVBOG1hY09TJTIwU2FmYXJpJTIwMTEuMSVFMyU4MSVBRSVFNyVBOSVCQSUzQ2lucHV0JTIwdHlwZSUzRCUyMmZpbGUlMjIlM0UlRTMlODIlOTJBamF4JUUzJTgxJUE3JUU5JTgwJTgxJUU0JUJGJUExJUUzJTgxJUE3JUUzJTgxJThEJUUzJTgxJUFBJUUzJTgxJTg0JUU1JTk1JThGJUU5JUExJThDJUUzJTgxJUI4JUUzJTgxJUFFJUU1JUFGJUJFJUU1JUJGJTlDJnR4dC1hbGlnbj1sZWZ0JTJDdG9wJnR4dC1jb2xvcj0lMjMxRTIxMjEmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9NTYmdHh0LXBhZD0wJnM9MzQ2MzgzMmI0OTBiOWUxMDJmNzBhYWZmZGQ4ZjcxNjA&amp;amp;mark-x=120&amp;amp;mark-y=112&amp;amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDB5dXlhX3ByZXN0byZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTM2JnR4dC1wYWQ9MCZzPTY5NzNkMTc1OWQ5YWRmNDAwYzEzYzAwNzQzM2VlNWYx&amp;amp;blend-x=242&amp;amp;blend-y=454&amp;amp;blend-w=838&amp;amp;blend-h=46&amp;amp;blend-fit=crop&amp;amp;blend-crop=left%2Cbottom&amp;amp;blend-mode=normal&amp;amp;txt64=5qCq5byP5Lya56S-44Kz44O844OJ44K_44Kv44OI&amp;amp;txt-x=242&amp;amp;txt-y=539&amp;amp;txt-width=838&amp;amp;txt-clip=end%2Cellipsis&amp;amp;txt-color=%231E2121&amp;amp;txt-font=Hiragino%20Sans%20W6&amp;amp;txt-size=28&amp;amp;s=551360b287156ad9663758604e6dfd5a" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;iOS 11.3 SafariとmacOS Safari 11.1の空 をAjaxで送信できない問題への対応 - Qiita&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;「特定のiOS端末だけ投稿時に400 Bad Requestが返ってくる」・・・突然のバグ報告をもらい、同僚の @elim さんと一緒に四苦八苦しながら調査した結果、最新のSafariのバグであることを突き止めた話です。 SafariのXHRバグの概要 iOS 11.3と...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;qiita.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>rest-clientで書いたAPIクライアントでプロキシが使えないケースがあったのでFaradayで書き換える</title><link>https://blog.piyo.tech/posts/2018-08-26-faraday-from-rest-client/</link><pubDate>Sun, 26 Aug 2018 06:14:47 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-26-faraday-from-rest-client/</guid><description>&lt;p&gt;rest-clientでAPIクライアントを書くって記事を書いたんですが、プロキシサーバーの設定によっては正しく接続できないケースがあったのでクライアント自体をFaradayで書き換えることをやりました。&lt;/p&gt;
&lt;p&gt;接続できないケースというのは、プロキシサーバーのパスワードに特殊な文字（僕の場合は&lt;code&gt;^+$&lt;/code&gt;など）が入っている場合で、エラー内容は残してないですが文字列処理か何かでエラーとなった記憶があります。特殊文字がエスケープできないか、とか色々試したんですが、確かダメだった気が、、ちょっと曖昧です。&lt;/p&gt;
&lt;h1 id="rest-client版"&gt;rest-client版&lt;/h1&gt;
&lt;p&gt;以下、rest-clientについて書いたときの記事から転載。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-08-10-api-client-with-rest-client/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/eDb1YtJd4SA3ZfNqhTKQy5hLY6pbIlBS9Nq6Q3EE8MvLVUGSaLsyvkMLsz9N4wDkPrbj9eVZ8zn29YwOMImXeDiO3MuqwMdpdGOU5igQodEQwywKlpKR_gM97CjNbDei7mtBLBmPzG_D6Pf4mMQS_ZlLSZQXM7mrC9gJNJipt-5_1y-et-brs0qbdBFc07JJohjJp9z90UriwXxkuoTdtXyGkQ9awf8G5pRvoI4ifDQ_RaTxeixE2gVPYZ6cLHy0X4guyxAXAKlBDpNJwcr6VKU9hQJzulM-JVhR81j0ucyWxlN6USozGOchRhZzRjQP6Q2Z2Ry4FN0Icbr2whR0Nn3mUewbl8_zww3H51VWr_AbPnCcAu5_GiGXlWqXC3C_2rZHnYEX6MkD-JlmcTogjM07VwJHFt-YbOWa8U2lBu81EivV3cNc_042IpENan1C3rET8K6Y-G2zYVj9475g2t7Qf6PDwo6kGgh6sCkKsXQc6lPy4iz_ttzGbXpMb1oy2Xs7yFNcdq3uc2iT-j6UBGCTWFvW7PZUoZCS4UpIBRWVX5MU4qWblP1ll4V7GwtYiKdo7u3Mamlhw_ypmdhYygPvXsy7KOX9Mho71DIGc_GBycF5EEzTCUwM4-UiWQFJxaUdOLvAy0BJWUrOXqBdcCDBhZEln_q6cA=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;rest-clientで簡易にAPIクライアントを書く - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;オープンではないサービスのAPIを使うとき、APIクライアントが無いってことが多いです。なのでアプリケーションから使いたいAPIだけを叩くような簡易なAPIクライアントを自分で書きます。そのときはrest-clientあたりを使ってベタっと書いてしまうことがほとんどです。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ApiClient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ENDPOINT&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;https://api.example.com/items.json&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;freeze
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; self
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;items&lt;/span&gt;(search)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENDPOINT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; params &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;s&lt;/span&gt;: search}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; get(url, params)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;[]&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; data&lt;span style="color:#f92672"&gt;.&lt;/span&gt;nil?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; data&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;items&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;].&lt;/span&gt;map &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;item&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ItemResponse&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(item)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;item&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(url, params)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; res &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;RestClient&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(url, &lt;span style="color:#e6db74"&gt;params&lt;/span&gt;: params)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; res&lt;span style="color:#f92672"&gt;.&lt;/span&gt;code &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;JSON&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;parse(res&lt;span style="color:#f92672"&gt;.&lt;/span&gt;body)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# こんな感じで使う&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ApiClient&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;items(&lt;span style="color:#e6db74"&gt;&amp;#39;けんさく&amp;#39;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;[...]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="faraday版"&gt;Faraday版&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ApiClient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ENDPOINTはホストまでになる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ENDPOINT&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;https://api.example.com/&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;freeze
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; self
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;items&lt;/span&gt;(search)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; params &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;s&lt;/span&gt;: search}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ENDPOINTは固定なのでpath渡し変えておく&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; get(&lt;span style="color:#e6db74"&gt;&amp;#39;items.json&amp;#39;&lt;/span&gt;, params)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 以下同じ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;[]&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; data&lt;span style="color:#f92672"&gt;.&lt;/span&gt;nil?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; data&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;items&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;].&lt;/span&gt;map &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;item&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ItemResponse&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(item)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(path, params)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; conn &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Faraday&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#66d9ef"&gt;ENDPOINT&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;proxy&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;uri&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;proxy_url&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;user&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;proxy_account&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;password&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;proxy_password^+$&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; res &lt;span style="color:#f92672"&gt;=&lt;/span&gt; conn&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(path, params)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; res&lt;span style="color:#f92672"&gt;.&lt;/span&gt;status &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;JSON&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;parse(res&lt;span style="color:#f92672"&gt;.&lt;/span&gt;body)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 使い方は一緒&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ApiClient&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;items(&lt;span style="color:#e6db74"&gt;&amp;#39;けんさく&amp;#39;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;[...]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Faraday版の場合はプロキシのアカウントを個別に指定できるので特殊文字が含まれていても問題がありませんでした。&lt;/p&gt;</description></item><item><title>Mac画面収録をAutomatorでアプリ化してショートカットで起動する</title><link>https://blog.piyo.tech/posts/2018-08-25-screen-recording-by-shortcut-key/</link><pubDate>Sat, 25 Aug 2018 06:53:53 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-25-screen-recording-by-shortcut-key/</guid><description>&lt;p&gt;兼ねてからQuickTimeを使った画面収録までの手数が面倒だなーと思っていたのでAppleScriptで自動化する方法を調べました。&lt;/p&gt;
&lt;p&gt;これにより&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;QuickTimer Playerの起動&lt;/li&gt;
&lt;li&gt;画面収録を選択&lt;/li&gt;
&lt;li&gt;録画開始のボタンを押す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ところまでを自動でやってくれるため、あとは録画する画面をクリックするか、録画したい範囲をドラッグするかだけで録画を始められるようになります。めちゃ便利。&lt;/p&gt;
&lt;h1 id="方法"&gt;方法&lt;/h1&gt;
&lt;p&gt;Automatorを使います。Automatorくん、久々に登場するなあ。&lt;/p&gt;
&lt;p&gt;Automatorはアプリケーションフォルダにあります。Spotlightなどから検索してもOK。起動したらアプリケーションを選んで開始します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/CYglIHAlPB6jrwXEpAbmqt0DUw65anBKQfsTft_DV1lwpNlTizs7UjYlO_JLtfsN76pCg8dtWD49B3OFGAJRswb-EHDBAXgz5xbRy9SW_QjC47l6sjsyC18oF732e3SEnwPbaBYOPF6tBuJliQG4rN6xo7fuTUwUqpHIGB8O-stHwXTcgUkBscasQB3p6G9XL18Ga5ovKm1e8qTG-9DdpBVjmavjMVPzJP2L3QyTOnt-W7qRhAt5qX7a-Kz8eU5-oII8_chtj7Nq-ELzpilEntZgjgQ52lTwg17Z3QXvaC__u7zF1C-4irQrrqfzZTFiKgvAGSKJa1CyaLy4yIiwj6_ChBbAd5WImMiU7rzBZnazWpXnfek93LZHpjcSg0qLiPK8zuFAXZUpu24fHAJtajpI-CPBtScIGAM7hq4LxCIL3XgRqKm2hyMzdyre8FypKmiZVxDsQl0gy91syuEJI1fOMenUfXdFFx8_inZhADEaAQxi-E0KTSSdZzrAVvG-zk71sxJEGCEf0EE721bZglVwwceBLdot3OBYDe3DJJt7yqgRZ-IUHqeqIu_T-a5rZBxDAWp721RYMAX20FPPuAE2me7TFGb29PZ56x5KePhU0F27roLyxotQAJUfNlYL0n7N0uuw7mKfkgWgbZZya1RecMBeL2wkV5IBb5GB2gFfcfLhjVtntnJM=w291-h283-no"&gt;&lt;img src="https://lh3.googleusercontent.com/CYglIHAlPB6jrwXEpAbmqt0DUw65anBKQfsTft_DV1lwpNlTizs7UjYlO_JLtfsN76pCg8dtWD49B3OFGAJRswb-EHDBAXgz5xbRy9SW_QjC47l6sjsyC18oF732e3SEnwPbaBYOPF6tBuJliQG4rN6xo7fuTUwUqpHIGB8O-stHwXTcgUkBscasQB3p6G9XL18Ga5ovKm1e8qTG-9DdpBVjmavjMVPzJP2L3QyTOnt-W7qRhAt5qX7a-Kz8eU5-oII8_chtj7Nq-ELzpilEntZgjgQ52lTwg17Z3QXvaC__u7zF1C-4irQrrqfzZTFiKgvAGSKJa1CyaLy4yIiwj6_ChBbAd5WImMiU7rzBZnazWpXnfek93LZHpjcSg0qLiPK8zuFAXZUpu24fHAJtajpI-CPBtScIGAM7hq4LxCIL3XgRqKm2hyMzdyre8FypKmiZVxDsQl0gy91syuEJI1fOMenUfXdFFx8_inZhADEaAQxi-E0KTSSdZzrAVvG-zk71sxJEGCEf0EE721bZglVwwceBLdot3OBYDe3DJJt7yqgRZ-IUHqeqIu_T-a5rZBxDAWp721RYMAX20FPPuAE2me7TFGb29PZ56x5KePhU0F27roLyxotQAJUfNlYL0n7N0uuw7mKfkgWgbZZya1RecMBeL2wkV5IBb5GB2gFfcfLhjVtntnJM=w291-h283-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;んで、AppleScriptを選んで右側にドラッグして追加します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/RxR2A6TSqQ8yxmulkYaT2E1VepGddY_6IZ8D6f-4PhAqtzsp8oKY_n7WEzGzHsKYjcpU5KFGQf8sM7l3xY8kfPFfBVgPusE58AHJLie3kv5zj3IHp-D-L6g477QnSQCAVJOtVUuqjHjlFsLsqxqfNJ_MrXguqQlSki5ShD_Hds47utlGC7AP3K6Vrtuw2O7mrKZlssnufbGkGG_4QAAad7dcG1fWXtqP34iAZXuNlxhB4Zdh3Rja9ccpI9taH3l2t_Oz7_aylgBUMvDMyeEnnCC_A3ROYItZ5cg-BB9lwW9IzqFQ61XzvVqbxKvSeZlsBuyZIon-Hctk2Pf5Y3NMk4WlgngaUXtg6W-NjomY1YuR15Lkp1ElNOKB9FF_DFn3tZgZnO3N1zZAP7TuwVoFwU9CCCZHtLk2b3ZXMqleClG44T1-vxJOKPg_Yr2A-atdCSjK8mrQsku1aTKAXmru1e21fOyR9DXmaxXdFBdvPUX08V0lPVIOlLfC61ebIGPCVW6dlHtqj66Q5A2xNMZril0Ohi-2zNHmKpT1ZnFdagtea5B93JVR32SPIarb3f2BfXGTH6-HN9drDbo14OUHj2TmPgQ4b7p-1k8BQPXtJ3EjAIc5jzys7VsUIDY7cCwC9X4N7ntkc0jrPIoXWFkML-aIeYEjsgcQuHf78IPrLA8WCq16R6V-Q-Fy=w1866-h670-no"&gt;&lt;img src="https://lh3.googleusercontent.com/RxR2A6TSqQ8yxmulkYaT2E1VepGddY_6IZ8D6f-4PhAqtzsp8oKY_n7WEzGzHsKYjcpU5KFGQf8sM7l3xY8kfPFfBVgPusE58AHJLie3kv5zj3IHp-D-L6g477QnSQCAVJOtVUuqjHjlFsLsqxqfNJ_MrXguqQlSki5ShD_Hds47utlGC7AP3K6Vrtuw2O7mrKZlssnufbGkGG_4QAAad7dcG1fWXtqP34iAZXuNlxhB4Zdh3Rja9ccpI9taH3l2t_Oz7_aylgBUMvDMyeEnnCC_A3ROYItZ5cg-BB9lwW9IzqFQ61XzvVqbxKvSeZlsBuyZIon-Hctk2Pf5Y3NMk4WlgngaUXtg6W-NjomY1YuR15Lkp1ElNOKB9FF_DFn3tZgZnO3N1zZAP7TuwVoFwU9CCCZHtLk2b3ZXMqleClG44T1-vxJOKPg_Yr2A-atdCSjK8mrQsku1aTKAXmru1e21fOyR9DXmaxXdFBdvPUX08V0lPVIOlLfC61ebIGPCVW6dlHtqj66Q5A2xNMZril0Ohi-2zNHmKpT1ZnFdagtea5B93JVR32SPIarb3f2BfXGTH6-HN9drDbo14OUHj2TmPgQ4b7p-1k8BQPXtJ3EjAIc5jzys7VsUIDY7cCwC9X4N7ntkc0jrPIoXWFkML-aIeYEjsgcQuHf78IPrLA8WCq16R6V-Q-Fy=w1866-h670-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;その中身はこう。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;tell application &amp;#34;QuickTime Player&amp;#34; to activate
tell application &amp;#34;System Events&amp;#34;
activate
tell process &amp;#34;QuickTime Player&amp;#34;
click menu item &amp;#34;新規画面収録&amp;#34; of menu &amp;#34;ファイル&amp;#34; of menu bar 1
end tell
end tell
tell application &amp;#34;QuickTime Player&amp;#34;
activate
tell application &amp;#34;System Events&amp;#34; to key code 49
end tell
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;QuickTime Playerを開いてメニューから新規画面収録を選ぶ、という動作をしています。Automatorから実行してみるとちゃんと録画待ち状態になるはずです。&lt;/p&gt;
&lt;p&gt;こんな感じで。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/DmGgDG90gxo46EJCqiucPlHqC2J1U2vICdLumcKJa8XqLna7fW9_GQQw2Hq30rplUw8D1IMQkJ4Qz0FFNsGVAx_hjfFoNyknm8fUDEjhxz7W1cocFx7ZENZ_84DPSg97ZbIT7R-qHFbssPmGDppsxkmGFS4iJ7M406HaHVjL-X7ZqHihEFEjwjkyP6DeGSMVP_foAxjQm-NyHJELTQJK35vfRxgrlXMYalri9Tlf1axlKJLprzMCs6QNeObsPY-2__IYswtKPq35VIahmintLcisICESEr6XX7DkQyGVj_fQglef6w-tRmipWw6ZaHZgbjR3VIw7APtZiknXqtyNMa8RgPJXNkrEEZ8z9APaF-sBr1foy0lJd33TlZPDo0_TLkyJvrLLhONyAp33QJgkNiuOe1tjFSeX1s45_bY3y_cwqvI0QY8yj6KBKuXbrd5czgPbqENCuwQGKd5lJIY3EUmANUvogGIAc0VNs18kzjSLGO0OApAu4EzZG_Ux7WvRCHfyotnkgDVBIhQZEwDddVNmAxKp_u_-7eYfvNnaIvst6eOtoza12OJO2XvGXZwRy8ReBMuq9RN-77UKJCFz33m6jVbf9kD3i3MHgnIZoYMJrCdPeI5pTMZHiT6EbQzZNkCpXqYVHUqel41pn67myhAtWfqqwFJkA7iFpskfDIfxTNZzVrwbZK_1=w2032-h974-no"&gt;&lt;img src="https://lh3.googleusercontent.com/DmGgDG90gxo46EJCqiucPlHqC2J1U2vICdLumcKJa8XqLna7fW9_GQQw2Hq30rplUw8D1IMQkJ4Qz0FFNsGVAx_hjfFoNyknm8fUDEjhxz7W1cocFx7ZENZ_84DPSg97ZbIT7R-qHFbssPmGDppsxkmGFS4iJ7M406HaHVjL-X7ZqHihEFEjwjkyP6DeGSMVP_foAxjQm-NyHJELTQJK35vfRxgrlXMYalri9Tlf1axlKJLprzMCs6QNeObsPY-2__IYswtKPq35VIahmintLcisICESEr6XX7DkQyGVj_fQglef6w-tRmipWw6ZaHZgbjR3VIw7APtZiknXqtyNMa8RgPJXNkrEEZ8z9APaF-sBr1foy0lJd33TlZPDo0_TLkyJvrLLhONyAp33QJgkNiuOe1tjFSeX1s45_bY3y_cwqvI0QY8yj6KBKuXbrd5czgPbqENCuwQGKd5lJIY3EUmANUvogGIAc0VNs18kzjSLGO0OApAu4EzZG_Ux7WvRCHfyotnkgDVBIhQZEwDddVNmAxKp_u_-7eYfvNnaIvst6eOtoza12OJO2XvGXZwRy8ReBMuq9RN-77UKJCFz33m6jVbf9kD3i3MHgnIZoYMJrCdPeI5pTMZHiT6EbQzZNkCpXqYVHUqel41pn67myhAtWfqqwFJkA7iFpskfDIfxTNZzVrwbZK_1=w2032-h974-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="アクセシビリティ"&gt;アクセシビリティ&lt;/h1&gt;
&lt;p&gt;さて、これをAutomatorで保存すると&lt;code&gt;xxxxx.app&lt;/code&gt;みたいなものが保存できますが、&lt;code&gt;app&lt;/code&gt;をこのまま実行するとアクセシビリティの都合でエラーが出るはずです。&lt;/p&gt;
&lt;p&gt;そこでシステム設定のアクセシビリティで、今回書き出したアプリを許可しましょう。この画面です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/iWvDv6MwtpNdx2UDc9hHayYbKrl1M-y0bPPcFTUQOfRHdwS09hda3aDk5EXlW0MATqH8Hnley3QNzQL5Bc6IW4CV8kJUW9zFKVyKieAJjnjHs8DTWrTXwb2DlO5SpOyG89p0AFhNVYjBN38Mlfbw7IrZYbKYEGGFAEBz6ERBylcCZdTxvxjs3mA5mcUras-mHd9sq3MWTDMNg_azEmJBbBIP64qdQEX23B4WknIA26pd8XbpJGJOUug2Z8I5nBrXb-WyZ8xFjIEpvq1WuHEnPsgLc-n7bS8MTpf02D2iAa00nqZE28aqkws890Q2qRk3SDHNrKuHkTEChgVbfRscjzaEgVuqyr3yCOVu_RaKVoiElvy9yXKj8PnX7WSqVBTDE1dtBvZa9oGDKrDywxpfp3xpM56O4PIVGWmO9AY9EEOff0-sNlWo11Ca_6HZ8Qvgc3fIG1XTXAqC3lsCf3Y4S1YSmPrTEW5P5MId3oeQh24DSsZchjEHkDO0JDbHXxOAyyvCTeWzSC2M2h1lNS8kVKXFTQoLTeqEPcuwtz4hjuIz7U0rm5CJZx2Zt61AK5njjXeP_n5B7vxiy0xuNbljXyp9H7gpYx9MWlayxauAMmgwHWXA8TfcH3lqHtPTrx9Zq3CdmgklyRfbWgGo-8TOb4n5eOwzebli4vL4FzFUOxR0xWrMxMjilIqD=w581-h410-no"&gt;&lt;img src="https://lh3.googleusercontent.com/iWvDv6MwtpNdx2UDc9hHayYbKrl1M-y0bPPcFTUQOfRHdwS09hda3aDk5EXlW0MATqH8Hnley3QNzQL5Bc6IW4CV8kJUW9zFKVyKieAJjnjHs8DTWrTXwb2DlO5SpOyG89p0AFhNVYjBN38Mlfbw7IrZYbKYEGGFAEBz6ERBylcCZdTxvxjs3mA5mcUras-mHd9sq3MWTDMNg_azEmJBbBIP64qdQEX23B4WknIA26pd8XbpJGJOUug2Z8I5nBrXb-WyZ8xFjIEpvq1WuHEnPsgLc-n7bS8MTpf02D2iAa00nqZE28aqkws890Q2qRk3SDHNrKuHkTEChgVbfRscjzaEgVuqyr3yCOVu_RaKVoiElvy9yXKj8PnX7WSqVBTDE1dtBvZa9oGDKrDywxpfp3xpM56O4PIVGWmO9AY9EEOff0-sNlWo11Ca_6HZ8Qvgc3fIG1XTXAqC3lsCf3Y4S1YSmPrTEW5P5MId3oeQh24DSsZchjEHkDO0JDbHXxOAyyvCTeWzSC2M2h1lNS8kVKXFTQoLTeqEPcuwtz4hjuIz7U0rm5CJZx2Zt61AK5njjXeP_n5B7vxiy0xuNbljXyp9H7gpYx9MWlayxauAMmgwHWXA8TfcH3lqHtPTrx9Zq3CdmgklyRfbWgGo-8TOb4n5eOwzebli4vL4FzFUOxR0xWrMxMjilIqD=w581-h410-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;左下の鍵マークを開けてから先ほど保存した&lt;code&gt;.app&lt;/code&gt;のファイルをリストにドラッグドロップします。元々リストに存在する場合はチェックを入れればOK。&lt;/p&gt;
&lt;p&gt;これでアプリとして動いてくれるようになります。&lt;/p&gt;
&lt;p&gt;あとはショートカットの設定ですが、僕はアプリの起動に&lt;code&gt;Snap&lt;/code&gt;という常駐型のアプリを使っていますので、このアプリも同じように追加すればOK。すぐに録画できますね。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Snapについてはこちら&lt;/strong&gt;&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-05-13-snap-app/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/J-gwVvf5EeIPukLol8SiFJSbeSmFPnFp6rgVC4VKCorSIrdToZkOqpfEC7nxm9WJ7K67wP67TX-1xCFVj3U5G__WloR1Mn4qxPAverUUMTAbAUTsOlclsG5vDUjmTznBgZmQHfD6SVtxolMIKn1Te7pMnz1OYwFsdy2cP6hYLlyOE4uQ7GGdODIbeIXIonZETn2ujF3tmgmCIynDfRmehtiLDFl8unWDq2AMmgd6tXLKYae7paOTpQJstNtlzpfiSAeNvkEADQw2KpW2rv-cXSGmssY6kD48klxvVMNTT9qoDfjHpg7nGGyOVYfJEag0MCX23DnEz_HZ86uS1Efve293MdsN841utdXY9d0PZp9Na36y6heTf2nUb14ursDe1jQivLc_bJ3u7rz3muJrDBAfnbVhfJHuLAQSvi9gFPdoNkGyI8exqZs9E6zW6RGMLyg0FSZEV_EugJBdeda-i7T1bQu6SXDRdwiGyr2ypQRP992DB_A5YKCLzu3YcRaPtAJq8BZUbGvAmU1UJpYtffiK-dj60Grkg5re1ZQc4w-XYola9yhSjQF7OBXyY7n_ydIYd_-_go4MSV9Gf9ftIXRhPg6OMZKkIMOReDb8MkNlI-44udKofuIKiZMtikS2QONzaFguAshVqdxEhNJKYkTYEUgev00f8Q=w657-h411-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Macアプリをショートカットで起動できるようにするSnap - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;よく使うアプリはAlfredみたいなランチャーから起動するのが面倒なのでSnapという常駐アプリを使ってショートカットから起動できるようにしています。 https://itunes.apple.com/jp/app/snap/id418073146?mt=12 例えばGoogle Chromeに「ctrl &amp;#43; shift &amp;#43; cmd &amp;#43; c」キーを割り当てていて、ブラウザを起動したいときやフォアグラウンドに持ってきたいときのこのキーを押します。また、フォアグラウンドにいるアプリのショートカットを押すとバックグラウンドに回ってくれます。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>UIImageの明るさをCIFilterで調整するSwiftコード</title><link>https://blog.piyo.tech/posts/2018-08-24-change-uiimage-brightness/</link><pubDate>Fri, 24 Aug 2018 06:53:05 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-24-change-uiimage-brightness/</guid><description>&lt;ul&gt;
&lt;li&gt;CIFilterを使う&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CIColorControls&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inputBrightness&lt;/code&gt;に値を設定&lt;/li&gt;
&lt;li&gt;値は&lt;code&gt;−1.0&lt;/code&gt;〜&lt;code&gt;1.0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CoreImage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;extention UIImage {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;adjustBrightness&lt;/span&gt;(brightness: Double) -&amp;gt; UIImage? {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; ciImage = CIImage(cgImage: &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.cgImage!)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; filter = CIFilter(name: &lt;span style="color:#e6db74"&gt;&amp;#34;CIColorControls&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; filter?.setValue(ciImage, forKey: kCIInputImageKey)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; filter?.setValue(brightness, forKey: &lt;span style="color:#e6db74"&gt;&amp;#34;inputBrightness&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;guard&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; newCIImage = filter?.outputImage &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; context = CIContext(options: &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;guard&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; cgImage = context.createCGImage(newCIImage, from: newCIImage.extent) &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; UIImage(cgImage: cgImage, scale: &lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt;, orientation: .up)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こんな感じで使える。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; image = UIImage(...)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; newImage = image.adjustBrightness(brightness: &lt;span style="color:#ae81ff"&gt;0.5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>CircleCIでRSpecの結果htmlをアーティファクトにおいて見られるようにする</title><link>https://blog.piyo.tech/posts/2018-08-23-rspec-html-results-on-ci/</link><pubDate>Thu, 23 Aug 2018 06:34:10 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-23-rspec-html-results-on-ci/</guid><description>&lt;p&gt;&lt;code&gt;rspec&lt;/code&gt;に&lt;code&gt;--format html --out FILE&lt;/code&gt;みたいなオプションをつけるとHTMLで結果を出力できます。&lt;/p&gt;
&lt;p&gt;とある事情でCircle CIのアーティファクトに置く必要が出たので、試してみました。&lt;/p&gt;
&lt;p&gt;Circle CIのV2です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;working_directory&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;/tmp/working-directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;- &lt;span style="color:#f92672"&gt;run&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Run rspec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;command&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; bundle exec rspec --format html --out /tmp/working-directory/rspec.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;- &lt;span style="color:#f92672"&gt;store_artifacts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;path&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;/tmp/working-directory/rspec.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;destination&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;rspec.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;色々と略してますが、要はワークングディレクトリに結果を書き出して、その結果を&lt;code&gt;store_artifacts&lt;/code&gt;で配置するという感じです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/YYfJGVknRAx-HdcVNUdiBZcwTOGdPam-mRylHkOgTmH-gfrzPd66cgAIeDqIY9lAh3r8pnRiF2-eM6D3yV2-VMOAo1_Ou9ccO0dDjH1mwr2WVzBLUFcK7UZwrG3N0pTGyl96ITeE9WLcXtJlrg435zbqhy9Uc4geykDXEGjONR_VW1uvWzO7zIHz5PGdFw1ts5hY7m6nCClK1HHei25A0aTKYWi5pJmi6Wnkf_TN9m3VTvtfQTWiraqkJKSEsmdmYSvIJY_6ZqvNWSI7VR9loEhnjzXq90rSPWEkq9_mEXbgc7giLtfKixZEj69qBfTI9gbHgUxFARlWJbSbOHGtxEc0WRNmQEfsUWKOTQLeh_L-_I4y5_JdcdCumSTiZ6mmY62rsytr2LkEBEDuZWD8KDZVe77NNr2woFlidVJuB7ykqA7Ul8faWd50hw6ByeGSZKDhd4tcYwVm3V2zcAqqXlVAbrsoSJEfAZAvxdfNdZFzrKRqAcKylrWvPppGzo8sOvFG751RAM9PkVbGo8JDm8tBe2KF3XbmvPRScb39cjBsHZlRDcl3b1GSevO8spqObQugSpJ-M5adnZI-ZEsNid7W34CDsIDPaHzdgb_21-gfQAyYn3hiDuBnkWcO-GCl4U9v3eot3ffehgb1bJka-nwZR9qwtndZ=w608-h135-no"&gt;&lt;img src="https://lh3.googleusercontent.com/YYfJGVknRAx-HdcVNUdiBZcwTOGdPam-mRylHkOgTmH-gfrzPd66cgAIeDqIY9lAh3r8pnRiF2-eM6D3yV2-VMOAo1_Ou9ccO0dDjH1mwr2WVzBLUFcK7UZwrG3N0pTGyl96ITeE9WLcXtJlrg435zbqhy9Uc4geykDXEGjONR_VW1uvWzO7zIHz5PGdFw1ts5hY7m6nCClK1HHei25A0aTKYWi5pJmi6Wnkf_TN9m3VTvtfQTWiraqkJKSEsmdmYSvIJY_6ZqvNWSI7VR9loEhnjzXq90rSPWEkq9_mEXbgc7giLtfKixZEj69qBfTI9gbHgUxFARlWJbSbOHGtxEc0WRNmQEfsUWKOTQLeh_L-_I4y5_JdcdCumSTiZ6mmY62rsytr2LkEBEDuZWD8KDZVe77NNr2woFlidVJuB7ykqA7Ul8faWd50hw6ByeGSZKDhd4tcYwVm3V2zcAqqXlVAbrsoSJEfAZAvxdfNdZFzrKRqAcKylrWvPppGzo8sOvFG751RAM9PkVbGo8JDm8tBe2KF3XbmvPRScb39cjBsHZlRDcl3b1GSevO8spqObQugSpJ-M5adnZI-ZEsNid7W34CDsIDPaHzdgb_21-gfQAyYn3hiDuBnkWcO-GCl4U9v3eot3ffehgb1bJka-nwZR9qwtndZ=w608-h135-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ところがこれをやってしまうと肝心のCIの画面への出力がなくなってしまうため、でどのテストが失敗したのかがわからなくなってしまいました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/CCdlGJ-fbw8wffomoz653YUU8FVoKm298DaMx8dW0XUm6bMp5ykZFgusPSdLuBDfloD8J9MxWviGC4nJNloMAj4it9rAbv4qVGxNFNSVm-wvT1Fy8EdqfiMM5SlWrjbgo1ma7JMbinSgsrJFFkA7xGiSfXyyqDs5faPvcLP2ZTKyw5DQn4lTJEsVaKxrrqreCBRf6t_RyrDav9UuwVhreRtuRO8oM1fu4J_iN2sR0ulBIHxdUDIBggSpsVekQWjsUWmjhojEx81ElZuGfH1VI78Oqv-_kQ8M32NXY3xnrpnxtnev1ZuNhNey31ipuCB83PC80wwNZaC29EtO4MN0PfVvB2Hjd9g2vxSZJjZACUo7ftS7ToxiJAqgtdheFq-7vrs_-7rnBz1FsTAUmSczHfaYbscfzn8mRUJw3vW9Kuw4o-1H5wO3185duHRPG-NhVWesIBL2OoXBx3qhLvTmKNqaAwi0rCWGn4IZBfj57A0LTsQBRsuslZSrOKibapfPuOHyLHnx9Z06DYv5Eua6rZdROO5STEXgcCjVjaP-yZcNc-7Px5xotIXK74o_f3MHM2iIOqe5_LN8duZt3wGHvlgccp80T0IwMdeX0cxZ_uWgkcpWQ-saxGjRLMjYpfrC0bqXaK37995ylAzE75h5K2_HDV_3xwmr=w949-h198-no"&gt;&lt;img src="https://lh3.googleusercontent.com/CCdlGJ-fbw8wffomoz653YUU8FVoKm298DaMx8dW0XUm6bMp5ykZFgusPSdLuBDfloD8J9MxWviGC4nJNloMAj4it9rAbv4qVGxNFNSVm-wvT1Fy8EdqfiMM5SlWrjbgo1ma7JMbinSgsrJFFkA7xGiSfXyyqDs5faPvcLP2ZTKyw5DQn4lTJEsVaKxrrqreCBRf6t_RyrDav9UuwVhreRtuRO8oM1fu4J_iN2sR0ulBIHxdUDIBggSpsVekQWjsUWmjhojEx81ElZuGfH1VI78Oqv-_kQ8M32NXY3xnrpnxtnev1ZuNhNey31ipuCB83PC80wwNZaC29EtO4MN0PfVvB2Hjd9g2vxSZJjZACUo7ftS7ToxiJAqgtdheFq-7vrs_-7rnBz1FsTAUmSczHfaYbscfzn8mRUJw3vW9Kuw4o-1H5wO3185duHRPG-NhVWesIBL2OoXBx3qhLvTmKNqaAwi0rCWGn4IZBfj57A0LTsQBRsuslZSrOKibapfPuOHyLHnx9Z06DYv5Eua6rZdROO5STEXgcCjVjaP-yZcNc-7Px5xotIXK74o_f3MHM2iIOqe5_LN8duZt3wGHvlgccp80T0IwMdeX0cxZ_uWgkcpWQ-saxGjRLMjYpfrC0bqXaK37995ylAzE75h5K2_HDV_3xwmr=w949-h198-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そこで更に&lt;code&gt;--format&lt;/code&gt;オプションを追加し標準出力にも出すようにすることでCIの画面上からも確認できるようにしました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;bundle exec rspec --format p --format html --out /tmp/working-directory/rspec.html
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;できた。&lt;/p&gt;</description></item><item><title>seed_dumpを使ったRSpec高速化にはsequenceのリセットが必要だった</title><link>https://blog.piyo.tech/posts/2018-08-22-fix-seed-dump-script/</link><pubDate>Wed, 22 Aug 2018 06:01:29 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-22-fix-seed-dump-script/</guid><description>&lt;p&gt;先日書いたこれが動かなくなってしまい、よく調べていたらプライマリキー（つまりid）が被って追加できないよってことになってしまったみたいです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-08-16-test-date-with-seed-dump/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/8w8SfiZTtrOc7c9P0cf7ls6oc5TOlZuwE2Ul37hLWPnFwfi06xbi3eFTgRqdkiisVaD_ucG1GK_HGw1gu3nQ1fMh2vZGGUOeAXDlPItU5n8wWtXKfJJ3zKLk2Qsl-ZVBsSajiH2zck2iXseLGjg9_CiP1yGUc2S6NvlSgpFHjDxfoGBEfwUYmJ3HO3SEviF89bh7ojIsmEoSYWKHB1VpADGgCEUt9K1zRpJtjKkr-uPYL7UBPwVjIzYYDR0OKBRIGpXqLqF8TUVU-GuprPoUcbGDBzxsMcXECzeEiCDRF60EsXxRRFUe4NvX1t_o2Z9CGZn_aTkuj_pinFzDKjc8gWs7xPt98icrJmU3ICir4a9L4kap68g-s8Jrsvkwsqnd_ePLHtWxsckV6luCpgahhlke4osGyByoxCw5DeOgdehn1vpQe8FOgmqZ17P6s-1Y2o_SzrQg_0FnfpnkeWR14pO05F3SV0CEt3lRzuZC3jhvWpXiFtqaQ9Vdm00z0jurQjoNSRtQM_dwlg7GhNMfVgJMCB9xxWR7ATltJEl8p3SEBYgLc8OeKImVx_vQO2MFAU4jU5-oseegi_ZN4PvJLFYfTn4wTSAgB88hg8uKPwUDOnN4nnwr7-HeqcPHeFW2_phfh6iURRliFbRLUpnB_p3QKPM-NuWk66UZQ437abS84_uBm7lu3EDyNQ=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;seed_dumpを使ってRailsのテストデータの読み込みを高速化した - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;そこそこ複雑なデータを持たないとフィーチャテストを動かせないようなプロジェクトがありまして、きちんとしたデータを作るためにはCSVファイルからデータを取り込んでリレーション作るという必要がありました。 テストケースによってはこれを使わないこともありますが、全体の40%程度はこのデータがないとうまくいかないので、それぞれのテストの前に取り込み処理が入るります。これにより全体を流すのにめちゃくちゃ時間がかかっていました。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;確かに、関連を維持するためにidも含めてテストデータを登録していますので、sequenceの値がおかしくなっていた可能性があります。&lt;/p&gt;
&lt;p&gt;そこで、&lt;code&gt;seed.rb&lt;/code&gt;の最後に関連するテーブルに対して&lt;code&gt;reset_pk_sequence!&lt;/code&gt;を呼ぶことでこの問題に対応しました。&lt;code&gt;reset_pk_sequence!&lt;/code&gt;はDBがpostgresのときに使えます。&lt;/p&gt;
&lt;p&gt;前回の&lt;code&gt;Parent&lt;/code&gt;、&lt;code&gt;Child&lt;/code&gt;の例をそのまま使うとすると、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;klasses &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Parent&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;Child&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;klasses&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;klass&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ApplicationRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;connection&lt;span style="color:#f92672"&gt;.&lt;/span&gt;reset_pk_sequence!(klass&lt;span style="color:#f92672"&gt;.&lt;/span&gt;table_name)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とすればOKです。&lt;/p&gt;</description></item><item><title>Capybaraで別タブで開いたWindowを閉じる</title><link>https://blog.piyo.tech/posts/2018-08-21-capybara-close-new-window/</link><pubDate>Tue, 21 Aug 2018 06:26:40 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-21-capybara-close-new-window/</guid><description>&lt;p&gt;利用規約を確認しないとチェックボックスにチェックできないみたいな仕組みを簡易で作りまして、それのテストを書くときにちょっと迷ったので残しときます。&lt;/p&gt;
&lt;p&gt;利用規約のリンクを押すと別タブで規約ページが開くと同時にチェックボックスのdisabledが外れる仕組みになっているとします。&lt;/p&gt;
&lt;p&gt;テストでは&lt;code&gt;click_link '利用規約'&lt;/code&gt;とすると別ウィンドウ（別タブ）が開いてしまい、そのままではチェックボックスを操作できません。新しく開いたウィンドウを閉じてあげなければいけません。&lt;/p&gt;
&lt;p&gt;そこで↓のようにします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;window &lt;span style="color:#f92672"&gt;=&lt;/span&gt; window_opened_by { click_link &lt;span style="color:#e6db74"&gt;&amp;#39;利用規約&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;window&lt;span style="color:#f92672"&gt;.&lt;/span&gt;close
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;check &lt;span style="color:#e6db74"&gt;&amp;#39;terms_of_use&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Windowを保持できるので、それを&lt;code&gt;close&lt;/code&gt;するだけ。そしたら元にWindowに戻った扱いになるので、あとは普通にテストを書けばOKです。&lt;/p&gt;</description></item><item><title>身近で見たデバッグが得意じゃない人の特徴</title><link>https://blog.piyo.tech/posts/2018-08-20-how-to-debug/</link><pubDate>Mon, 20 Aug 2018 06:24:08 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-20-how-to-debug/</guid><description>&lt;p&gt;身近で何人か見た例を整理してみる（誰か1人の話ではないです）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;エラーメッセージ自体は読む&lt;/li&gt;
&lt;li&gt;エラーメッセージでググったりする&lt;/li&gt;
&lt;li&gt;エラーメッセージから発生箇所を推定できない
&lt;ul&gt;
&lt;li&gt;例えば&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JSのcannot read property 'xxxx' of undefined&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Rubyのundefined method 'xxxx' for nil:NilClass&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;xxxxを呼んでる箇所が怪しいと気づかない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ブレークポイントを置いてデバッグしないこともない&lt;/li&gt;
&lt;li&gt;渡ってきているパラメータを疑わない&lt;/li&gt;
&lt;li&gt;スタックトレースを見ない&lt;/li&gt;
&lt;li&gt;DevツールのNetworkタブを見ない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;うーん、あんまり抽象化できないな。デバッグできない人がデバッグできるようになるために何をしたらいいかを言語化したいです。&lt;/p&gt;
&lt;p&gt;僕がやるのは、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;前提
&lt;ul&gt;
&lt;li&gt;怪しい箇所を二分探索で絞り込んでいく&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;方法
&lt;ul&gt;
&lt;li&gt;ログを置く（&lt;code&gt;console.log&lt;/code&gt;, &lt;code&gt;Rails.logger&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;ブレークポイントを置く（&lt;code&gt;debugger&lt;/code&gt;, &lt;code&gt;binding.pry&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;フロントエンドの場合はNetworkタブを見る&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;見る箇所
&lt;ul&gt;
&lt;li&gt;オブジェクトの状態が想定通りかを見る&lt;/li&gt;
&lt;li&gt;受け取った引数やパラメータが想定通りかを見る&lt;/li&gt;
&lt;li&gt;渡す引数やパラメータを見る&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;怪しい箇所の絞り込みが大事です。少しずつ狭めていくとおのずと原因がわかってくるものだし、デバッグはいずれ勝てる勝負なので根気よく攻めていくのが大事じゃなかろうかと。慣れたらアタリをつけられるようになりますが。&lt;/p&gt;
&lt;p&gt;デバッグ苦手な人はエラーが出た→色々調べる、みたいになりがちなのでは？と思いました。&lt;/p&gt;</description></item><item><title>Bootstrap3をwebpackerで使うときにハマったこと</title><link>https://blog.piyo.tech/posts/2018-08-19-bootstrap3-on-webpacker/</link><pubDate>Sun, 19 Aug 2018 06:47:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-19-bootstrap3-on-webpacker/</guid><description>&lt;p&gt;個人のRailsアプリケーションをwebpacker化する際、BootstrapのCSSをwebpackerでimportしようとして少しだけハマったので共有します。&lt;/p&gt;
&lt;p&gt;そもそも、&lt;code&gt;yarn add bootstrap&lt;/code&gt;とするとBootstrap4系がインストールされますし、&lt;code&gt;yarn add bootstrap@3&lt;/code&gt;としてバージョン3系を入れようとすると、SASSではなくLESSのBootstrapがインストールされます。バージョン3系は確かにLESSでしたね。&lt;/p&gt;
&lt;p&gt;このRailsプロジェクトではSASSを使っていたので、&lt;code&gt;yarn add bootstrap-sass@3&lt;/code&gt;として、SASSポート版のBootstrap3を入れました。&lt;/p&gt;
&lt;p&gt;そしてこれをimportするわけです。&lt;/p&gt;
&lt;p&gt;JS側は比較的単純で、↓でOK。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// application.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;bootstrap-sass/assets/javascripts/bootstrap.js&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;CSS側は↓のようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sass" data-lang="sass"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;~bootstrap-sass/assets/stylesheets/bootstrap&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;が、ここでWebpackerが↓のようなコンパイルエラーを吐きます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; Module not found: Error: Can&amp;#39;t resolve &amp;#39;../fonts/bootstrap/glyphicons-halflings-regular.woff2&amp;#39; in &amp;#39;/Users/..(中略)../app/javascript/styles&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;どうやらフォントファイルが見つからない、とのこと。&lt;/p&gt;
&lt;p&gt;ソースコードでいうとここ（↓）のあたりで参照している箇所がまずそうに見えます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/twbs/bootstrap-sass/blob/master/assets/stylesheets/bootstrap/_glyphicons.scss" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/ba0b4c8f45ba62bbeb99d08fb43708d423c76f57ccbd9af126757c3e9a61f234/twbs/bootstrap-sass" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;bootstrap-sass/assets/stylesheets/bootstrap/_glyphicons.scss at master · twbs/bootstrap-sass&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Official Sass port of Bootstrap 2 and 3. Contribute to twbs/bootstrap-sass development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ソースコードを見る限り&lt;code&gt;$icon-font-path&lt;/code&gt;をメンテすれば良いはずです。実際、sprocketsでインポートするときもパスの指定をしていましたし、READMEにも書いてあります。&lt;/p&gt;
&lt;p&gt;今回は&lt;code&gt;node_modules&lt;/code&gt;以下から探すようにしたいので、&lt;code&gt;~&lt;/code&gt;を使うように&lt;code&gt;$icon-font-path&lt;/code&gt;を定義すれば良いわけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sass" data-lang="sass"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$icon-font-path&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;~bootstrap-sass/assets/fonts/bootstrap/&amp;#34;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;~bootstrap-sass/assets/stylesheets/bootstrap&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;@import&lt;/code&gt;の前に書けばOKです。&lt;/p&gt;</description></item><item><title>Rails5.0系の個人プロジェクトをアップグレードしてWebpackerを使うまでにやったこと</title><link>https://blog.piyo.tech/posts/2018-08-18-upgrade-personal-project/</link><pubDate>Sat, 18 Aug 2018 06:21:12 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-18-upgrade-personal-project/</guid><description>&lt;p&gt;個人プロジェクトを最新のRailsアップグレードして、Webpackerを使えるところまでやりました。自分への覚書の意味もこめて。&lt;/p&gt;
&lt;h2 id="railsを52までアップグレードする"&gt;Railsを5.2までアップグレードする&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Rails以外のgemをupdateしておく&lt;/li&gt;
&lt;li&gt;Rails 5.1にアップグレード
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bin/rails app:update&lt;/code&gt;する&lt;/li&gt;
&lt;li&gt;差分を調整する&lt;/li&gt;
&lt;li&gt;new_framework_defaultsあたりも注意する&lt;/li&gt;
&lt;li&gt;軽く動かして警告などに対応する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Rails 5.2にアップグレード
&lt;ul&gt;
&lt;li&gt;手順は5.1と一緒&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="まずはyarnを使う"&gt;まずはyarnを使う&lt;/h2&gt;
&lt;p&gt;gemやrails-assetsで追加していたJSライブラリやCSSなどをyarnで管理するように変更します。この時点ではwebpackerを使いません。&lt;/p&gt;
&lt;p&gt;手順はほぼこれです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-08-05-rails-yarn/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/8w8SfiZTtrOc7c9P0cf7ls6oc5TOlZuwE2Ul37hLWPnFwfi06xbi3eFTgRqdkiisVaD_ucG1GK_HGw1gu3nQ1fMh2vZGGUOeAXDlPItU5n8wWtXKfJJ3zKLk2Qsl-ZVBsSajiH2zck2iXseLGjg9_CiP1yGUc2S6NvlSgpFHjDxfoGBEfwUYmJ3HO3SEviF89bh7ojIsmEoSYWKHB1VpADGgCEUt9K1zRpJtjKkr-uPYL7UBPwVjIzYYDR0OKBRIGpXqLqF8TUVU-GuprPoUcbGDBzxsMcXECzeEiCDRF60EsXxRRFUe4NvX1t_o2Z9CGZn_aTkuj_pinFzDKjc8gWs7xPt98icrJmU3ICir4a9L4kap68g-s8Jrsvkwsqnd_ePLHtWxsckV6luCpgahhlke4osGyByoxCw5DeOgdehn1vpQe8FOgmqZ17P6s-1Y2o_SzrQg_0FnfpnkeWR14pO05F3SV0CEt3lRzuZC3jhvWpXiFtqaQ9Vdm00z0jurQjoNSRtQM_dwlg7GhNMfVgJMCB9xxWR7ATltJEl8p3SEBYgLc8OeKImVx_vQO2MFAU4jU5-oseegi_ZN4PvJLFYfTn4wTSAgB88hg8uKPwUDOnN4nnwr7-HeqcPHeFW2_phfh6iURRliFbRLUpnB_p3QKPM-NuWk66UZQ437abS84_uBm7lu3EDyNQ=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;遅まきながらRails5の頃に作ったプロジェクトをyarn化する（webpacker無し） - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Rails5の頃に作ったプロジェクトで、JS系のアセットの管理には Rails Assets を使っている、Rails 5.1のプロジェクトが手元にありました。 先日（8/3）にそのRails Assetsが証明書の期限切れでbundle installできなくなるという問題が発生。これを期に管理方法を変えないとねということで、Rails 5.1から使えるYarnを使うことにしました。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;できるだけ全部yarn側に持っていくことをおすすめします。jqueryとかbootstrapとかもです。webpacker化しちゃってから対応すると面倒だった記憶があります（一度やった）。&lt;/p&gt;
&lt;p&gt;また、この時点でメンテされていないライブラリがあったら実装を置き換えておくのがいいかもしれません。今回対応したプロジェクトではcolorpicker系のライブラリを置き換えました。&lt;/p&gt;
&lt;p&gt;Railsのヘルパー系とJSを一緒に提供するようなgemはyarn管理に持っていけないので、それはwebpacker管理に変更したのちに個別に対応しました（後述）。&lt;/p&gt;
&lt;h2 id="webpackerのインストール"&gt;webpackerのインストール&lt;/h2&gt;
&lt;p&gt;いよいよwebpackerを入れますが、ここではあまり欲張らず既存のcoffeeスクリプトをそのまま活かす形にしました。JSへ変換するスクリプトなんかを使うとなかなか大変そうだということがわかったので（これも一度やりました）。&lt;/p&gt;
&lt;p&gt;Gemfileに&lt;code&gt;gem 'webpacker'&lt;/code&gt;を追記して、&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% bundle install
% rails webpacker:install
% rails webpacker:install:erb # erbとして読むため
% rails webpacker:install:coffee # coffeeを読めるようにするため
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="jsを移動"&gt;JSを移動&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;app/assets/javascripts&lt;/code&gt;にあったcoffeeスクリプトのファイルを新しくできた&lt;code&gt;app/javascript/packs/&lt;/code&gt;以下のフォルダへ移動します。&lt;code&gt;packs&lt;/code&gt;配下に直接置くとエントリポイントになっちゃうので一つ階層を置くと良さそうです。&lt;code&gt;pages&lt;/code&gt;などとしてその下に置きます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;packs/application.js&lt;/code&gt;は&lt;code&gt;packs/application.js.erb&lt;/code&gt;とリネームしました。これはRails管理のJSをimportするためです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-08-11-gem-with-js-on-webpacker/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/8w8SfiZTtrOc7c9P0cf7ls6oc5TOlZuwE2Ul37hLWPnFwfi06xbi3eFTgRqdkiisVaD_ucG1GK_HGw1gu3nQ1fMh2vZGGUOeAXDlPItU5n8wWtXKfJJ3zKLk2Qsl-ZVBsSajiH2zck2iXseLGjg9_CiP1yGUc2S6NvlSgpFHjDxfoGBEfwUYmJ3HO3SEviF89bh7ojIsmEoSYWKHB1VpADGgCEUt9K1zRpJtjKkr-uPYL7UBPwVjIzYYDR0OKBRIGpXqLqF8TUVU-GuprPoUcbGDBzxsMcXECzeEiCDRF60EsXxRRFUe4NvX1t_o2Z9CGZn_aTkuj_pinFzDKjc8gWs7xPt98icrJmU3ICir4a9L4kap68g-s8Jrsvkwsqnd_ePLHtWxsckV6luCpgahhlke4osGyByoxCw5DeOgdehn1vpQe8FOgmqZ17P6s-1Y2o_SzrQg_0FnfpnkeWR14pO05F3SV0CEt3lRzuZC3jhvWpXiFtqaQ9Vdm00z0jurQjoNSRtQM_dwlg7GhNMfVgJMCB9xxWR7ATltJEl8p3SEBYgLc8OeKImVx_vQO2MFAU4jU5-oseegi_ZN4PvJLFYfTn4wTSAgB88hg8uKPwUDOnN4nnwr7-HeqcPHeFW2_phfh6iURRliFbRLUpnB_p3QKPM-NuWk66UZQ437abS84_uBm7lu3EDyNQ=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;gemが持ってるJSをwebpackerで読み込むには - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;手持ちのレガシー目なRails案件をいい加減Webpackerに直す活動を始めていまして、まずは仕事以外のプロジェクトからやってます。 JS用のgemだったりrails-assetsあたりはyarn化の時点でだいたい撲滅できていいですね。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;application.js.erb&lt;/code&gt;は例えば以下のようになるかと思います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// packs/application.js.erb
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;jQuery&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;jquery/dist/jquery&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;window.&lt;span style="color:#a6e22e"&gt;jQuery&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;jQuery&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;window.&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;jQuery&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;jquery-ujs/src/rails.js&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;bootstrap-sass/assets/javascripts/bootstrap.js&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;%= File.join(Gem.loaded_specs[&amp;#39;cocoon&amp;#39;].full_gem_path, &amp;#39;app&amp;#39;, &amp;#39;assets&amp;#39;, &amp;#39;javascripts&amp;#39;, &amp;#39;cocoon.js&amp;#39;) %&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./pages/items.js.coffee&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./pages/map.js.coffee&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;従来の&lt;code&gt;application.js&lt;/code&gt;で書いていたような&lt;code&gt;require jquery&lt;/code&gt;のような部分をimportに変えつつ、先程移動したcoffeeスクリプトも相対パス指定で直接書いていきます。globを使うような方法もありそうでしたが、今回は数が少なかったので調べませんでした。&lt;/p&gt;
&lt;p&gt;あとはView側の&lt;code&gt;javascript_include_tag&lt;/code&gt;を&lt;code&gt;javascript_pack_tag&lt;/code&gt;と変更すればOK。ここで動作確認をしておくと良いです。&lt;/p&gt;
&lt;p&gt;ちなみにjqueryは他のライブラリからグローバルに参照されることが多かったり、自身のView側のJSのコードでもそのように書いていることがあり得るので最初の3行のようにして参照できるようにしています。&lt;/p&gt;
&lt;h2 id="cssもwebpacker"&gt;CSSもwebpacker&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;packs/application.js.erb&lt;/code&gt;でsassをimportするとそれもコンパイルされ、application.cssとして参照されるようになります。なので、CSSもこちらに移動しましょう。手順はほぼ一緒ですが、importの書き方に工夫が要ります。&lt;/p&gt;
&lt;p&gt;まずapplication.jsに以下を追記&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;import &amp;#39;../styles/application.sass&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;packsと同じ階層に&lt;code&gt;styles&lt;/code&gt;ディレクトリを作ってそこに&lt;code&gt;application.sass&lt;/code&gt;というファイルを配置。&lt;/p&gt;
&lt;p&gt;中身はこんな感じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sass" data-lang="sass"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;~bootstrap-datepicker/dist/css/bootstrap-datepicker3&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;~toastr/toastr.scss&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;common&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;yarn管理のライブラリには&lt;code&gt;~&lt;/code&gt;をつける必要があります。これをつけるとnode_modulesからのパスになるようです。&lt;/p&gt;
&lt;p&gt;あとは、&lt;code&gt;stylesheet_link_tag&lt;/code&gt;を&lt;code&gt;stylesheet_pack_tag&lt;/code&gt;に変更すればOKのはずです。&lt;/p&gt;
&lt;p&gt;ちなみにここでハマったのは&lt;code&gt;sass&lt;/code&gt;ファイルに凡ミスがあってコンパイルエラーになったときに、エラーメッセージにはcssファイルがないよ、としか表示されなくて原因がわからなくて困ったというやつです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;public/packs&lt;/code&gt;配下にも&lt;code&gt;application.css&lt;/code&gt;が書き出されていなくて設定ミスかな？なんて思っていたんですが、&lt;code&gt;webpack-dev-server&lt;/code&gt;を動かしてみたら&lt;code&gt;sass&lt;/code&gt;側にエラーがあったというオチでした。&lt;/p&gt;
&lt;h1 id="終わり"&gt;終わり&lt;/h1&gt;
&lt;p&gt;ここまででひとまずsprocketsを使わないようにできたのではないかと思います。本当はちゃんと新しいJSでかけるようにしたり、coffeeスクリプトをやめたり、ESLintをかけられるようにしたりとモダンにしていきたいところ。&lt;/p&gt;</description></item><item><title>ブログの細かい見た目を微調整しました</title><link>https://blog.piyo.tech/posts/2018-08-17-blog-design-fix/</link><pubDate>Fri, 17 Aug 2018 06:57:34 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-17-blog-design-fix/</guid><description>&lt;p&gt;ごちゃっとしていてなんとなく気に入らなかった当ブログの見た目をちょっとだけ調整しました。&lt;/p&gt;
&lt;h1 id="before"&gt;Before&lt;/h1&gt;
&lt;p&gt;Beforeはメイン部分とサイドバーの2カラムレイアウトでした。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/fadAMMpgkfIrPszDc4P4wTt7lTn5tBHVgBBtK9rOXGA8XqWEtkKLpJwklgDjZsbZNtnc3pLYzp4JK5Q6315LvbbjZbg2Zr9yjwxrif1SmEhVNDWmnfLqjd16DXWc2sE29SFrr5_5DuooXiNYSV3SQgqz4YfPBzNgI1BfqZI79R5NOZ7DV-82nFcfnQrJYz3TGMCGKnig3gQvbd3YaedceuDDBRiESLCqC95dwg0LwebjOD5lYmwKke-iJHMcN1OauI0ieBNBtymavWv5qWRpNVxvYURZCpiS-4AZ8g05gpI2oku7XNOu695_E9sJazLoEPCcl70QEXwNrvmgwYjk8O7VoS5PkGZMhpMCkXMw4cAhtYgrdbrI4xTosW1ktCUa-0CfmQhZu1XSHSuqjatmXpYxhFY8hq0omPts2ty_d6oJmUovhgcqMrvhMZTiGWnjy6AQmj1S3sKeDYBU0IDPllZ9GyRpgr96VXvTno_-1NBXmzhm1yD0tScVjPEFKGnins-NwVhMQNSGl0TpR9DVbL_GwFFMFtHsrP_Y4k7QginiNFSJ_iFYQ96Falj1kg4LY1-NIVwxQbAY-9JvHcTr4c5zE3ntBLt5q91ZovpHf3-RSIkNPd46mVgwz0U0opHmKNALUWrwAgXjHqMEouv5H1dbe0Akz56hxg=w2246-h1796-no"&gt;&lt;img src="https://lh3.googleusercontent.com/fadAMMpgkfIrPszDc4P4wTt7lTn5tBHVgBBtK9rOXGA8XqWEtkKLpJwklgDjZsbZNtnc3pLYzp4JK5Q6315LvbbjZbg2Zr9yjwxrif1SmEhVNDWmnfLqjd16DXWc2sE29SFrr5_5DuooXiNYSV3SQgqz4YfPBzNgI1BfqZI79R5NOZ7DV-82nFcfnQrJYz3TGMCGKnig3gQvbd3YaedceuDDBRiESLCqC95dwg0LwebjOD5lYmwKke-iJHMcN1OauI0ieBNBtymavWv5qWRpNVxvYURZCpiS-4AZ8g05gpI2oku7XNOu695_E9sJazLoEPCcl70QEXwNrvmgwYjk8O7VoS5PkGZMhpMCkXMw4cAhtYgrdbrI4xTosW1ktCUa-0CfmQhZu1XSHSuqjatmXpYxhFY8hq0omPts2ty_d6oJmUovhgcqMrvhMZTiGWnjy6AQmj1S3sKeDYBU0IDPllZ9GyRpgr96VXvTno_-1NBXmzhm1yD0tScVjPEFKGnins-NwVhMQNSGl0TpR9DVbL_GwFFMFtHsrP_Y4k7QginiNFSJ_iFYQ96Falj1kg4LY1-NIVwxQbAY-9JvHcTr4c5zE3ntBLt5q91ZovpHf3-RSIkNPd46mVgwz0U0opHmKNALUWrwAgXjHqMEouv5H1dbe0Akz56hxg=w2246-h1796-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ちょっと詰めすぎではなかったかなと思い、縦に並べることにしました。例えばサイドバーのPOPULARの部分なんかはちょっと文字を小さくしすぎだったかなと思います。&lt;/p&gt;
&lt;h1 id="after"&gt;After&lt;/h1&gt;
&lt;p&gt;こちらがAfterです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/KMMm-w2-QgnD1YCXQIjxkZrNIJMF4zkZXV1ZFqnJjNRG-D5aoc-SST9jySCZnNEAun7EOBSThHrHetAh1FaQoh-7TWMvQWAwHJEh7YPULib2XRaE7civXkNa9L0G4fw8RzwWRjjJWBYcnLk3n7x1VYG-zdMTDwFwi1HiZwutAqBSxPeKUJf6v6ix4uaNSBlOYpjkdHVmxx5fF6UtzJvYN-OBLpbRD0PTHp6FQNid1yNS4JkjSiUd3uNxdBveF0eDZ_o-FtLr_SqO5XL-z5GMw-eTKnGI2uomQr5TMbeYwbr7ud1zTreM7ujGdk1gA8SxoZ0TlngjlrvXYiqrjm1j6i8EAphyGh5ENkar0ZxqozD_dUi5SrC-gzUP1Qvy6569J9-DLbYijwPCk7HuQ7JpYQhqKndrk4Ybdw9xn4mZu5A2eNODg_P99B73UXFWwjqEGudQPke7-vMP113Sh48litVjaPYystGn-q4101cBBlm5DLsL58sY1CrZYZ1nlD8YWmPUsDGPTSasm6T6h0CwaH4rhrF1Js7hYsJjKBWAgLn3zHas9aai0aTVwSQXmkgz-a27xfuEhlFS8W0c8VLOaixLyB6bEoCuRrbXitqpzp7-nq2TSe2-Z-PBvj_01j0bv3-5cCOlDhiwio9mdTCslUVf6P-g0mMGMQ=w420-h335-no"&gt;&lt;img src="https://lh3.googleusercontent.com/KMMm-w2-QgnD1YCXQIjxkZrNIJMF4zkZXV1ZFqnJjNRG-D5aoc-SST9jySCZnNEAun7EOBSThHrHetAh1FaQoh-7TWMvQWAwHJEh7YPULib2XRaE7civXkNa9L0G4fw8RzwWRjjJWBYcnLk3n7x1VYG-zdMTDwFwi1HiZwutAqBSxPeKUJf6v6ix4uaNSBlOYpjkdHVmxx5fF6UtzJvYN-OBLpbRD0PTHp6FQNid1yNS4JkjSiUd3uNxdBveF0eDZ_o-FtLr_SqO5XL-z5GMw-eTKnGI2uomQr5TMbeYwbr7ud1zTreM7ujGdk1gA8SxoZ0TlngjlrvXYiqrjm1j6i8EAphyGh5ENkar0ZxqozD_dUi5SrC-gzUP1Qvy6569J9-DLbYijwPCk7HuQ7JpYQhqKndrk4Ybdw9xn4mZu5A2eNODg_P99B73UXFWwjqEGudQPke7-vMP113Sh48litVjaPYystGn-q4101cBBlm5DLsL58sY1CrZYZ1nlD8YWmPUsDGPTSasm6T6h0CwaH4rhrF1Js7hYsJjKBWAgLn3zHas9aai0aTVwSQXmkgz-a27xfuEhlFS8W0c8VLOaixLyB6bEoCuRrbXitqpzp7-nq2TSe2-Z-PBvj_01j0bv3-5cCOlDhiwio9mdTCslUVf6P-g0mMGMQ=w420-h335-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;スペースができた分関連記事などの要素を少し広げられたので、狭い領域に文字が入るように小さくしていたフォントサイズを大きくしたり余白を取ったりすることができました。&lt;/p&gt;
&lt;p&gt;そして、ヘッダー部分の下に2色の帯を入れてみました。これはほんとに適当で、僕の好きなスペインのVALENCIA C.F. のイメージカラーを入れてみようという感じです。帯に揃える形で全体的なイメージを暖色系としました。元々はどちらかというと青系というの色が多かったし、若干青が強いグレーが使われていましたね。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/jI9QPjXIo7IpcbTodeGltsq8eYn_zHg9jCWN6MXA2sf7WODEL-tDwggu_l_c6ItY-3Vj64fhhI13_fsMcdR5FvsZiu_Z0bV005aFAa368454jAp9jXUCJU0g5I70-L0or9R_LcpJ8FpuS2E3-gNXcXjchlvvnWvLcIMpyA8KrmTY981wFW1kjTrFjZkNr0k2CTgQYm-JwbMVeipStZVaNGF4q0wA9gjF27nd4bgPrIu-S-ytD8CS8nMuKG5KhHWSZfhS8y8lcplUYALLqVBZgtGsgQATMA1VGOLSSSIojSirg-XvVUu9kNY_EPHXWUCtGbiXHjUHAvXzT_fFyQtXxVq7-TmNwOC8k7Pjnfq_uklTxNeF7CBk6IX4kEsMnmdliqoFMuQB9ui_hp9__fUKRGfglO537k2FJxiln2NpsM8JJS5FN3lmjBj41JN3Azh9k5jFOj7_ez5ma_TQd-uQ-H6oE2MNtUzsM4YHeVIr0-tCQDhtVB_fQfR1NCWycno6ayiL0wBBTGWdt129Zj6GFalQ869kfhi_YGA46OulFsyjjVxevnxfuEs6tKwx2NalQswWYUq4XCMFyRi2sjgjxY7l7v1W0Q0wNR2izcJDrBmJNKv1x9u4WlJwNsKhrnPHd-9MNtP-T_raiLSKttAPGAiar_9xGFft_g=w1980-h1556-no"&gt;&lt;img src="https://lh3.googleusercontent.com/jI9QPjXIo7IpcbTodeGltsq8eYn_zHg9jCWN6MXA2sf7WODEL-tDwggu_l_c6ItY-3Vj64fhhI13_fsMcdR5FvsZiu_Z0bV005aFAa368454jAp9jXUCJU0g5I70-L0or9R_LcpJ8FpuS2E3-gNXcXjchlvvnWvLcIMpyA8KrmTY981wFW1kjTrFjZkNr0k2CTgQYm-JwbMVeipStZVaNGF4q0wA9gjF27nd4bgPrIu-S-ytD8CS8nMuKG5KhHWSZfhS8y8lcplUYALLqVBZgtGsgQATMA1VGOLSSSIojSirg-XvVUu9kNY_EPHXWUCtGbiXHjUHAvXzT_fFyQtXxVq7-TmNwOC8k7Pjnfq_uklTxNeF7CBk6IX4kEsMnmdliqoFMuQB9ui_hp9__fUKRGfglO537k2FJxiln2NpsM8JJS5FN3lmjBj41JN3Azh9k5jFOj7_ez5ma_TQd-uQ-H6oE2MNtUzsM4YHeVIr0-tCQDhtVB_fQfR1NCWycno6ayiL0wBBTGWdt129Zj6GFalQ869kfhi_YGA46OulFsyjjVxevnxfuEs6tKwx2NalQswWYUq4XCMFyRi2sjgjxY7l7v1W0Q0wNR2izcJDrBmJNKv1x9u4WlJwNsKhrnPHd-9MNtP-T_raiLSKttAPGAiar_9xGFft_g=w1980-h1556-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;POPULARの箇所も余白ができたり文字が大きくなったりして見やすくなったのではないかと思います。&lt;/p&gt;
&lt;p&gt;本当はもっと手を入れたいですが、自分でできる範囲では少しはよくなったかなー。&lt;/p&gt;</description></item><item><title>seed_dumpを使ってRailsのテストデータの読み込みを高速化した</title><link>https://blog.piyo.tech/posts/2018-08-16-test-date-with-seed-dump/</link><pubDate>Thu, 16 Aug 2018 06:09:32 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-16-test-date-with-seed-dump/</guid><description>&lt;p&gt;そこそこ複雑なデータを持たないとフィーチャテストを動かせないようなプロジェクトがありまして、きちんとしたデータを作るためにはCSVファイルからデータを取り込んでリレーション作るという必要がありました。&lt;/p&gt;
&lt;p&gt;テストケースによってはこれを使わないこともありますが、全体の40%程度はこのデータがないとうまくいかないので、それぞれのテストの前に取り込み処理が入るります。これにより全体を流すのにめちゃくちゃ時間がかかっていました。&lt;/p&gt;
&lt;p&gt;といっても数十分程度なので多少目をつぶってこれまではやり過ごしてきました。&lt;/p&gt;
&lt;p&gt;このたび、重い腰をあげて対応策を考えましたので記しておきます。といっても↓の記事を大いに参考にして実施したので、こちらの記事に感謝します。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://milk1000cc.hatenablog.com/entry/2016/11/20/141641" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://ogimage.blog.st-hatena.com/13208692334729896050/10328749687195176022/1479619001" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;実際の DB データをテストで使用する - milk1000cc&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Rails で開発していると、実際に使っている DB のデータを、テストで使用したい場合があります。 そのような場合、seed_dump と activerecord-import を使ってうまく実現することができました。 Gemfile group :development do gem &amp;#39;seed_dump&amp;#39; end group :test do gem &amp;#39;activerecord-import&amp;#39; end 使わない環境では、gem を読み込まないようにします。 script/dump_models.rb DUMPED_MODELS = [Site, Category, SubCategor…&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://milk1000cc.hatenablog.com/icon/favicon" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;milk1000cc.hatenablog.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;こちらの記事で紹介されているのは&lt;a href="https://github.com/rroblak/seed_dump"&gt;seed_dump&lt;/a&gt; gemを使ってDBのデータを&lt;code&gt;activerecord-import&lt;/code&gt;の形式で書き出し、テストの必要な箇所で書き出したRubyのコードを実行するというとやり方です。大筋はこのやり方をとります。&lt;/p&gt;
&lt;p&gt;細かいところで工夫した箇所があるのでその点について紹介します。&lt;/p&gt;
&lt;h2 id="必要なデータだけのdbをつくる"&gt;必要なデータだけのDBをつくる&lt;/h2&gt;
&lt;p&gt;元々CSVインポート処理で取り込まれていたデータはごく一部なので、開発用に使っているデータが全て必要なわけではありません。
そこで新しいデータベースを用意してテスト用のデータのみを取り込んだあとで、そのデータベースに対して&lt;code&gt;seed_dump&lt;/code&gt;により書き出せばよいと考えました。&lt;/p&gt;
&lt;p&gt;ちなみに、テストコードでのインポート処理は、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;MyTestData&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;import!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;みたいに、ユーティリティクラスのメソッドを呼ぶだけとなっています。これを踏まえた上で、一時的なデータベースを作るために以下のようなことをしました。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;database.ymlを開き、developmentの&lt;code&gt;database&lt;/code&gt;名を&lt;code&gt;seed_tmp_dev&lt;/code&gt;みたいな適当な名前に変更する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rails db:create&lt;/code&gt;などでデータベースを作成&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rails db:migrate&lt;/code&gt;でマイグレーション&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rails console&lt;/code&gt;でコンソールに入る&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MyTestData.import!&lt;/code&gt;を実行&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;これで必要なデータだけが入った一時的なデータベースが完成しました。&lt;/p&gt;
&lt;h2 id="seed_dump時の工夫"&gt;seed_dump時の工夫&lt;/h2&gt;
&lt;p&gt;先程紹介した記事ではRubyスクリプトによりデータを出力していました。&lt;code&gt;seed_dump&lt;/code&gt;にはrakeタスクがありますので、今回はそちらを使いました。データベースにあるデータを全て書き出してくれればいいので、モデルの絞り込みは特にしませんでした。&lt;/p&gt;
&lt;p&gt;出力用のコマンドは次のようになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;% rake &lt;/span&gt; &lt;span style="color:#e6db74"&gt;db&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;seed&lt;/span&gt;:dump &lt;span style="color:#66d9ef"&gt;EXCLUDE&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;created_at,updated_at &lt;span style="color:#66d9ef"&gt;IMPORT&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FILE&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;spec&lt;span style="color:#f92672"&gt;/&lt;/span&gt;fixtures&lt;span style="color:#f92672"&gt;/&lt;/span&gt;seed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;rb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;記事と同様に以下のオプションを指定しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;EXCLUDE&lt;/code&gt; 除外カラム。関連のためidは出力対象です。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IMPORT&lt;/code&gt; activerecord-import対応の形式で書き出します。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FILE&lt;/code&gt; 出力先のファイルパスを指定しています。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;さて、このファイルを元記事のように&lt;code&gt;:seed&lt;/code&gt;タグ有りのときに読み込むようにして実施したところ、関連の外部キーでエラーになりました。&lt;/p&gt;
&lt;p&gt;出力されたファイルを見てみると、アルファベット順に処理が書かれています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Child&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;import(&lt;span style="color:#f92672"&gt;...&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Parent&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;import(&lt;span style="color:#f92672"&gt;...&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここでChildが外部キー&lt;code&gt;parent_id&lt;/code&gt;あたりでParentを参照していたりするとChildをimportするときにエラーとなります。本来は以下のような順番で取り込まれるべきです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# こうなっているべき&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Parent&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;import(&lt;span style="color:#f92672"&gt;...&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Child&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;import(&lt;span style="color:#f92672"&gt;...&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今回のプロジェクトの場合、関連するモデルが15程度あったのでそれぞれ親子関係をたどって出力されたファイルのコードを並び替える必要がありそうでした。&lt;/p&gt;
&lt;p&gt;ここで&lt;code&gt;seed_dump&lt;/code&gt;では対象のモデルを指定するやり方があることを思い出しました。rakeタスクの場合は&lt;code&gt;MODELS=&amp;quot;Parent, Child&amp;quot;&lt;/code&gt;のように指定可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;% rake &lt;/span&gt; &lt;span style="color:#e6db74"&gt;db&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;seed&lt;/span&gt;:dump &lt;span style="color:#66d9ef"&gt;MODELS&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Parent, Child&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;EXCLUDE&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;created_at,updated_at &lt;span style="color:#66d9ef"&gt;IMPORT&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FILE&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;spec&lt;span style="color:#f92672"&gt;/&lt;/span&gt;fixtures&lt;span style="color:#f92672"&gt;/&lt;/span&gt;seed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;rb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これを実行したところ&lt;code&gt;MODELS&lt;/code&gt;に指定した順番でコードが出力されており、望み通りにインポートできそうなところまでいきました。&lt;/p&gt;
&lt;h2 id="バリデーションの回避"&gt;バリデーションの回避&lt;/h2&gt;
&lt;p&gt;一部のモデルではデータベースのカラムの情報だけでは保存できないようなバリデーションがかかっているモデルがありました。&lt;/p&gt;
&lt;p&gt;そのため、出力されたファイルの&lt;code&gt;Parent.import(\[...\])&lt;/code&gt;のところに&lt;code&gt;validate: false&lt;/code&gt;オプションをつける必要がありました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# before&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Parent&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;import(&lt;span style="color:#f92672"&gt;[...]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# after&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Parent&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;import(&lt;span style="color:#f92672"&gt;[...]&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;validate&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この変更はエディタのマルチカーソル機能でがんばって変更しましたｗ&lt;/p&gt;
&lt;p&gt;ここまででようやく取り込めるようになりました。&lt;/p&gt;
&lt;h1 id="結果"&gt;結果&lt;/h1&gt;
&lt;p&gt;対象のテストを流してみたらこんな結果となりました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;変更前&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Finished in 41 minutes 15 seconds (files took 11.15 seconds to load)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;変更後&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Finished in 17 minutes 25 seconds (files took 11.13 seconds to load)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;41分→17分ということで、40%程度に短縮できました！&lt;/p&gt;</description></item><item><title>MacBook Proの設定を変えたら無事スリープ中に起きなくなった</title><link>https://blog.piyo.tech/posts/2018-08-15-mac-sleep-2/</link><pubDate>Wed, 15 Aug 2018 06:30:11 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-15-mac-sleep-2/</guid><description>&lt;p&gt;先日Macのスリープ中の挙動について設定変更だけ行いました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-08-12-mac-sleep/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/69CTPfvN1iLkTzPWPxjlM5I5Qx2zFp2jXKNpXo1xhlpjj_UFsNpsmaEUdh2GbWpaq1uanpYqIVIkjfm750JxrnSuRpO0hu1Gf2Q3Yeh74CAvl9KLcQku4ivBI7VWhBSFZOmfLECTWIXFWCXf46CKJ4cnI0XoxA3APG_SWvInSLpQcfITqYW_tG1xtPtdbyDicO7kcN1-OajxTcr4aQYE9a8UTncrngbafb9zSGTBbQAdwXexMr-hHkOGLraKJ9pVrQg73kOKb1Ahdf_b2cjvdHv21GJOf8AHh3w_fPKVFZciFZVXez4Ha1-gOEmLmV1ssHJavJ85ItbYM7M-SUFqUyt2D3lZ0zv-JR40byX_UiZTHIGZF787W7Mu9_CdARmGy-h7P1YLiZa3-FvuJDNwN_Cps2-PbQxYgquJG96jVMPbYPpGhTMLRBDJ_7Rb5H5sZSdCRUV40h91KIadmcR00i4ckguWMdfHf30k2g6UpqSCNhGLiJBRJULuKzTj0jBb_p_u-GTndNQQb5AAt75KE0dDPzTO7YfFT4IM3RjUuQ3wSvgajPw9xwt3W6qlxz7HibIEmzWkB1OXXcUYW0Tep3ycR27RQAf40vA8VTetbTOjdrw80IBEOtKShcRqdsYhAc8dV7UmdDIrA8Nou4j6aK-NYqNa0-CWz-FO0XVpPjLuOSvesjG_74JQ=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;MacBook Proがスリープ中に起きまくっているようなので設定を変えてみた - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;スリープ中のMacが熱くなる現象がずっと前からありました。Macの熱のせいで部屋が暑いし（夏だから）、本体もかなり熱いので心配です。 Macの挙動で気になっていたのでは、スリープしているにもかかわらず接続しているディスプレイからMacの復帰を認識したときのピッという音がなることです。だいたいFacebookメッセンジャーなどのメッセージを受信したタイミングで起こっていることがなんとなくわかっていたので、実はスリープ中もネットワークがつながっていて、通知のタイミングで起こすのかな？と思っていました。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;その後数日過ごしてみたところ無事スリープ中に熱くなったりファンが回ったりすることがなくなりまして、おそらく無事想定通りの挙動になっているのではないかと思います。&lt;/p&gt;
&lt;p&gt;毎朝アツアツのMacにびっくりすることはもうなさそうです。&lt;/p&gt;</description></item><item><title>Googleでカラーコードを検索するとカラーピッカーが使える</title><link>https://blog.piyo.tech/posts/2018-08-14-google-color-picker/</link><pubDate>Tue, 14 Aug 2018 06:21:34 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-14-google-color-picker/</guid><description>&lt;p&gt;Googleで16進数のカラーコードを検索したらこんなふうにカラーピッカーが現れました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/q2Ppv10GnknEjAuXNUZyPbWXM_Ib5zFIollulgqxUYViAf5S4LlhqZdw59zAfa9Kt2LIkWnGnaTj_t1fVfAaFdM8MsiKkMfoqObQH2T_aGinBtxqGfZIRPXM92TsUQqNqCbV5FKi5BTZc463UI1fukvJECtn6ST349qlgElnHxOPeN9D0WM5L08mcEJ_gBJ1oPr2hDv8GTKILjTj45_m0yjKoSqQgkBcKsz0xU9JVGMnQEyydbhVtlzFKbYWDAgfEj9Qpbk7Q_oCJxpt0E3sOXLo-Q1WdAjk3GkUhAnk7uw70_aDB8OGHWWdTgXTAfFewmK6ibeLetBtPEY__6yRykdtxPdTz8uCIahmAe95H6ocga4aIxSqLnUdOzDMGG5HE7APrTT_Izpiu8anQQhVThL2COFpVuxeTtJ6-vusSgU1qCeiSMD_jt7lNu8Fb7_z2WMTfaaTOhcL0RSTjNfYQKhdhE3MwbBQBfj9iWIyEJbQxEDng7sYWKhkMGsbGoexyxa7RI9-OnzLOa6wFNwVpLT4MVfcOX1xE0o-N9SM2MeBn9DSA5dxWBCH0rwyaSNpWBrwIUQbhdwOZdJvUJYaU1OnMnlG9xG6goPKxIVf6QZirlk16_lHESTw-OsuwZN-JvXdjaBiHfsqeJgc3XA0vbvCXNEqy4-u=w806-h674-no"&gt;&lt;img src="https://lh3.googleusercontent.com/q2Ppv10GnknEjAuXNUZyPbWXM_Ib5zFIollulgqxUYViAf5S4LlhqZdw59zAfa9Kt2LIkWnGnaTj_t1fVfAaFdM8MsiKkMfoqObQH2T_aGinBtxqGfZIRPXM92TsUQqNqCbV5FKi5BTZc463UI1fukvJECtn6ST349qlgElnHxOPeN9D0WM5L08mcEJ_gBJ1oPr2hDv8GTKILjTj45_m0yjKoSqQgkBcKsz0xU9JVGMnQEyydbhVtlzFKbYWDAgfEj9Qpbk7Q_oCJxpt0E3sOXLo-Q1WdAjk3GkUhAnk7uw70_aDB8OGHWWdTgXTAfFewmK6ibeLetBtPEY__6yRykdtxPdTz8uCIahmAe95H6ocga4aIxSqLnUdOzDMGG5HE7APrTT_Izpiu8anQQhVThL2COFpVuxeTtJ6-vusSgU1qCeiSMD_jt7lNu8Fb7_z2WMTfaaTOhcL0RSTjNfYQKhdhE3MwbBQBfj9iWIyEJbQxEDng7sYWKhkMGsbGoexyxa7RI9-OnzLOa6wFNwVpLT4MVfcOX1xE0o-N9SM2MeBn9DSA5dxWBCH0rwyaSNpWBrwIUQbhdwOZdJvUJYaU1OnMnlG9xG6goPKxIVf6QZirlk16_lHESTw-OsuwZN-JvXdjaBiHfsqeJgc3XA0vbvCXNEqy4-u=w806-h674-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;HEXやRGB表記などのいくつかの形式のコピペ用の文字列が用意されていて、色を選択するとその部分も変わるので簡易な表記変換方法としては便利じゃないかと思います。&lt;/p&gt;
&lt;p&gt;ちなみに、&lt;code&gt;rgb(r, g, b)&lt;/code&gt;形式で検索した場合にもこのカラーピッカーは表示されますが、それ以外のHSVやHSL、CMYKの形式で検索した場合にはピッカーは現れません。&lt;/p&gt;</description></item><item><title>今更input type=color の存在を知る</title><link>https://blog.piyo.tech/posts/2018-08-13-html-input-color/</link><pubDate>Mon, 13 Aug 2018 06:02:32 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-13-html-input-color/</guid><description>&lt;p&gt;HTML5のinput type=colorの存在を今の今まで知りませんでしたが、たまたま知りました。&lt;/p&gt;
&lt;p&gt;Webでカラーピッカー使ったことなくて、という言い訳だけしとこ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;input&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;color&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;で↓が出ます（Safariだと単なるInputに見えると思う）。&lt;/p&gt;
&lt;input type="color" /&gt;
&lt;p&gt;ちなみにRailsだと、&lt;code&gt;color_field&lt;/code&gt;が使えます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; form_for(object) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;f&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;color_field &lt;span style="color:#e6db74"&gt;:color&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;もしかして他にも知らないのあるのかも？と思ってMDNで調べてみました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Elements/input" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://developer.mozilla.org/mdn-social-image.46ac2375.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;: HTML 入力要素 - HTML | MDN&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;は HTML の要素で、ユーザーからデータを受け取るための、ウェブベースのフォーム用の操作可能なコントロールを作成するために使用します。端末とユーザーエージェントによりますが、広範に渡る種類のデータ入力やコントロールウィジェットが利用できます。 要素は入力型と属性の組み合わせの数が非常に多いため、HTML の中で最も強力かつ最も複雑な要素の一つです。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://developer.mozilla.org/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;developer.mozilla.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;全部で20ちょいのtypeがあるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;button&lt;/li&gt;
&lt;li&gt;checkbox&lt;/li&gt;
&lt;li&gt;color → 知った&lt;/li&gt;
&lt;li&gt;date&lt;/li&gt;
&lt;li&gt;datetime-local → 知らなかった&lt;/li&gt;
&lt;li&gt;email&lt;/li&gt;
&lt;li&gt;file&lt;/li&gt;
&lt;li&gt;hidden&lt;/li&gt;
&lt;li&gt;image&lt;/li&gt;
&lt;li&gt;month → 知らなかった&lt;/li&gt;
&lt;li&gt;number&lt;/li&gt;
&lt;li&gt;password&lt;/li&gt;
&lt;li&gt;radio&lt;/li&gt;
&lt;li&gt;range → 知らなかった&lt;/li&gt;
&lt;li&gt;reset → 知らなかった&lt;/li&gt;
&lt;li&gt;search&lt;/li&gt;
&lt;li&gt;submit&lt;/li&gt;
&lt;li&gt;tel&lt;/li&gt;
&lt;li&gt;text&lt;/li&gt;
&lt;li&gt;time&lt;/li&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;li&gt;week → 知らなかった&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;知らないのが5つありました。colorを含めると6つですね。&lt;/p&gt;
&lt;p&gt;このうちcolorとrangeあたりは使うタイミングがありそうなので、よく覚えておきます。&lt;/p&gt;</description></item><item><title>MacBook Proがスリープ中に起きまくっているようなので設定を変えてみた</title><link>https://blog.piyo.tech/posts/2018-08-12-mac-sleep/</link><pubDate>Sun, 12 Aug 2018 06:48:28 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-12-mac-sleep/</guid><description>&lt;p&gt;スリープ中のMacが熱くなる現象がずっと前からありました。Macの熱のせいで部屋が暑いし（夏だから）、本体もかなり熱いので心配です。&lt;/p&gt;
&lt;p&gt;Macの挙動で気になっていたのでは、スリープしているにもかかわらず接続しているディスプレイからMacの復帰を認識したときのピッという音がなることです。だいたいFacebookメッセンジャーなどのメッセージを受信したタイミングで起こっていることがなんとなくわかっていたので、実はスリープ中もネットワークがつながっていて、通知のタイミングで起こすのかな？と思っていました。&lt;/p&gt;
&lt;p&gt;省エネルギーからいじれる設定は割といじっているので、他にも原因があるのではないかと思って色々調べてみましたところ、こんな記事をみつけたのでトライしてみました。結果しばらく様子見しようと思っています。&lt;/p&gt;
&lt;p&gt;「スリープ時にもネットワーク接続を許可するオプションを確認」のところです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://wp.bmemo.pw/1264/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://wp.bmemo.pw/images/default.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Macでスリープ時にバッテリーが減る現象を改善する方法まとめ - wp.bmemo.pw&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;⚠この記事はブログ移転前のアーカイブです El capitanから？よくわからないけどMacのスリープ中にバッテリーがモリモリ減る現象が出るようになった。夜100%、朝80%とかになってたり。MBA2012モデル使ってたときは夜100%朝100%ってくらいスリープ時にバッテリーは減らなかったので、直したいなあと思ってました。原因はいくつかあるので１つずつ潰してみたいと思います。 もくじ Power Napの設定を確認する 詳細な電源設定を確認する SDカードを挿しっぱなしにしていないか スリープ時にもネットワーク接続を許可するオプションを確認 SIPをオフに TCPKeepAliveDuringSleepをオフに 12時間スリープで1%消費まで改善 Power Napの設定を確認する システム環境設定 -&amp;gt; 省エネルギー -&amp;gt; バッテリー の項目で 「バッテリー電源使用中にPowerNapをオンにする」にチェックが入っていないか確認してください。 スリープ中勝手に起きて更新やらなにやらを確認する設定です。自分の環境では既にオフ状態でした。 詳細な電源設定を確認する バッテリー電源で動作させているときに以下のコマンドを実行します pmset -g こんな感じの結果が出力されたでしょうか。 System-wide power settings: Currently in use: standbydelay 1800 standby 1 halfdim 1 hibernatefile /var/vm/sleepimage powernap 0 gpuswitch 2 disksleep 0 sleep 3 autopoweroffdelay 0 hibernatemode 3 autopoweroff 0 ttyskeepawake 1 displaysleep 3 acwake 0 lidwake 1 stanbydelay カバーを閉じてから、スタンバイモードに突入する時間です（秒）デフォルトは10800秒 hibernatemode スリープの状態を選択します。0,3,25から選択します。 各モードの意味についてはここ参照 http://www.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://wp.bmemo.pwimages/logo.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;wp.bmemo.pw&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;詳しくはわかってないですが、&lt;code&gt;ioreg&lt;/code&gt;というコマンドがあって、そこでスリープ中のネットワークアクセスなどに関する設定を確認することができるようです。&lt;/p&gt;
&lt;p&gt;紹介したブログ記事の通り実行してみると僕もまったく同じ状況でした。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% ioreg -l | grep IOPlatformFeatureDefaults
| | | &amp;#34;IOPlatformFeatureDefaults&amp;#34; = {&amp;#34;TCPKeepAliveDuringSleep&amp;#34;=Yes,&amp;#34;DNDWhileDisplaySleeps&amp;#34;=No,&amp;#34;TCPKeepAliveExpirationTimeout&amp;#34;=43200,&amp;#34;NotificationWake&amp;#34;=Yes
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;表に整理すると、こうなっていました。キー名から推測した意味も書いておきます。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;意味（推測）&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TCPKeepAliveDuringSleep&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;スリープ中にTCP通信を維持するかどうか&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DNDWhileDisplaySleeps&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;ディスプレイのスリープ時にはDND（おやすみモード的なの）にする&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TCPKeepAliveExpirationTimeout&lt;/td&gt;
&lt;td&gt;43200&lt;/td&gt;
&lt;td&gt;TCPを維持する時間（秒）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NotificationWake&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;通知時に起きる&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;意味が推測通りだとしたら、僕が気になってたメッセージを受け取るとスリープから解除するというのは、&lt;code&gt;NotificationWake&lt;/code&gt;によるものではないかという気がします。&lt;/p&gt;
&lt;p&gt;正直、スリープ中にネットワークに接続したい用途は一切ないので、先ほどの記事のように設定を書き換えました。&lt;/p&gt;
&lt;p&gt;手順は元記事を見ていただいたほうがいいような気がします。他にも関連してそうな情報が載ってるので。。。&lt;/p&gt;
&lt;p&gt;さて、無事設定を変更して再度コマンドで確認をすると以下のようになっており、無事想定通りの結果になっていることがわかりました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% ioreg -l | grep IOPlatformFeatureDefaults
| | | &amp;#34;IOPlatformFeatureDefaults&amp;#34; = {&amp;#34;DNDWhileDisplaySleeps&amp;#34;=Yes,&amp;#34;TCPKeepAliveDuringSleep&amp;#34;=No,&amp;#34;NotificationWake&amp;#34;=No}
&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TCPKeepAliveDuringSleep&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DNDWhileDisplaySleeps&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NotificationWake&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;これでメッセージ受信でスリープ解除されないか、毎朝熱くなっていないかどうかなどをを確認したいと思います。&lt;/p&gt;</description></item><item><title>gemが持ってるJSをwebpackerで読み込むには</title><link>https://blog.piyo.tech/posts/2018-08-11-gem-with-js-on-webpacker/</link><pubDate>Sat, 11 Aug 2018 06:48:11 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-11-gem-with-js-on-webpacker/</guid><description>&lt;p&gt;手持ちのレガシー目なRails案件をいい加減Webpackerに直す活動を始めていまして、まずは仕事以外のプロジェクトからやってます。&lt;/p&gt;
&lt;p&gt;JS用のgemだったりrails-assetsあたりはyarn化の時点でだいたい撲滅できていいですね。&lt;/p&gt;
&lt;p&gt;ですが、RubyのコードがメインでJSも持っているようなgemではwebpacker化したときにJSをビルドできないという問題が起こります。&lt;/p&gt;
&lt;p&gt;例えばcocoon gemがそうです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/nathanvda/cocoon" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/8883daabafc40e16b2ae6e7032cf9b359072384e5efba90540f4827790942550/nathanvda/cocoon" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - nathanvda/cocoon: Dynamic nested forms using jQuery made easy; works with formtastic, simple_form or default forms&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Dynamic nested forms using jQuery made easy; works with formtastic, simple_form or default forms - nathanvda/cocoon&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;その場合はERBの仕組みを使って、gemのパスから対象のJSファイルをインポートするような書き方を取れば大丈夫、とcocoonおissueにありまして、実際それで解消しました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/nathanvda/cocoon/issues/452"&gt;Changes related to RoR 5.1 optionable Webpacker · Issue #452 · nathanvda/cocoon&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;↓コマンドでインストールして、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% rails webpacker:install:erb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;config/webpacker.yml&lt;/code&gt;も一部変更して、&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# config/webpacker.yml
default: &amp;amp;default
# Search jQuery in node_modules of the application and not in the cocoon directory
resolved_paths: [&amp;#39;node_modules/jquery/dist&amp;#39;]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;最後に&lt;code&gt;app/javascript/packs/application.js&lt;/code&gt;を&lt;code&gt;app/javascript/packs/application.js.erb&lt;/code&gt;とリネームした上で、gemのパスを含めたファイルのパスを指定してインポート等すればOK。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;// app/javascript/packs/application.js.erb
import &amp;#34;&amp;lt;%= File.join(Gem.loaded_specs[&amp;#39;cocoon&amp;#39;].full_gem_path, &amp;#39;app&amp;#39;, &amp;#39;assets&amp;#39;, &amp;#39;javascripts&amp;#39;, &amp;#39;cocoon&amp;#39;) %&amp;gt;&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;おかげでJSを含んだgemの対応も問題なくいけました。&lt;/p&gt;</description></item><item><title>rest-clientで簡易にAPIクライアントを書く</title><link>https://blog.piyo.tech/posts/2018-08-10-api-client-with-rest-client/</link><pubDate>Fri, 10 Aug 2018 06:40:25 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-10-api-client-with-rest-client/</guid><description>&lt;p&gt;オープンではないサービスのAPIを使うとき、APIクライアントが無いってことが多いです。なのでアプリケーションから使いたいAPIだけを叩くような簡易なAPIクライアントを自分で書きます。そのときはrest-clientあたりを使ってベタっと書いてしまうことがほとんどです。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;rest-client&lt;/strong&gt;&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/rest-client/rest-client" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/d627fa4c45a4a17d0833d92560e6b944b3647ae360187286263f212b05f52e44/rest-client/rest-client" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - rest-client/rest-client: Simple HTTP and REST client for Ruby, inspired by microframework syntax for specifying actions.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Simple HTTP and REST client for Ruby, inspired by microframework syntax for specifying actions. - rest-client/rest-client&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="まずはサクッと"&gt;まずはサクッと&lt;/h1&gt;
&lt;p&gt;例をいきなり書いてしまうと↓な感じでやります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ApiClient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ENDPOINT&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;https://api.example.com/items.json&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;freeze
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; self
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;items&lt;/span&gt;(search)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENDPOINT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; params &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;s&lt;/span&gt;: search}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; get(url, params)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;item&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(url, params)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; res &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;RestClient&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(url, &lt;span style="color:#e6db74"&gt;params&lt;/span&gt;: params)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; res&lt;span style="color:#f92672"&gt;.&lt;/span&gt;code &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;JSON&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;parse(res&lt;span style="color:#f92672"&gt;.&lt;/span&gt;body)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# こんな感じで使う&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ApiClient&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;items(&lt;span style="color:#e6db74"&gt;&amp;#39;けんさく&amp;#39;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;[...]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;はい、これだけ。&lt;/p&gt;
&lt;h1 id="レスポンスを工夫する"&gt;レスポンスを工夫する&lt;/h1&gt;
&lt;p&gt;なんですが、レスポンスを&lt;code&gt;JSON.parse&lt;/code&gt;したHashそのままというのはなんだかイケてないので、rest-clietを使っているAPIクライアントライブラリはどうしているのか、みたいなことを調べました。いい感じの実装を発見したので、それをインスパイアしてみました。&lt;/p&gt;
&lt;p&gt;まず、Hashの扱いが少し変わります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;items&lt;/span&gt;(search)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENDPOINT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; params &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;s&lt;/span&gt;: search}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; get(url, params)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;[]&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; data&lt;span style="color:#f92672"&gt;.&lt;/span&gt;nil?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; data&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;items&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;].&lt;/span&gt;map &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;item&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ItemResponse&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(item)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こうすると&lt;code&gt;ApiClient.items('xxx')&lt;/code&gt;の結果は&lt;code&gt;ItemResponse&lt;/code&gt;の配列となります。&lt;/p&gt;
&lt;p&gt;で、この&lt;code&gt;ItemResponse&lt;/code&gt;とは何者かといいますと、レスポンスのHashをJSのオブジェクトっぽいものに変換する（ドットでアクセスできるようにする）ためのクラスです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;hash &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;hoge&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;hogehoge&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;fuga&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;fugafuga&amp;#39;&lt;/span&gt;, hash: { &lt;span style="color:#e6db74"&gt;key1&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;value1&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;key2&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;value2&amp;#39;&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;obj &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ApiClient&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Response&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(hash)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;obj&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hoge &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;hogehoge&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;obj&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fuga &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;fugafuga&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;obj&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hash &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;:key1&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;value1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:key2&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;value2&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実装が半端なので入れ子のHashはメソッドでアクセスできるようになっていませんが、僕のケースはこれで事足りたのでそれ以上はがんばりませんでした。&lt;/p&gt;
&lt;p&gt;ちなみに、このResponseクラスの実装は&lt;code&gt;payjp-ruby&lt;/code&gt;のこの辺のコードを参考にしています（実際には参考にしたのはしばらく前なので、そのときから更に実装が変わっているみたい。Hashのネストも対応してそう）。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/payjp/payjp-ruby/blob/master/lib/payjp/payjp_object.rb" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/198b9110ae7e9e73d9bd98cf6ad6b57dc8c45d0b32c05f8b1cc1cdba46b9d20a/payjp/payjp-ruby" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;payjp-ruby/lib/payjp/payjp_object.rb at master · payjp/payjp-ruby&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Contribute to payjp/payjp-ruby development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Response&lt;/code&gt;とそれを継承した&lt;code&gt;ItemResponse&lt;/code&gt;というのを&lt;code&gt;ApiClient&lt;/code&gt;内に用意する形にしました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ApiClient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# （略）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Response&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;initialize&lt;/span&gt;(hash)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; @values &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; instance_eval &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; add_accessors(hash&lt;span style="color:#f92672"&gt;.&lt;/span&gt;keys)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; hash&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;k, v&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; @values&lt;span style="color:#f92672"&gt;[&lt;/span&gt;k&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; v
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add_accessors&lt;/span&gt;(keys)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; metaclass&lt;span style="color:#f92672"&gt;.&lt;/span&gt;instance_eval &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; keys&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;k&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; k_eq &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;:&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;k&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;=&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; define_method(k) { @values&lt;span style="color:#f92672"&gt;[&lt;/span&gt;k&lt;span style="color:#f92672"&gt;]&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; define_method(k_eq) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;v&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; v &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;raise&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ArgumentError&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;You cannot set &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;k&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; to an empty string.&amp;#34;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;We interpret empty strings as nil in requests.&amp;#34;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;You may set &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;self&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;k&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; = nil to delete the property.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; @values&lt;span style="color:#f92672"&gt;[&lt;/span&gt;k&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; v
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;metaclass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; self; self; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ItemResponse&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Response&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;42&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 必要であればメソッド生やす&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;43&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;my_method&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;44&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;45&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;46&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="プロキシサーバーを経由する"&gt;プロキシサーバーを経由する&lt;/h1&gt;
&lt;p&gt;冒頭に「オープンではないサービスのAPI」と書きました。そういう場合って、特定のIPアドレスからしかアクセスできませんみたい制約があったりするので、開発時には工夫が必要です。&lt;/p&gt;
&lt;p&gt;このクライアントを実装したときには、プロキシサーバーのIPを許可してもらい、クライアントはプロキシサーバー経由でAPIリクエストを投げるようにしました。&lt;/p&gt;
&lt;p&gt;rest-clientの場合のプロキシ設定は非常に簡単で、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;RestClient&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;proxy &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://accountname:password@54.xxx.yyy.zzz&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;としておくだけでOK。Railsならinitializerで書いておくのが良いです。&lt;/p&gt;</description></item><item><title>PLANTRONICSのBluetoothのヘッドセットが一番良い</title><link>https://blog.piyo.tech/posts/2018-08-09-bluetooth-headset/</link><pubDate>Thu, 09 Aug 2018 06:43:57 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-09-bluetooth-headset/</guid><description>&lt;p&gt;こないだBluetoothのヘッドセットを買った話と、そのときに買ったJABRAのヘッドセットの使い勝手があまりよくなかったという話を書きました。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-07-26-bluetooth-headset/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;blog.piyo.tech →&lt;/span&gt;&lt;span&gt;https://blog.piyo.tech/posts/2018-07-26-bluetooth-headset/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;結局、一度壊してしまったのと全く同じモデルのPLANTRONICSのヘッドセットを購入しました。これです。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-orange-300 rounded p-3 text-sm"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B00IIJUMTE/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline"&gt;
&lt;span class="text-orange-600 mr-1"&gt;amazon.co.jp →&lt;/span&gt;ASIN: B00IIJUMTE
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;購入履歴で検索をかけると&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/rzdRIMzZHzx6rhIYqIqPaHemMLRc_Iblf0uQw3CcGftaqGwIR3FTTxcxvTeskey9CQpbzwmlyUCZ0TN-_C5mITMz8_s4PWW43AqXxPmQJp_88y1jR4-Uy5nTxXbz9hkMnzUGOyyP-AASpQnBque3X9me0bnFEzeuzX-QocPbjtRiEsuQUd7PCM7jMwzrOZG7Smy8u2-VomLfbK_ZiV2OJMiOEO3TVTTARdwnK61WHNchw-YIqK1xRe0PLyGaWJCWN2cOzUft9lLSa7kk-zvDmDdGBk9g74MRCfdsdHucoQ8KyKePIuAgqU4lp0P7bz-ChlPv8tCQGk-VePkEAiNY4FfT1mEFQ0B3nQA3YkoHm2Yf5ntUo_lc_sE2xUswnfZLi476lW3I6xzMR77afq9JKoE6EjBuuPrpeUiHyO20meW8UMz8uN_aolYOqhbsIv_nRw4aNbHlCsycRsSu9DvrZt4UJAiXWvUHp1UUBm_xKlngDjHT9YVB4wvV0XbGQmzBWAE7YZ24bE8zjVpbhwMwr7aIzij0Lid6LRwZShi6AthrrMxsRiq12NL3qeHbhep6ZVaRYyruvOdeNRwGuRLPFcmav8Y0gZh0NhDnZ4MZmCtjCtJVAmgGEVJU20C1ymRmkMfKGTPEF2WgceX85YXkWwJMGsFQJc7_=w1896-h834-no"&gt;&lt;img src="https://lh3.googleusercontent.com/rzdRIMzZHzx6rhIYqIqPaHemMLRc_Iblf0uQw3CcGftaqGwIR3FTTxcxvTeskey9CQpbzwmlyUCZ0TN-_C5mITMz8_s4PWW43AqXxPmQJp_88y1jR4-Uy5nTxXbz9hkMnzUGOyyP-AASpQnBque3X9me0bnFEzeuzX-QocPbjtRiEsuQUd7PCM7jMwzrOZG7Smy8u2-VomLfbK_ZiV2OJMiOEO3TVTTARdwnK61WHNchw-YIqK1xRe0PLyGaWJCWN2cOzUft9lLSa7kk-zvDmDdGBk9g74MRCfdsdHucoQ8KyKePIuAgqU4lp0P7bz-ChlPv8tCQGk-VePkEAiNY4FfT1mEFQ0B3nQA3YkoHm2Yf5ntUo_lc_sE2xUswnfZLi476lW3I6xzMR77afq9JKoE6EjBuuPrpeUiHyO20meW8UMz8uN_aolYOqhbsIv_nRw4aNbHlCsycRsSu9DvrZt4UJAiXWvUHp1UUBm_xKlngDjHT9YVB4wvV0XbGQmzBWAE7YZ24bE8zjVpbhwMwr7aIzij0Lid6LRwZShi6AthrrMxsRiq12NL3qeHbhep6ZVaRYyruvOdeNRwGuRLPFcmav8Y0gZh0NhDnZ4MZmCtjCtJVAmgGEVJU20C1ymRmkMfKGTPEF2WgceX85YXkWwJMGsFQJc7_=w1896-h834-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;こうです。アップデートがなかったみたいで、全く同じモデルでした。&lt;/p&gt;
&lt;p&gt;やはりフィット感も使い勝手も良いです。&lt;/p&gt;
&lt;p&gt;そしてやはり持ち出すたびにどこに置いたか忘れます。洗濯、紛失注意です。&lt;/p&gt;</description></item><item><title>Highchartsのseriesの表示非表示をJSで切り替える</title><link>https://blog.piyo.tech/posts/2018-08-07-highcharts-toggle-series/</link><pubDate>Tue, 07 Aug 2018 06:57:54 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-07-highcharts-toggle-series/</guid><description>&lt;p&gt;最近Highchartsをちょこちょこいじっているので、仕入れたのを小出しにしていきます。&lt;/p&gt;
&lt;p&gt;Highchartsでは凡例を出しておくと凡例のクリックでデータ毎に表示の切り替えができます。&lt;/p&gt;
&lt;p&gt;ですが、凡例は見た目上の工夫がほぼできないため、凝ったUIで表示状態を切り替えるためにはJavascriptを書いて制御してあげる必要があります。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;series&lt;/code&gt;には&lt;code&gt;hide()&lt;/code&gt;や&lt;code&gt;show()&lt;/code&gt;という関数、&lt;code&gt;visible&lt;/code&gt;という属性があるのでそれらを駆使してJavscriptから制御が可能です。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://api.highcharts.com/class-reference/Highcharts.Series#hide" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Highcharts Class: Series&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://api.highcharts.com/../highcharts/favicon-192x192.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;api.highcharts.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;以下、ボタンを押したら&lt;code&gt;visible&lt;/code&gt;で状態を見て、隠すなり出すなりするコードです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onClick&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;series&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;chart&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;visible&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;hide&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;show&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;全体はこちら。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://jsfiddle.net/17bfmw5g/1/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Highcharts Demo - JSFiddle - Code Playground&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;JSFiddle - Test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://jsfiddle.net/img/favicon.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;jsfiddle.net&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;案外簡単なので自前のUIというもの簡単に実現できそうです。&lt;/p&gt;</description></item><item><title>遅まきながらRails5の頃に作ったプロジェクトをyarn化する（webpacker無し）</title><link>https://blog.piyo.tech/posts/2018-08-05-rails-yarn/</link><pubDate>Sun, 05 Aug 2018 06:58:07 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-05-rails-yarn/</guid><description>&lt;p&gt;Rails5の頃に作ったプロジェクトで、JS系のアセットの管理には&lt;a href="https://rails-assets.org"&gt;Rails Assets&lt;/a&gt;を使っている、Rails 5.1のプロジェクトが手元にありました。&lt;/p&gt;
&lt;p&gt;先日（8/3）にそのRails Assetsが証明書の期限切れでbundle installできなくなるという問題が発生。
これを期に管理方法を変えないとねということで、Rails 5.1から使えるYarnを使うことにしました。&lt;/p&gt;
&lt;p&gt;webpackerを使うのは遠すぎるのでやめました。&lt;/p&gt;
&lt;h1 id="手順"&gt;手順&lt;/h1&gt;
&lt;h2 id="node_modulesを読み込めるようにしておく"&gt;node_modulesを読み込めるようにしておく&lt;/h2&gt;
&lt;p&gt;Rails 5.1へアップデートしたときに自動的に対応済になっていることが多い箇所ですが、asset pipelineのパスにnode_modulesを通しておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# config/initializers/assets.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ↓を追記&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Add Yarn node_modules folder to the asset load path.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;.&lt;/span&gt;config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;assets&lt;span style="color:#f92672"&gt;.&lt;/span&gt;paths &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;root&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(&lt;span style="color:#e6db74"&gt;&amp;#39;node_modules&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="packagejsonの用意"&gt;package.jsonの用意&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% yarn init
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;するとpackage.jsonが作られます。ただ、Railsが生成するファイルとは異なるので適当に削っておきます。おそらくdescriptionとか要らないはずなので。&lt;/p&gt;
&lt;p&gt;こんな感じのファイルで良いはずです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;my-project&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;private&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;dependencies&amp;#34;&lt;/span&gt;: {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="パッケージの追加"&gt;パッケージの追加&lt;/h2&gt;
&lt;p&gt;bootstrapが使う&lt;code&gt;popper.js&lt;/code&gt;と、アプリケーションが使っていた&lt;code&gt;jquery-confirm&lt;/code&gt;をyarnで入れてみます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ yarn add popper.js jquery-confirm
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ついでにGemfileの不要な記述は消しておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-source &amp;#39;https://rails-assets.org&amp;#39; do
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;- gem &amp;#39;rails-assets-popper.js&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;- gem &amp;#39;rails-assets-jquery-confirm2&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-end
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="requireを変更"&gt;requireを変更&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-#= require jquery
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-#= require popper
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-#= require jquery-confirm2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+#= require jquery/dist/jquery.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+#= require popper.js/dist/umd/popper.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+#= require jquery-confirm/dist/jquery-confirm.min.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;popper.jsはdistに3種類あって正しいものを指定しないとsyntaxエラーとなります。トランスパイラを使わない場合は&lt;code&gt;umd/&lt;/code&gt;以下のコードを参照する必要がありました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;Popper.js is currently shipped with 3 targets in mind: UMD, ESM, and ESNext.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;No idea what am I talking about? You are looking for UMD probably.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;-&lt;/span&gt; UMD - Universal Module Definition: AMD, RequireJS, and globals;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;-&lt;/span&gt; ESM - ES Modules: For webpack/Rollup or browser supporting the spec;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;-&lt;/span&gt; ESNext: Available in /dist, can be used with webpack and babel-preset-env;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;cssがあるパッケージの場合はそちらも変更する必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-@import &amp;#34;jquery-confirm2&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;+@import &amp;#34;jquery-confirm/dist/jquery-confirm.min.css&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;p&gt;多分これら手順で動くはず。&lt;/p&gt;</description></item><item><title>Highchartsのチャートに新しいデータ列（Series）をJSで追加する</title><link>https://blog.piyo.tech/posts/2018-08-04-highcharts-add-series/</link><pubDate>Sat, 04 Aug 2018 06:05:47 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-04-highcharts-add-series/</guid><description>&lt;p&gt;今日もHighcharts。今度は新しいデータ列を追加する方法です。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://jsfiddle.net/rveczxL1/7" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Highcharts Demo - JSFiddle - Code Playground&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;JSFiddle - Test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://jsfiddle.net/img/favicon.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;jsfiddle.net&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;昨日のJSFiddleをちょっと改変して、ボタンを押したら新しいデータ列を追加します。データの変更のときと同様アニメーションつきで描画されるのでとてもリッチな感じで良いです。&lt;/p&gt;
&lt;p&gt;highchartのインスタンスに&lt;code&gt;addSeries&lt;/code&gt;という関数があるのでこちらを使えばOKです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onClick&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;chart&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;addSeries&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;新しく追加したデータ&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;100000&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;110000&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;120000&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;100000&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;130000&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;140000&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;渡すオブジェクトはHighchartsを初期化するときにseriesとして渡す内容と同じで良さそう。&lt;/p&gt;
&lt;p&gt;詳細はドキュメント↓&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://api.highcharts.com/class-reference/Highcharts.Chart#addSeries" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Highcharts Class: Chart&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://api.highcharts.com/../highcharts/favicon-192x192.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;api.highcharts.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ちなみにseriesの削除はこれだけでOK。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;chart&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;remove&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Highchartsで描画したチャートをJSから更新する</title><link>https://blog.piyo.tech/posts/2018-08-03-update-highcharts-chart/</link><pubDate>Fri, 03 Aug 2018 06:53:07 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-03-update-highcharts-chart/</guid><description>&lt;p&gt;Highchartsで描画したチャートの値はあとからjavascriptで更新できます。&lt;/p&gt;
&lt;p&gt;デモをちょっと改変してサンプルを作ってみました↓&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://jsfiddle.net/sz84x5q6/8/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Highcharts Demo - JSFiddle - Code Playground&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;JSFiddle - Test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://jsfiddle.net/img/favicon.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;jsfiddle.net&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;options&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {} &lt;span style="color:#75715e"&gt;// 略
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;chart&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Highcharts&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;chart&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;container&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;options&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onClick&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;chart&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;update&lt;/span&gt;({&lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;80000&lt;/span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;chart&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;update&lt;/span&gt;({&lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;60000&lt;/span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;chart&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;update&lt;/span&gt;({&lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;40000&lt;/span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;chart&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;update&lt;/span&gt;({&lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100000&lt;/span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;chart&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;update&lt;/span&gt;({&lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100000&lt;/span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;chart&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;update&lt;/span&gt;({&lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;んで、ボタンを押したらonClickが呼ばれるようにしておきました。雑だけど、まあ。&lt;/p&gt;
&lt;p&gt;onClickではhighchartsのインスタンスのseries以下のデータに対してupdateを呼び出します。すると値が更新されて、アニメーション付で再描画されます。アニメーションがあるのが気持ち良い感じ。&lt;/p&gt;
&lt;p&gt;JSFiddleから試してみてください。ちなみにchartのインスタンスはjQueryで&lt;code&gt;$('#container').highcharts()&lt;/code&gt;とかやっても取得できます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;update&lt;/code&gt;関数の詳細はドキュメントで確認できます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://api.highcharts.com/class-reference/Highcharts.Point.html#update" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Highcharts Class: Point&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://api.highcharts.com/../highcharts/favicon-192x192.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;api.highcharts.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>ディレクトリ内の画像をコマンドラインで一括縮小する</title><link>https://blog.piyo.tech/posts/2018-08-02-bulk-resize-image-cli/</link><pubDate>Thu, 02 Aug 2018 06:57:47 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-08-02-bulk-resize-image-cli/</guid><description>&lt;p&gt;&lt;code&gt;mogrify&lt;/code&gt;というコマンドを使います。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mogrify&lt;/code&gt;はImageMagickに含まれるツールの一つで&lt;code&gt;convert&lt;/code&gt;とほぼ同じことができますが、&lt;code&gt;mogrify&lt;/code&gt;の場合は基本的に元画像がそのまま上書きされます。&lt;/p&gt;
&lt;p&gt;ImageMagickが入っていない場合は適当に調べて入れてください。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% mogrify -geometry 50% input.jpg
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;のように使えます。↑の場合は&lt;code&gt;input.jpg&lt;/code&gt;を縦横半分のサイズに縮小できます。&lt;/p&gt;
&lt;p&gt;他のオプションは詳しくは調べるとわかるんですが、ざっくり小さくしたいときにはこれで済むのでここでは割愛。&lt;/p&gt;
&lt;p&gt;で、一括置換の方法です。僕の用途はiPhoneで撮った写真をブログに載せるためにサイズを落とすときに使います。iPhoneの写真は最近は4MBとかありますからそのまま載せると無駄が多いです。&lt;/p&gt;
&lt;p&gt;まずはiPhoneで撮影した写真をAirDropでMacへ送ります。あとはコマンドラインでの操作ですね。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% cd ~/Downloads
% ls
IMG_1609.JPG IMG_1610.JPG IMG_1611.JPG IMG_1612.JPG IMG_1613.JPG IMG_8601.JPG IMG_9133.JPG
% ls | xargs mogrify -geometry 30%
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これで30%のサイズに変わります。元が3024x3024の画像なら907x907の画像になるというわけ。&lt;/p&gt;
&lt;p&gt;GUIのツールが要らないから楽でいいですね。&lt;/p&gt;</description></item><item><title>TestFlightでテスト情報の保存で何度も「問題が発生しました」エラーになった</title><link>https://blog.piyo.tech/posts/2018-07-31-testflight-setting-error/</link><pubDate>Tue, 31 Jul 2018 06:14:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-31-testflight-setting-error/</guid><description>&lt;p&gt;TestFlightのベータ版審査に提出するために、事前準備として必要なテスト情報を入力しようとしたらエラーになりました。&lt;/p&gt;
&lt;p&gt;テスト情報はAppStore ConnectのTestFlightのタブへ移動し、サイドメニューのテスト情報から入力ができるアレです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/UBTuP1mYfBCrNN4iWuwgO2UnJ3WGmxAtyMAEWlQp4hZI6s-NXByK84fWwnpbo9kKLvSaqKd1EtQXrvTGIE-ze8Vh1sjh_X1MLngS2FTxcyWPPGHDx8B94drhHVvfDgaH3UUsJx6dc-fmvIVQth7C1NMTQhXBRmjKUuqNYO4f8xXufvsXricCBPFQhNjfrb7YhOgDzrZ3sGj_yBLxoCM1FaaNIp4cHgeOxuH6bfUvG9lQuI5Kpt3s8chuEB-o39pI6loYhdoMTsvLIUTEI44DMsKQ8vYW99zUrCH-8dIvXmdZOyyFZHyzb3YspG8bMz5dAfvJgbRKb7ktELrp8nf7vPssquiFTu_25puRgR7XH8bk9UJdMQECaPEOl-bOlI5LANAgWbTHuBCq1hPXUyvSoIVFqbNNR0t0_vH2fc2egsdERsoaC9-ZrMDaovPORVTKVhW7hSXiJznuprDZ3-ahFeKKnBC0rb5_EfVB-J1LivBQNv4-lmkL1zLCjyy5t64qd__FWtmhFscGw_WJb2h99glL1Aw9zgZuJdpwb7EAr73MO26l5-CBA81cDiXMCgqc9EABg96HlV6-OU1m1UhCTa2uxpobf_tdczxrzooG5UePStFkzH5fTC4nOO2XY53jZauzXY5PCJvbmoHX85tVrhTZbjYJU081=w264-h551-no"&gt;&lt;img src="https://lh3.googleusercontent.com/UBTuP1mYfBCrNN4iWuwgO2UnJ3WGmxAtyMAEWlQp4hZI6s-NXByK84fWwnpbo9kKLvSaqKd1EtQXrvTGIE-ze8Vh1sjh_X1MLngS2FTxcyWPPGHDx8B94drhHVvfDgaH3UUsJx6dc-fmvIVQth7C1NMTQhXBRmjKUuqNYO4f8xXufvsXricCBPFQhNjfrb7YhOgDzrZ3sGj_yBLxoCM1FaaNIp4cHgeOxuH6bfUvG9lQuI5Kpt3s8chuEB-o39pI6loYhdoMTsvLIUTEI44DMsKQ8vYW99zUrCH-8dIvXmdZOyyFZHyzb3YspG8bMz5dAfvJgbRKb7ktELrp8nf7vPssquiFTu_25puRgR7XH8bk9UJdMQECaPEOl-bOlI5LANAgWbTHuBCq1hPXUyvSoIVFqbNNR0t0_vH2fc2egsdERsoaC9-ZrMDaovPORVTKVhW7hSXiJznuprDZ3-ahFeKKnBC0rb5_EfVB-J1LivBQNv4-lmkL1zLCjyy5t64qd__FWtmhFscGw_WJb2h99glL1Aw9zgZuJdpwb7EAr73MO26l5-CBA81cDiXMCgqc9EABg96HlV6-OU1m1UhCTa2uxpobf_tdczxrzooG5UePStFkzH5fTC4nOO2XY53jZauzXY5PCJvbmoHX85tVrhTZbjYJU081=w264-h551-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ところがこのテスト情報、なんどやっても保存できない。保存できないのでベータ審査への提出ができません。（できませんよね？よく考えるとちゃんと確認してなかった。）&lt;/p&gt;
&lt;p&gt;このようなエラーが出て、何がダメなのか全くわかりません。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/4xEtBXCaXFDG-nMcuoKsVODsMVSRTRkQKYH5XOp5yh9jbzTebDC7BoPuDroRRpGDILd5H8_tUgs2uCon0vmskBrXShsieBCTewIApPiM6-ul3qAcU4b3JdWCClT8yPiZupX846jCFzR3gNQnzzFl5yK1rtKGQHrGI0-FLTmfzRDjVdt0RFiNfIcmgqxEbRJ2s5Wvgb7usZnOY1EYEk2PTL_5mlyFDEYfBJY9Y3aj2yjBvNbUH_yTSeFZtsHLqDDOAnKeiSdwdHbN1OVdH8EWi2sj9lLx4XNJ2mc19YzBr0QyfI_xN8As3VUBk7-UKU_j3tA7WZ4XnIbrtJusnhYQvmCRJSlaRF5JRiAiRfDmDeBAFlDG5CO_AfdK_tRNBdOlh3R1zgapXGJiiPl2SX7EQG_CLfnMgzJvV3yvOyfFmuCePucCeT0dcQhVC22uPYvopBWQup9wE_YVHHW5gR5dCVIymmTxyW9llQRmUKGkNhQfgrRsMHPxSl6l-uBV4I9-G2RlbPTYp3PBrYXH1NppN87bAaZenGYsSEUlLH7osoWN9Jb3KxMPgwc6Ajyq44Hq0fTjXztAaTVaM8S1ycphLkWAaqZXZ3DwVBHc8-OT3wWVwH7LUjlC4nbQ-SR3pb_OarOqd_MrxohwEfoDhCRyUeJPDdtJIyL6=w521-h294-no"&gt;&lt;img src="https://lh3.googleusercontent.com/4xEtBXCaXFDG-nMcuoKsVODsMVSRTRkQKYH5XOp5yh9jbzTebDC7BoPuDroRRpGDILd5H8_tUgs2uCon0vmskBrXShsieBCTewIApPiM6-ul3qAcU4b3JdWCClT8yPiZupX846jCFzR3gNQnzzFl5yK1rtKGQHrGI0-FLTmfzRDjVdt0RFiNfIcmgqxEbRJ2s5Wvgb7usZnOY1EYEk2PTL_5mlyFDEYfBJY9Y3aj2yjBvNbUH_yTSeFZtsHLqDDOAnKeiSdwdHbN1OVdH8EWi2sj9lLx4XNJ2mc19YzBr0QyfI_xN8As3VUBk7-UKU_j3tA7WZ4XnIbrtJusnhYQvmCRJSlaRF5JRiAiRfDmDeBAFlDG5CO_AfdK_tRNBdOlh3R1zgapXGJiiPl2SX7EQG_CLfnMgzJvV3yvOyfFmuCePucCeT0dcQhVC22uPYvopBWQup9wE_YVHHW5gR5dCVIymmTxyW9llQRmUKGkNhQfgrRsMHPxSl6l-uBV4I9-G2RlbPTYp3PBrYXH1NppN87bAaZenGYsSEUlLH7osoWN9Jb3KxMPgwc6Ajyq44Hq0fTjXztAaTVaM8S1ycphLkWAaqZXZ3DwVBHc8-OT3wWVwH7LUjlC4nbQ-SR3pb_OarOqd_MrxohwEfoDhCRyUeJPDdtJIyL6=w521-h294-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この、サーバーエラーであるかのようなエラー。&lt;/p&gt;
&lt;p&gt;結局サポートに問い合わせて何回かやりとりしてようやくわかったのは、入力した文字数が少ないのかもしれない、ということでした。&lt;/p&gt;
&lt;p&gt;テスト情報には「ベータ版Appの説明」というテキストエリアがあります。ここに10文字以上入れてください、とのことでした（↓これ）。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Y48ZlGn2z0GbMpYyhiSAU3CZ50amzClG0LW06o2OoVRJTisNrBQpFkiqju044petxnNJigDo_CaAzyJ1UMXztAEyGIgWcurglpe59v5TmE8dpU_uJqJd5VqdLNE47DkFnJ9Bxkn0UY0IIGZEOrVz4iNVaH7hDAjC5q0wGspBO_ggnor2EF90u2ckObHNsvRfU9jnKff5OxnvM2OpuxwCudNaulh-3HMtVL7dnxdCZcfdrCfyTU2S1Ru6LjMQHpoMLfPNIgeCqKiW6wSGjdIYeWRodY8ziOSxhR3XXfDtEZMunCCPLdc5VMVP-wr07BPutZ9dee3yw1wHv8fYDf1bHVZXAZiZGwAEFjjy6SEDDhTmIRgsZ7-F8vULmK84B94rniLkwKy6vILGQK8q-th-STWbr--_3SltizBnPBeDm2-v4DSdKTNCOxtzb4dxdcdt_QlS1h7Yz_UO6yZWtNAsojOHdAW8ThY4Ujb987OfFN97awPHSj2idFW83sIfgCVvpkfAWP5gjmfx4XJCw1jJyE7Lt2XoDTPB9RcKVt0x0b-0B5NvfRH-ZS99lOcUQ0bVC9a7STZ8HMT_jGiZXDnnJyJZ6__0_H9ZTwA9mGAWCn9Uqm5PT4WnUzNQwKl4e2Hkn1YUdHr7iqOaBMjFpCnfqB8QB8xz1Fuy=w769-h294-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Y48ZlGn2z0GbMpYyhiSAU3CZ50amzClG0LW06o2OoVRJTisNrBQpFkiqju044petxnNJigDo_CaAzyJ1UMXztAEyGIgWcurglpe59v5TmE8dpU_uJqJd5VqdLNE47DkFnJ9Bxkn0UY0IIGZEOrVz4iNVaH7hDAjC5q0wGspBO_ggnor2EF90u2ckObHNsvRfU9jnKff5OxnvM2OpuxwCudNaulh-3HMtVL7dnxdCZcfdrCfyTU2S1Ru6LjMQHpoMLfPNIgeCqKiW6wSGjdIYeWRodY8ziOSxhR3XXfDtEZMunCCPLdc5VMVP-wr07BPutZ9dee3yw1wHv8fYDf1bHVZXAZiZGwAEFjjy6SEDDhTmIRgsZ7-F8vULmK84B94rniLkwKy6vILGQK8q-th-STWbr--_3SltizBnPBeDm2-v4DSdKTNCOxtzb4dxdcdt_QlS1h7Yz_UO6yZWtNAsojOHdAW8ThY4Ujb987OfFN97awPHSj2idFW83sIfgCVvpkfAWP5gjmfx4XJCw1jJyE7Lt2XoDTPB9RcKVt0x0b-0B5NvfRH-ZS99lOcUQ0bVC9a7STZ8HMT_jGiZXDnnJyJZ6__0_H9ZTwA9mGAWCn9Uqm5PT4WnUzNQwKl4e2Hkn1YUdHr7iqOaBMjFpCnfqB8QB8xz1Fuy=w769-h294-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;う、確かに言われてみれば、とりあえずベータ審査に出したかったがために、テキトーな文字を打っていたような気が。ということで少し長くしたら無事保存できました。&lt;/p&gt;
&lt;p&gt;Appleよ、ちゃんとバリデーションエラーぐらい表示してくれよ、という話でした。&lt;/p&gt;</description></item><item><title>fastlaneでTestFlightにアップロードするところまでをセットアップ</title><link>https://blog.piyo.tech/posts/2018-07-30-testflight-with-fastlane/</link><pubDate>Mon, 30 Jul 2018 06:02:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-30-testflight-with-fastlane/</guid><description>&lt;pre tabindex="0"&gt;&lt;code&gt;% bundle init
% echo &amp;#39;gem &amp;#34;fastlane&amp;#34;&amp;#39; &amp;gt;&amp;gt; Gemfile
% bundle install
% fastlane init
[22:17:37]: What would you like to use fastlane for?
1. 📸 Automate screenshots
2. 👩‍✈️ Automate beta distribution to TestFlight
3. 🚀 Automate App Store distribution
4. 🛠 Manual setup - manually setup your project to automate your tasks
? 2
# 他にもいくつかの情報を入力
# fastlane/Appfile
# fastlane/Fastfile
# の2ファイルが作られる
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;Appfile&lt;/code&gt;はチームの情報などが入っています。&lt;code&gt;Fastfile&lt;/code&gt;は実行したいタスクの内容が記述されています。おそらく次のようになっているはず。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;default_platform(&lt;span style="color:#e6db74"&gt;:ios&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;platform &lt;span style="color:#e6db74"&gt;:ios&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; desc &lt;span style="color:#e6db74"&gt;&amp;#34;Push a new beta build to TestFlight&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; lane &lt;span style="color:#e6db74"&gt;:beta&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; build_app(&lt;span style="color:#e6db74"&gt;workspace&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;my-project.xcworkspace&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;scheme&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;my-project&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; upload_to_testflight
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちなみに僕は&lt;code&gt;build_app&lt;/code&gt;の前に&lt;code&gt;increment_build_number&lt;/code&gt;を入れました。うっかり同じビルド番号で上げてしまうとエラーになって面倒だからです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;lane &lt;span style="color:#e6db74"&gt;:beta&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; increment_build_number &lt;span style="color:#75715e"&gt;# &amp;lt;= これを追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; build_app(&lt;span style="color:#e6db74"&gt;workspace&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;my-project.xcworkspace&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;scheme&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;my-project&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; upload_to_testflight
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちなみに&lt;code&gt;increment_build_number&lt;/code&gt;を動かすために、Apple GenericなVersioningにする必要があります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/E7shPK32yNLDUrx5J-qLBfBOcD9I_txVC4QBgbCz6qL7hqXm0EAZRDpE6VK2Oz5gYdyUwnya0KeEoqN8AB6MOB41cSmTnfNVSDq9UCGF6hvgY0-cNJlwRaejv2cmLIwO4xuKh4wfS9XbEw6RAXFw8qNi_xqAciiSua7ZvVhvmkQSXiiauU-4skqU-9ipYt6_4Hl-yL_ZuS04SWG_RZi06Qp_CkW8gEZutEa-BE0yRDbq5BRK8vHSSHMK9gcREtgAe-16T21jCgulaKZtD4bM23ZjWD-pbcS5Q4Kjk_uaNqfH8TXpJCMoP1iSaxcj3S1-wUzmvWiK8ze63fTiaHweO76qs-dtRbiW7uyZ2DYeVPe3BMH6Tz92Z35lZCsNRkzBk5vraGy3ZquMf82-NdDjc-JMujuRy5kxvsOJuNNsCPSp5oLDSYSyrdhxGeP3WCuYpyyfTiQg-b1nXJiNIm60Lll1n88bXX6VuS0hbF-cIARqCFpW52ZB_uKdwfvgxBqilX194EdqTUDYy25h-gJhMwiJsTq_NccxLZ_ZqIzWFT4abJk42-xlnukoBSPZPi_2gXlLuPiQVROusOIodpyRg5jaXjjh67lztOhIoHTWMs1wcRj6Q68YAPOORNszoywUM7y7MlRLzESebjGSeGHXHftkK-bpPJYm=w1076-h392-no"&gt;&lt;img src="https://lh3.googleusercontent.com/E7shPK32yNLDUrx5J-qLBfBOcD9I_txVC4QBgbCz6qL7hqXm0EAZRDpE6VK2Oz5gYdyUwnya0KeEoqN8AB6MOB41cSmTnfNVSDq9UCGF6hvgY0-cNJlwRaejv2cmLIwO4xuKh4wfS9XbEw6RAXFw8qNi_xqAciiSua7ZvVhvmkQSXiiauU-4skqU-9ipYt6_4Hl-yL_ZuS04SWG_RZi06Qp_CkW8gEZutEa-BE0yRDbq5BRK8vHSSHMK9gcREtgAe-16T21jCgulaKZtD4bM23ZjWD-pbcS5Q4Kjk_uaNqfH8TXpJCMoP1iSaxcj3S1-wUzmvWiK8ze63fTiaHweO76qs-dtRbiW7uyZ2DYeVPe3BMH6Tz92Z35lZCsNRkzBk5vraGy3ZquMf82-NdDjc-JMujuRy5kxvsOJuNNsCPSp5oLDSYSyrdhxGeP3WCuYpyyfTiQg-b1nXJiNIm60Lll1n88bXX6VuS0hbF-cIARqCFpW52ZB_uKdwfvgxBqilX194EdqTUDYy25h-gJhMwiJsTq_NccxLZ_ZqIzWFT4abJk42-xlnukoBSPZPi_2gXlLuPiQVROusOIodpyRg5jaXjjh67lztOhIoHTWMs1wcRj6Q68YAPOORNszoywUM7y7MlRLzESebjGSeGHXHftkK-bpPJYm=w1076-h392-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;あとはコマンドラインで&lt;code&gt;% fastlane beta&lt;/code&gt;と叩くと実行されます。&lt;/p&gt;
&lt;p&gt;これでAppStoreConnectにビルドが登録されて、あとは輸出コンプライアンスをチェックすれば内部テスターに配布されるところまではいけました。このプロジェクトはまだ外部テスター向けのレビューが通っていないのでその先までは検証できていないです。&lt;/p&gt;
&lt;p&gt;ホントは輸出コンプライアンスのチェックもパスできるといいんけど、その操作はできないようです。でも、Xcodeで操作すると待って操作して待って操作してになってしまうから、それに比べたらだいぶいいですね。&lt;/p&gt;</description></item><item><title>apache + passengerの環境でアンダースコア区切りのHTTPヘッダーが届かない</title><link>https://blog.piyo.tech/posts/2018-07-29-http-header-with-underscore/</link><pubDate>Sun, 29 Jul 2018 06:09:53 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-29-http-header-with-underscore/</guid><description>&lt;p&gt;iOSアプリからリクエストヘッダーに情報を追加して送る、みたいなことをやろうとして少しはまりました。&lt;/p&gt;
&lt;p&gt;受け取る人はRailsアプリです。ローカルで開発しているときには問題なかったのにAWS上のapache + passengerの環境にデプロイしたら当該ヘッダー情報が抜けてました。&lt;/p&gt;
&lt;p&gt;環境依存っぽいのでapacheかpassengerを疑って色々調べていると、最終的には&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Starting with version 2.4, Apache is more strict about how HTTP headers are converted to environment variables in mod_cgi and other modules: Previously any invalid characters in header names were simply translated to underscores. This allowed for some potential cross-site-scripting attacks via header injection (see Unusual Web Bugs, slide 19/20).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;という、Apacheのドキュメントに到達。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://httpd.apache.org/docs/trunk/en/env.html#fixheader" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Environment Variables in Apache httpd - Apache HTTP Server Version 2.5&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://httpd.apache.org/./images/favicon.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;httpd.apache.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;該当箇所をGoogle翻訳するとこんな感じ。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;2.4より、Apacheはmod_cgiや他のモジュールでHTTPヘッダーを環境変数に変換する方が厳密です。以前はヘッダ名の無効な文字はすべて下線に変換されていました。 これにより、ヘッダインジェクションによるいくつかのクロスサイトスクリプティング攻撃が可能になりました（Unusual Web Bugs、slide 19/20を参照）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;まあつまりアンダースコアが入ってるのはおかしいと判定するみたいですね。まさにアンダースコアをうっかり使っちゃってたのでRailsまで届いてないのは当然っちゃ当然だったわけです。&lt;/p&gt;
&lt;p&gt;ちなみに、Rails側でちゃんとヘッダーが来ているかどうかを見るために↓のURLを参考にしてログに出力して確認しました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://xyk.hatenablog.com/entry/2015/02/01/181648" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://ogimage.blog.st-hatena.com/11696248318757696881/8454420450082049448/1423545377" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Rails でリクエストの HTTP ヘッダを取得してログに出力する - xyk blog&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;環境：rails 4.2.0 Rails でリクエストの HTTP ヘッダはrequest.headersから取得できる。 すべてログに出力するなら # すべてログに出力する request.headers.sort.map { |k, v| logger.info &amp;#34;#{k}:#{v}&amp;#34; } 個別に取得するなら # ユーザーエージェントを取得する request.headers[:HTTP_USER_AGENT] request.envからでも取得できる。 # ユーザーエージェントを取得する request.env[&amp;#39;HTTP_USER_AGENT&amp;#39;] 今回やりたいことはクライアント側から …&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://xyk.hatenablog.com/icon/favicon" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;xyk.hatenablog.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;headers&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sort&lt;span style="color:#f92672"&gt;.&lt;/span&gt;map { &lt;span style="color:#f92672"&gt;|&lt;/span&gt;k, v&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;logger&lt;span style="color:#f92672"&gt;.&lt;/span&gt;info &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;k&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;v&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Swiftデバッグビルドでの最適化オプション</title><link>https://blog.piyo.tech/posts/2018-07-28-swift-slow-with-no-optimization/</link><pubDate>Sat, 28 Jul 2018 06:11:43 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-28-swift-slow-with-no-optimization/</guid><description>&lt;p&gt;React Nativeで使うために高速フーリエ変換のためのコードをJSで書いていたんですが、色々とあってiOSネイティブで作り直してみるということがありました。&lt;/p&gt;
&lt;p&gt;同様のコードをSwiftに移植して、さぞ速くなるだろうなーと思ったら激遅。JSだと1〜2秒ぐらいで終わっていた処理が6秒ぐらいかかるようになりました。&lt;/p&gt;
&lt;p&gt;実際にはもっと大きいデータを扱いたいのですが、Swift版で動かしてみると5分〜10分程度かかってしまうという自体になりました。どれだけ実装悪いんだろう、と悩みました。&lt;/p&gt;
&lt;p&gt;でもその前に、デバッグビルドであることを少し疑ってみました。きっと余計な情報が色々あるんだろうと。最適化したら速くなるだろう、と。&lt;/p&gt;
&lt;p&gt;そこでXcodeでDebugビルド時の最適化オプションを元々の&lt;code&gt;-Onone&lt;/code&gt;（No optimization）から&lt;code&gt;-O&lt;/code&gt;（Optimize for Speed）に変えてみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/XENoUtoctIIGe03JlDoZwLqsn2RlzrwRE-3mFx11KCCwqJXa06ppjYSdyFnHjPXyZ2VFcKXV-BMBcHmZs-a20qv4HbyWG-1hx5R4ipGY497Hb0M0LAuVeCINmRFEUWAolyatD3Yo2c4_W6I-gxHJ9DkkqZr5fA2cb3v6XQmjUXOuVIr4mkWFErZ2b6b0qck4X_8hraTXHJuensas3a40SOKY_Q3Y7ouAgHt2M54XSZDSrGHu6QIgGRSnt7RO6TwreaTF1A00wvUuepB-hh43nTsztqD0dl6Whx4yV-egeJjiaulamD5UvlyGdtLlthxQWUf-s_iWl-7kzhczwOav7ax6V8qgnMbyS0rTxmFnHroOZcPEPHlrEITT7F2VgEFSPn6psluhTaaATZXeIef469wLh8PPTFJ8MN01T1eg-8yZhMO3BaYptdJ--B2pJrPYikKJboRPjifRxlMLx-zzUMgSs-OLdorBjHAAmfFu-K24BpjYqgOmrvMhJwNiXMVMYWVT0QsmeW8Ca4aE9bfJHKMC4QMNl4-EAWnOeLsPrpod6szyQhI6itfZRO5u5AF17p-DUCtPHGtQVc8xk63rUWSKH0-GzD8jcLDCR1IR2NitnH7Cydj0rMduoVrNgOcZ1INDYumFI31J7Q1B7RXksb5AQv2eOJ3w=w1142-h280-no"&gt;&lt;img src="https://lh3.googleusercontent.com/XENoUtoctIIGe03JlDoZwLqsn2RlzrwRE-3mFx11KCCwqJXa06ppjYSdyFnHjPXyZ2VFcKXV-BMBcHmZs-a20qv4HbyWG-1hx5R4ipGY497Hb0M0LAuVeCINmRFEUWAolyatD3Yo2c4_W6I-gxHJ9DkkqZr5fA2cb3v6XQmjUXOuVIr4mkWFErZ2b6b0qck4X_8hraTXHJuensas3a40SOKY_Q3Y7ouAgHt2M54XSZDSrGHu6QIgGRSnt7RO6TwreaTF1A00wvUuepB-hh43nTsztqD0dl6Whx4yV-egeJjiaulamD5UvlyGdtLlthxQWUf-s_iWl-7kzhczwOav7ax6V8qgnMbyS0rTxmFnHroOZcPEPHlrEITT7F2VgEFSPn6psluhTaaATZXeIef469wLh8PPTFJ8MN01T1eg-8yZhMO3BaYptdJ--B2pJrPYikKJboRPjifRxlMLx-zzUMgSs-OLdorBjHAAmfFu-K24BpjYqgOmrvMhJwNiXMVMYWVT0QsmeW8Ca4aE9bfJHKMC4QMNl4-EAWnOeLsPrpod6szyQhI6itfZRO5u5AF17p-DUCtPHGtQVc8xk63rUWSKH0-GzD8jcLDCR1IR2NitnH7Cydj0rMduoVrNgOcZ1INDYumFI31J7Q1B7RXksb5AQv2eOJ3w=w1142-h280-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そうしたら、6秒程度かかっていた処理が0.1秒で終わるように。&lt;/p&gt;
&lt;p&gt;続いて本当に処理したいサイズのデータでもやってみると、10秒しないうちに処理が戻ってきてくれました。すばらしい。さすがにJSより遅いわけないもんね。&lt;/p&gt;
&lt;p&gt;当初は実装に難ありかと思っていましたが、ひとまず実用に耐えうるレベルだということがわかったので方針を変えなくてよさそうです。&lt;/p&gt;
&lt;p&gt;ちなみにSwiftでの時間測定はこちらの方法を参考にしました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://qiita.com/tady/items/40d7c4feecda337cf271" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFtYXpvbmF3cy5jb20lMkYwJTJGMTAyNzIlMkZwcm9maWxlLWltYWdlcyUyRjE0ODE0MTQ2OTc_aXhsaWI9cmItNC4wLjAmYXI9MSUzQTEmZml0PWNyb3AmbWFzaz1lbGxpcHNlJmJnPUZGRkZGRiZmbT1wbmczMiZzPWQ3N2JiNjEwN2E4OWE3NGZiNzUyODcyYzFkZTUzMjky%26blend-x%3D120%26blend-y%3D462%26blend-w%3D90%26blend-h%3D90%26blend-mode%3Dnormal%26mark64%3DaHR0cHM6Ly9xaWl0YS1vcmdhbml6YXRpb24taW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnMzLWFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkZxaWl0YS1vcmdhbml6YXRpb24taW1hZ2UlMkY3ZTZjOTQ2OTQzY2Y5NmJjMDU5OWJjOWMzZjllODE2MjQ1MjRkYTdlJTJGb3JpZ2luYWwuanBnJTNGMTQ0MTk2NTEwND9peGxpYj1yYi00LjAuMCZ3PTQ0Jmg9NDQmZml0PWNyb3AmbWFzaz1jb3JuZXJzJmNvcm5lci1yYWRpdXM9OCZiZz1GRkZGRkYmYm9yZGVyPTIlMkNGRkZGRkYmZm09cG5nMzImcz0wYzFhYWE5NmU3YThjODM4ZjUxZDViMjI5NzExODNlMw%26mark-x%3D186%26mark-y%3D515%26mark-w%3D40%26mark-h%3D40%26s%3Dadb31fbfe8e8a2abbd3f63384a657127?ixlib=rb-4.0.0&amp;amp;w=1200&amp;amp;fm=jpg&amp;amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9U3dpZnQlRTMlODElQTclRTklODclOEQlRTMlODElODQlRTUlODclQTYlRTclOTAlODYlRTMlODElQUUlRTUlODclQTYlRTclOTAlODYlRTYlOTklODIlRTklOTYlOTMlRTMlODIlOTIlRTYlQjglQUMlRTUlQUUlOUElRTMlODElOTklRTMlODIlOEImdHh0LWFsaWduPWxlZnQlMkN0b3AmdHh0LWNvbG9yPSUyMzFFMjEyMSZ0eHQtZm9udD1IaXJhZ2lubyUyMFNhbnMlMjBXNiZ0eHQtc2l6ZT01NiZ0eHQtcGFkPTAmcz1kMDcwZThjYTVjZmFhY2RhYjkxNWI0OTUwMzcyNmViMw&amp;amp;mark-x=120&amp;amp;mark-y=112&amp;amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDB0YWR5JnR4dC1jb2xvcj0lMjMxRTIxMjEmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9MzYmdHh0LXBhZD0wJnM9NDVkOTQ1ZjQ2MDNlMWZlZDk4Y2ZiZmU2MzVhYmViZWQ&amp;amp;blend-x=242&amp;amp;blend-y=454&amp;amp;blend-w=838&amp;amp;blend-h=46&amp;amp;blend-fit=crop&amp;amp;blend-crop=left%2Cbottom&amp;amp;blend-mode=normal&amp;amp;txt64=5qCq5byP5Lya56S-44Oq44Kv44Or44O844OI44Op44Kk44OV44K544K_44Kk44Or&amp;amp;txt-x=242&amp;amp;txt-y=539&amp;amp;txt-width=838&amp;amp;txt-clip=end%2Cellipsis&amp;amp;txt-color=%231E2121&amp;amp;txt-font=Hiragino%20Sans%20W6&amp;amp;txt-size=28&amp;amp;s=b2cb7af312fcb5f2356ffab643a5a847" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Swiftで重い処理の処理時間を測定する - Qiita&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;概要 Swiftでも、rubyのBenchmarkのように簡単に処理時間を計算するメソッドを書いた。 このメソッドを使うと、アプリの速度改善に役立つ。 Benchmarkクラス Benchmark.swift import Foundation class Ben...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;qiita.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;JS書いていたFFTのコードはこちらを参考に書き直したものを使いました。今回のSwiftのコードはさらにそのJSを書き直したものです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/wellflat/imageprocessing-labs/tree/main/cv/fft" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/88ddc011535fb3ae99ce14532e9532c2e59b123cedc193cffa9ec0199afbbc7a/wellflat/imageprocessing-labs" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;imageprocessing-labs/cv/fft at main · wellflat/imageprocessing-labs&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;computer vision, image processing and machine learning on the web browser or node. - wellflat/imageprocessing-labs&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>roo gemでxlsxファイルを読み込もうとしてundefined method `bytesize'</title><link>https://blog.piyo.tech/posts/2018-07-27-roo-rubyzip-mac-error/</link><pubDate>Fri, 27 Jul 2018 06:11:36 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-27-roo-rubyzip-mac-error/</guid><description>&lt;p&gt;Rubyでxlsxファイルを読める&lt;a href="https://github.com/roo-rb/roo"&gt;roo&lt;/a&gt;というgemでエクセルを読んでいる箇所がエラーになるようになりました。&lt;/p&gt;
&lt;p&gt;しかもローカル環境のMacでのみ発生し、AWSのAmazonLinuxやUbuntu上では問題なく動くという罠っぷり。これのおかげでだいぶハマりました。&lt;/p&gt;
&lt;p&gt;問題のはS3上に置いたエクセルをRubyで開こうとしたときで、コードはだいたいこんな感じでした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;client &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Aws&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;S3&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Client&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;region&lt;/span&gt;: region,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;access_key_id&lt;/span&gt;: access_key,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;secret_access_key&lt;/span&gt;: secret_access_ke,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;file &lt;span style="color:#f92672"&gt;=&lt;/span&gt; client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get_object(&lt;span style="color:#e6db74"&gt;bucket&lt;/span&gt;: bucket_name, &lt;span style="color:#e6db74"&gt;key&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;file.xlsx&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;spreadsheet &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Roo&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Excelx&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;body) &lt;span style="color:#75715e"&gt;# &amp;lt;= エラー発生&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最後の行で&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;undefined method `bytesize&amp;#39; for nil:NilClass
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;のエラーが発生しました。&lt;/p&gt;
&lt;p&gt;ここの&lt;code&gt;file.body&lt;/code&gt;はStringIOで、S3のファイルの中身を読むためのストリームで、少しずつ読み出す途中でエラーになっているようです。&lt;/p&gt;
&lt;p&gt;rooやrooが内部で使っているrubyzipの中に潜ってデバッグしたけどよくわからず、issueを見てもすんなりいかず困ってたんですが、同僚に相談してたらそれっぽいissueを見つけてくれました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/rubyzip/rubyzip/issues/177" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/96e117238eb9c5b55771b07cf8bbdbe75de2fe447d2f362ba1ced22d76e0540c/rubyzip/rubyzip/issues/177" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Problem with open_buffer · Issue #177 · rubyzip/rubyzip&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;I&amp;#39;m getting undefined method bytesize&amp;#39; for nil:NilClass`using open_buffer. this code works: data = string_with_zip_file ::File.open(&amp;#39;my_file.zip&amp;#39;, &amp;#34;wb&amp;#34;) {|f| f.write(data) } Zip::File.open(&amp;#39;my_file...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;このURLの&lt;code&gt;aalvarado&lt;/code&gt;さんのコメントに↓のような記載がありまして、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Roo&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Excelx&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#66d9ef"&gt;StringIO&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(xlsx_report&lt;span style="color:#f92672"&gt;.&lt;/span&gt;file_data))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;NoMethodError:
undefined method `bytesize&amp;rsquo; for nil:NilClass&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;まさに今回踏んでいる現象のように見えました。この方は&lt;code&gt;set_encoding&lt;/code&gt;でアスキー指定したら直ったということです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Roo&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Excelx&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#66d9ef"&gt;StringIO&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(xlsx_report&lt;span style="color:#f92672"&gt;.&lt;/span&gt;file_data)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_encoding(&lt;span style="color:#e6db74"&gt;&amp;#39;ASCII-8BIT&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;さて、自身のコードに戻って、&lt;code&gt;file.body&lt;/code&gt;のエンコーディングを調べてみると&lt;code&gt;UTF-8&lt;/code&gt;だということがわかりました。&lt;/p&gt;
&lt;p&gt;StackOverflowに倣って&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;body&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_encoding(&lt;span style="color:#e6db74"&gt;&amp;#39;ASCII-8BIT&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;spreadsheet &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Roo&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Excelx&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;body)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とやってあげたら見事にエラーがなくなりました。このコードはLinux上でも問題なく動いたのでそのまま採用としました。&lt;/p&gt;</description></item><item><title>GitHubで依存Gemの脆弱性をチェック</title><link>https://blog.piyo.tech/posts/2018-07-24-github-gem-vulnerabilities/</link><pubDate>Tue, 24 Jul 2018 06:59:38 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-24-github-gem-vulnerabilities/</guid><description>&lt;p&gt;だいぶ前からGitHubにて、プロジェクトが利用するGemfileの脆弱性を判定してくれるようになっています。&lt;/p&gt;
&lt;p&gt;参考までに僕が2年以上前にコミットしたサンプルプロジェクトを見てみます。
ちなみに脆弱性の情報は対象のリポジトリの権限をもっていないと表示されません。&lt;/p&gt;
&lt;p&gt;対象のプロジェクトはこちら。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/pi-chan/integration-sample-rails" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/4ddc6859ec1aa287fcdcd99dde462ea5891c584f67fef0571a54ca6f5309926f/pi-chan/integration-sample-rails" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - pi-chan/integration-sample-rails: Railsアプリケーションにdoorkeeper入れてiOSと連携できるようにするサンプルのRails側のコード&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Railsアプリケーションにdoorkeeper入れてiOSと連携できるようにするサンプルのRails側のコード - pi-chan/integration-sample-rails&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ログインしている状態でこのプロジェクトを開くと警告が表示されている状態になっています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/vUiG3YnXRQn53svG6qpoktT69JRmycdRAJ9ZuZacguqtwDlqxAev8AGLah0kWRe77Mp4s8Crfp0z2ejy-AAQfHQImmQ_Kc0wJHbUNKdjW_Mm0Asrr9oap4_F4i-UrY5BYMTZ3Jd7PZB1FIOIW0U3AVMEyeSKuVIkO0RyVM5Q0mMmHFZ5JHxSzyRyrqN8OpzK954u9-IJN3OrgfviKwf8hgooxdHYKk0Ap6giCvx9ov_bAwIi3KSxGbffcf29Y_oXRdqPtxZK1jk9yty-UuQBgXMIs_EY1zyB6Wd-XUqxg0_4vm9SLyX2YgXPv3i_9VIQcFNmW4QozOZe7SdHnmrqTa9OKdOwFLyICBTfYoWFIQiLCkNsHBtF44nVdGXdcJKwoJDnn9mwzQe0T-vwNaTwXLi10Outwpkk_avN9RHQpcXM1NZ4rHieoLVu87bB_uCp5N9d0h7C9gHvOq3cX-yHjNa2alB0iVAkhcVIcD56t1Cl3MeRuo2AMpBJMhPg_JOLGgavkvPUKbdvDONK27f5DmDA6VPuicpFIoA7ltj66iqAkGFBRlCZ5SpOkKA1pwFCBsY4yYFJpSW8UuKYRYGqahm51soY90Uz4SaCZgANrpMNOveud_JP2zhJkHJpSluu8wHklCrzRj-x0shlsItnFfKxxoQakJD1=w1992-h1062-no"&gt;&lt;img src="https://lh3.googleusercontent.com/vUiG3YnXRQn53svG6qpoktT69JRmycdRAJ9ZuZacguqtwDlqxAev8AGLah0kWRe77Mp4s8Crfp0z2ejy-AAQfHQImmQ_Kc0wJHbUNKdjW_Mm0Asrr9oap4_F4i-UrY5BYMTZ3Jd7PZB1FIOIW0U3AVMEyeSKuVIkO0RyVM5Q0mMmHFZ5JHxSzyRyrqN8OpzK954u9-IJN3OrgfviKwf8hgooxdHYKk0Ap6giCvx9ov_bAwIi3KSxGbffcf29Y_oXRdqPtxZK1jk9yty-UuQBgXMIs_EY1zyB6Wd-XUqxg0_4vm9SLyX2YgXPv3i_9VIQcFNmW4QozOZe7SdHnmrqTa9OKdOwFLyICBTfYoWFIQiLCkNsHBtF44nVdGXdcJKwoJDnn9mwzQe0T-vwNaTwXLi10Outwpkk_avN9RHQpcXM1NZ4rHieoLVu87bB_uCp5N9d0h7C9gHvOq3cX-yHjNa2alB0iVAkhcVIcD56t1Cl3MeRuo2AMpBJMhPg_JOLGgavkvPUKbdvDONK27f5DmDA6VPuicpFIoA7ltj66iqAkGFBRlCZ5SpOkKA1pwFCBsY4yYFJpSW8UuKYRYGqahm51soY90Uz4SaCZgANrpMNOveud_JP2zhJkHJpSluu8wHklCrzRj-x0shlsItnFfKxxoQakJD1=w1992-h1062-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Reviewを押すか「insights」のタブから進んでサイドメニューの「Dependency Graph」リンクをクリックすると、次のような画面となるはず。&lt;/p&gt;
&lt;p&gt;さらにそこから下線部のリンクへ進むと&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/HzXI4jl-r5dK0Cy7PNUn154p14vM66E38rkVXi3dnfbBTPX15nCSt1fVbS5RgazwXogO8d8dQxQNDuR8NleU_5uf7NT8ugOxvmaPwpNABS-NHn0ineDWeyen6mE63T-ezIjKCdqO7xwgl6MnTzhWEPQWKPwQahuNlGwCg9jNmq6A_7m-RksCu3EIKiVXyIdQrVQmXI8ZsyLwZkwRpo0bEGeOGZeoODbVcCRrpxSzj3RgDsOytfyCkVjSHML885GCgSm_gaiaCFwZLER4gw-P7okwHOImBOPhnERHcQfehP9yapDYwKSzeUBgzgNf5YSKwe38qJQ9v7Kf6P5lJGx23mb73uczwCknyUWfkP0Yab4GaKrc8pvjUt5LaFxpIsBSVFEF05KOmojV5nAtBKR03MjPSyQUFxrkYRIGedU8ezBatsTSklnfI0yiT_Lr536xfbaa23oIto5a14TaQrBerqdqd7SzAgYhJeaW559CxxTuCwr28CZwpod6fMiLR2gda0BP1xbUnHAVGi44DFXZ7wj8pY4Erel4es9nFS6_yUnjLPrHlq_UFnteZhajVVghjHTG5ItLfISdsmYDYQShvGkxjj1M0qNu4_clvWJ96YrpdjQev1StxFmTl4Jl2MYaKR9ulyAWx7tyH1in5d4N1qGC0IOxwTK1=w2064-h978-no"&gt;&lt;img src="https://lh3.googleusercontent.com/HzXI4jl-r5dK0Cy7PNUn154p14vM66E38rkVXi3dnfbBTPX15nCSt1fVbS5RgazwXogO8d8dQxQNDuR8NleU_5uf7NT8ugOxvmaPwpNABS-NHn0ineDWeyen6mE63T-ezIjKCdqO7xwgl6MnTzhWEPQWKPwQahuNlGwCg9jNmq6A_7m-RksCu3EIKiVXyIdQrVQmXI8ZsyLwZkwRpo0bEGeOGZeoODbVcCRrpxSzj3RgDsOytfyCkVjSHML885GCgSm_gaiaCFwZLER4gw-P7okwHOImBOPhnERHcQfehP9yapDYwKSzeUBgzgNf5YSKwe38qJQ9v7Kf6P5lJGx23mb73uczwCknyUWfkP0Yab4GaKrc8pvjUt5LaFxpIsBSVFEF05KOmojV5nAtBKR03MjPSyQUFxrkYRIGedU8ezBatsTSklnfI0yiT_Lr536xfbaa23oIto5a14TaQrBerqdqd7SzAgYhJeaW559CxxTuCwr28CZwpod6fMiLR2gda0BP1xbUnHAVGi44DFXZ7wj8pY4Erel4es9nFS6_yUnjLPrHlq_UFnteZhajVVghjHTG5ItLfISdsmYDYQShvGkxjj1M0qNu4_clvWJ96YrpdjQev1StxFmTl4Jl2MYaKR9ulyAWx7tyH1in5d4N1qGC0IOxwTK1=w2064-h978-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;脆弱性のあるバージョンだと判定されているGemがハイライトされた状態で並んでいます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/UviY_ws5A4f4dZiNUefsSM2YnfGbkddRzMQqLyCzjDnMZKJaZbQQO4Pn1lcMgbFQfR-RQ_nDk6zxdNs5PdTvMkqU1LR4eYJvza_-y2SlN4g8YfjI2N9zUtUq6SFKce6EtVod3cFFwH8uiaC5gBREvVIUMatR2CD23b5gdLqXZuFMUe-1Tv_7lPhjchEPhNPFOfl_Qi6A6Y2X83eL6TBytcU08gBPZo9tD985z8ixgwr8vLsDOGeWeFT_81b1MzoK47aPy2Olv-GyEWUwSlzcO9XkFOnC1OE-9df7pFMwA251CprZS27C0J6EjHLwzA1gAE295aPZMXAapeuQzRknizcppClalCVuv1_0j6ERzmWBeaZpWLb-uXUwf3MMZSQROj1-wL8rfRkNiGzPqp-gXhW1TO6wL6IwTgrbaLMs5Dx7FW8kM-pmCAydEl1q5CSILKd_LNPX0081PdQRaoAmBeEu9HWxmPpL5UiAjVWCrLn-Yk1xZhhrQ-J1Y6lP7yLwC6gx8R_SB2_8AGeRJ03LwBaS5dBo-byFOMEn2P2xbiX8Mdt2NBI4FzP7mLpZ0Ez18YjIV62dR2p8WSwwSt0s_INxIwvUh86kmw-FdGg-PoP7HCQZnJkhyMLCs_5qh9rDUf7fmIJQGjOQ1nj4doX0gh_GAo4p3y_h=w1514-h1532-no"&gt;&lt;img src="https://lh3.googleusercontent.com/UviY_ws5A4f4dZiNUefsSM2YnfGbkddRzMQqLyCzjDnMZKJaZbQQO4Pn1lcMgbFQfR-RQ_nDk6zxdNs5PdTvMkqU1LR4eYJvza_-y2SlN4g8YfjI2N9zUtUq6SFKce6EtVod3cFFwH8uiaC5gBREvVIUMatR2CD23b5gdLqXZuFMUe-1Tv_7lPhjchEPhNPFOfl_Qi6A6Y2X83eL6TBytcU08gBPZo9tD985z8ixgwr8vLsDOGeWeFT_81b1MzoK47aPy2Olv-GyEWUwSlzcO9XkFOnC1OE-9df7pFMwA251CprZS27C0J6EjHLwzA1gAE295aPZMXAapeuQzRknizcppClalCVuv1_0j6ERzmWBeaZpWLb-uXUwf3MMZSQROj1-wL8rfRkNiGzPqp-gXhW1TO6wL6IwTgrbaLMs5Dx7FW8kM-pmCAydEl1q5CSILKd_LNPX0081PdQRaoAmBeEu9HWxmPpL5UiAjVWCrLn-Yk1xZhhrQ-J1Y6lP7yLwC6gx8R_SB2_8AGeRJ03LwBaS5dBo-byFOMEn2P2xbiX8Mdt2NBI4FzP7mLpZ0Ez18YjIV62dR2p8WSwwSt0s_INxIwvUh86kmw-FdGg-PoP7HCQZnJkhyMLCs_5qh9rDUf7fmIJQGjOQ1nj4doX0gh_GAo4p3y_h=w1514-h1532-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これを解消するには対象のGemをアップグレードすれば良いので、&lt;code&gt;bundle update xxxxx&lt;/code&gt;してPushすれば解消します。
もちろんライブラリのバージョンを上げることで副作用的に不具合が起こりうるので、複数のライブラリが対象になっている場合には注意が必要な場合があります。&lt;/p&gt;
&lt;p&gt;なお、ログインしていない状態では次の画像のように警告は見えません。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/A5k4294oNPebnLowKXMxJfAGC_DUae4AdzPdryz6c7J84x8onha55DW9zIISok8qBGQ-KugdKl3bHbJJ_k56C0US--LPoc7HoV4qWUAWc5zCxPIupEvgnbtgb77rTrrFCikFEPBYMADOn_DwzkHVMTE3l0c21U5fkBHND1RhG45-0ypqJys03XnuEtE2wmDsDzIm0UIdF2mpBGbaIE68jeyTDBXkiKNHsOmzq-Rvug1APq3cUEhpG1ltLfqWrOD9ohc49xcEfuY8nfj7gtK5lbUnJzsRNnaaklR6fsM_KKuLKVT174AmAlWL9JvG5GVBXehuvUjXT_p8pdMUWo6E0gfy0gaeRB1jkll66lnrUEs6BzgDStajk_30T5g2_1I9XzoREWMckXukMG0f3cMYPxlcE_9kdRmf1mDpR7O9ay7qNFphPz_3q2QGSyV7Wg0js9vJeX7gwtxRg9sUYIOPXkUnrWVPJE8HjfFQ4QVbcJxaUIYVqwipSo8cP_oGdqOoXQcAmcivUSB4NkOqLfIM9l6aG8G-UzWSc5oibWuW0PovRrExzyPgH7v87K92A4wzr8RtfryQSVt9kgDEXO9CAqTf0H7rh8ElmzLjJ5uZuE4UfWsBuUnWYTXMOKf6CjAIlzdC8CGU4i5Z7YW9oPvCjIiRs1DwBpr0=w2040-h990-no"&gt;&lt;img src="https://lh3.googleusercontent.com/A5k4294oNPebnLowKXMxJfAGC_DUae4AdzPdryz6c7J84x8onha55DW9zIISok8qBGQ-KugdKl3bHbJJ_k56C0US--LPoc7HoV4qWUAWc5zCxPIupEvgnbtgb77rTrrFCikFEPBYMADOn_DwzkHVMTE3l0c21U5fkBHND1RhG45-0ypqJys03XnuEtE2wmDsDzIm0UIdF2mpBGbaIE68jeyTDBXkiKNHsOmzq-Rvug1APq3cUEhpG1ltLfqWrOD9ohc49xcEfuY8nfj7gtK5lbUnJzsRNnaaklR6fsM_KKuLKVT174AmAlWL9JvG5GVBXehuvUjXT_p8pdMUWo6E0gfy0gaeRB1jkll66lnrUEs6BzgDStajk_30T5g2_1I9XzoREWMckXukMG0f3cMYPxlcE_9kdRmf1mDpR7O9ay7qNFphPz_3q2QGSyV7Wg0js9vJeX7gwtxRg9sUYIOPXkUnrWVPJE8HjfFQ4QVbcJxaUIYVqwipSo8cP_oGdqOoXQcAmcivUSB4NkOqLfIM9l6aG8G-UzWSc5oibWuW0PovRrExzyPgH7v87K92A4wzr8RtfryQSVt9kgDEXO9CAqTf0H7rh8ElmzLjJ5uZuE4UfWsBuUnWYTXMOKf6CjAIlzdC8CGU4i5Z7YW9oPvCjIiRs1DwBpr0=w2040-h990-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>文書を自動チェックするtextlintを日本語の技術ブログにも使おう</title><link>https://blog.piyo.tech/posts/2018-07-23-textlint-ja-for-blog/</link><pubDate>Mon, 23 Jul 2018 06:24:43 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-23-textlint-ja-for-blog/</guid><description>&lt;p&gt;日本語にtextlintをかけると便利、という話をチラっと聞いたのでブログに応用すべく導入してみました。&lt;/p&gt;
&lt;p&gt;まず、textlint自体がこちら。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/textlint/textlint" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://repository-images.githubusercontent.com/28478929/a029f79f-6cc3-4521-b01c-32240bc0b2c9" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - textlint/textlint: textlint is the pluggable linter for natural language text.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;textlint is the pluggable linter for natural language text. - textlint/textlint&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;そして、日本語技術文書用のルールプリセットがこちらです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/textlint-ja/textlint-rule-preset-ja-technical-writing" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/3caa1208217dcaa040e153eff20347fb76a27d59d3d6c1df9610225ce9ee3635/textlint-ja/textlint-rule-preset-ja-technical-writing" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - textlint-ja/textlint-rule-preset-ja-technical-writing: 技術文書向けのtextlintルールプリセット&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;技術文書向けのtextlintルールプリセット. Contribute to textlint-ja/textlint-rule-preset-ja-technical-writing development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ブログに応用するという観点で考えると、Hugoのルートディレクトリがよさそうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% npm install textlint
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;% npm install textlint-rule-preset-ja-technical-writing
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;としてtextlint本体とルールをインストールします。&lt;code&gt;-g&lt;/code&gt;でインストールしなかったのはNetlifyで自動ビルドすることを想定したためです。&lt;/p&gt;
&lt;p&gt;次のような形でファイルやディレクトリを指定して文書チェックが可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ファイル指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;% ./node_modules/textlint/bin/textlint.js ./content/posts/xxxxxx.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ディレクトリ指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;% ./node_modules/textlint/bin/textlint.js ./content/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;試しにある日の投稿をチェックしてみると、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% ./node_modules/textlint/bin/textlint.js ./content/posts/2018-07-21-codepush.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;./content/posts/2018-07-21-codepush.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; 18:15 error 弱い表現: &lt;span style="color:#e6db74"&gt;&amp;#34;思います&amp;#34;&lt;/span&gt; が使われています。 preset-ja-technical-writing/ja-no-weak-phrase
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; 26:16 error 二重否定: 〜ないことはない preset-ja-technical-writing/no-double-negative-ja
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; 34:51 error 弱い表現: &lt;span style="color:#e6db74"&gt;&amp;#34;思います&amp;#34;&lt;/span&gt; が使われています。 preset-ja-technical-writing/ja-no-weak-phrase
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; 51:26 error 文末が&lt;span style="color:#e6db74"&gt;&amp;#34;。&amp;#34;&lt;/span&gt;で終わっていません。 preset-ja-technical-writing/ja-no-mixed-period
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;✖ &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; problems &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; errors, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; warnings&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このようにエラーが出力されます。くせになっている表現なんかがみつかるのでとても良さそう。&lt;/p&gt;
&lt;p&gt;全記事一気にチェックしたらどうなるのかなっとやってみたところ、だいぶ長いこと待たされ、こんな結果になりました。timeコマンドで時間を測ってやりましたとも。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% time ./node_modules/textlint/bin/textlint.js ./content
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;（略）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;✖ &lt;span style="color:#ae81ff"&gt;2176&lt;/span&gt; problems &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2176&lt;/span&gt; errors, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; warnings&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;✓ &lt;span style="color:#ae81ff"&gt;128&lt;/span&gt; fixable problems.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;Try to run: $ textlint --fix &lt;span style="color:#f92672"&gt;[&lt;/span&gt;file&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;./node_modules/textlint/bin/textlint.js ./content 249.03s user 45.99s system 112% cpu 4:22.55 total
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;450近くのファイルを処理するのにトータルで6分ちょいかかり、2000を超える指摘がありました。この時間、この量を考えるとNetlifyでビルド前に確認するというのはあまり現実的ではなさそうです。&lt;/p&gt;
&lt;p&gt;そうなると新しく追加する記事はチェックするとか、気が向いたときに少しずつ修正するというのが現実的な解になりそう。&lt;/p&gt;
&lt;p&gt;ちなみに先程の出力を見てみると&lt;code&gt;✓ 128 fixable problems.&lt;/code&gt;という表示が目に付きます。これは自動的に修復可能な問題箇所だということで、&lt;code&gt;--fix&lt;/code&gt;オプションをつけると自動的に直してくれるようです。&lt;/p&gt;
&lt;p&gt;早速実施してみましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;% ./node_modules/textlint/bin/textlint.js ./content --fix
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;（略）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; 42:35 ✔ 一つ &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; 1つ
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;数量を表現し、数を数えられるものは算用数字を使用します。任意の数に置き換えても通用する語句がこれに該当します。 preset-ja-technical-writing/arabic-kanji-numbers
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; 24:53 ✔ &lt;span style="color:#e6db74"&gt;&amp;#34;することができる機能&amp;#34;&lt;/span&gt;は冗長な表現です。&lt;span style="color:#e6db74"&gt;&amp;#34;することが&amp;#34;&lt;/span&gt;を省き簡潔な表現にすると文章が明瞭になります。参考: http://qiita.com/takahi-i/items/a93dc2ff42af6b93f6e0 preset-ja-technical-writing/ja-no-redundant-expression
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;（略）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;✔ Fixed &lt;span style="color:#ae81ff"&gt;128&lt;/span&gt; problems
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;✖ Remaining &lt;span style="color:#ae81ff"&gt;348&lt;/span&gt; problems
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;どうも&lt;code&gt;することができる&lt;/code&gt;という表現を使ってしまいがちなようです。&lt;/p&gt;
&lt;p&gt;textlintで細かい点を改善していきます。最後はこの記事にlintをかけてPush！&lt;/p&gt;</description></item><item><title>EasyImagyを使ってiOSでの画像の画素列を取得する</title><link>https://blog.piyo.tech/posts/2018-07-22-ios-easy-imagy/</link><pubDate>Sun, 22 Jul 2018 06:46:28 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-22-ios-easy-imagy/</guid><description>&lt;p&gt;先日React NativeでやったことのiOSネイティブ実装版です。&lt;/p&gt;
&lt;p&gt;React Native版はこれ↓&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-05-20-image-rgba-react-native/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/y_i9fp87K99TSZkeLX2ZqCVu9aZ_itzXBB_AI90I1mycnWj72EQPc8YAlSOhDnWqOR-Tq2TNtMf1dIIwIB41o-tEjMH1Ahn90cPMyM-T83elsZBhs66peHCP2VfVWTT4R0OYwI65EU58kiApaDCGtXZLbQpBpg8mw4amb_Pu0o83H9sPVmkb8vDO08dFJoAeBghTwl0RJZFBzLPAvEo1yySRpKa1haI95sy4tF0fQD3H0VZF7yenhWdUvJtHk86DqtZGGZxA1KDPKFQ0MGBn6Q6vM785kgN1rWzWHxjmehqWLagVnwbhhBSukD-6rTB00p714JTqnff0BIK411edZRmzPaCaPzEbeM_i6WmbR6LcWPn-J5U7qn2O5GFjTpNF8ef0gvqD0dww9pNYC6yU1aFoyac9A1BVBzCHO5OoUgOVqn3PzE0fIv_J4twqGMYW2X34-yi11r2ZLbw9bbBGbz4lsuWSoGAyrMPvdwOPGG9eFn5MsLIK_-fMRmSDGeaDTi4yBa4-jw2xAy4HSi1VBSZkThJEuqm8nQdjd1u1Fz2cAtg2rVAdOfomS7FmFR_3i8UxLTUtNtU55U9Yc5wLwtZDOYz80cMG3PEP5g-5sYTEsOQ-fhil_IVIzdI-TCO2bmvTsvO0EwcM9SZXjZnEDFMANWVUPGfq3g=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;React Nativeで画像のRGBA値を得る - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;React Nativeで画像のRGBA値が欲しくて調べてたら react-native-image-tools というライブラリを見つけました。 https://github.com/Benjamin-Lin-X/react-native-image-tools かなり名前が近い別パッケージもあるので混同注意です。 1 % npm -i react-native-image-tool 2 % react-native link react-native-image-tool で導入できます。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;んで、Swift版なんですが、いい感じに実装してくれている&lt;code&gt;EasyImagy&lt;/code&gt;というライブラリを見つけたのでこれを試してみました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/koher/swift-image" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/33fb281e4230e150b22fd06e174a200b33369ff065487613fe66dee5eb92cfc9/koher/swift-image" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - koher/swift-image: SwiftImage: an image library in Swift with Swifty APIs and value semantics&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;SwiftImage: an image library in Swift with Swifty APIs and value semantics - koher/swift-image&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;日本の方っぽいですね。ありがたや。&lt;/p&gt;
&lt;p&gt;お試し用の画像としては以下を使います。画素がはっきりしているのでわかりやすくて良いんです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://imgur.com/download/OSEiha9"&gt;https://imgur.com/download/OSEiha9&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://imgur.com/download/OSEiha9"&gt;&lt;img src="https://imgur.com/download/OSEiha9" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;UIImage&lt;/code&gt;や&lt;code&gt;Data&lt;/code&gt;などを使ってインスタンスを初期化しうると画素を取れるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// UIImageの場合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;image = Image&amp;lt;RGBA&amp;lt;UInt8&amp;gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(uiImage: imageView.image!)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;各色の列を取り出してテキストに出力してみました。&lt;code&gt;UITextView&lt;/code&gt;を縦に4つ並べて雑に書き出しています。対象のViewController全体のコードは↓のようになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EasyImagy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EasyImagyViewController&lt;/span&gt;: UIViewController {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBOutlet&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; redText: UITextView!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBOutlet&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; greenText: UITextView!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBOutlet&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; blueText: UITextView!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBOutlet&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; alphaText: UITextView!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.viewDidLoad()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; uiImage : UIImage = #imageLiteral(resourceName: &lt;span style="color:#e6db74"&gt;&amp;#34;image&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; image = Image&amp;lt;RGBA&amp;lt;UInt8&amp;gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(uiImage: uiImage)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; redText.text = &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;image.map { $0.redInt }&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; greenText.text = &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;image.map { $0.greenInt }&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; blueText.text = &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;image.map { $0.blueInt }&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; alphaText.text = &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;image.map { $0.alphaInt }&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;結果このようになりました。各色のデータとわかるように色をつけています。最後はAlphaです。それぞれをIntで出しているので0〜255の範囲になっています。見た感じちゃんと取れていそうですね。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/irfNrcQLxdFIlda1u4Wrmum0_h8i5AeJb4i0wwCfK61LFOBr7WlE7Pks24bZowU2sC5Z-ID9XQaGBtJOLqzFbKXqjsx8zJJohcq0icNjhzCZAURsUTZq6c590RhBeeFUvXfFUvVWv5fQ7s1FlpneXMUCi_EhRfecOcAxz8Behua_RMZEsNrptFGE1qs2CUYGNnhBPaaiEgTO0JqOo7ileaKlhmfjvfQt5Hko2s04ejH6CQdRuW2bRhH_d35MMAofor4juEK1gfBOEdga0Rx6ncOvVWj4WcA7XZbytqYEZA-rcQ14wrcMeaD69OnnB8ctB0L3VCYbqvBo1r49IjW1XjKkjRQDDNE_CPmWIqD9L7AAsoAako56Lv50YdB6yPN63sb1jGpJY_cfv9p-UlJTYU2436S2PYemalSFZ4kNfST-BczCAfnewXJglQ21dXUpXxlP77P3AayU4k8Jg0JqNux7oydIuxsbWoilZ7VVuLHPYhNr4Q8bX-T1vyRpMutzuwMF_QpGI3W23zq9x1EV0tI4CSfeK5AuQNHN4KlaNwHn1h3Vlte-XqijyA8DOffiHzYSoCshaVhRVMGQpvapnj5s7ACm7jFHvn3qBQf8PSE4-Gt5af80vJxs1Nkh4Jch7_EEDoGaUvZdxpjiwgzOgT3LI4qhwDc_7Q=w172-h371-no"&gt;&lt;img src="https://lh3.googleusercontent.com/irfNrcQLxdFIlda1u4Wrmum0_h8i5AeJb4i0wwCfK61LFOBr7WlE7Pks24bZowU2sC5Z-ID9XQaGBtJOLqzFbKXqjsx8zJJohcq0icNjhzCZAURsUTZq6c590RhBeeFUvXfFUvVWv5fQ7s1FlpneXMUCi_EhRfecOcAxz8Behua_RMZEsNrptFGE1qs2CUYGNnhBPaaiEgTO0JqOo7ileaKlhmfjvfQt5Hko2s04ejH6CQdRuW2bRhH_d35MMAofor4juEK1gfBOEdga0Rx6ncOvVWj4WcA7XZbytqYEZA-rcQ14wrcMeaD69OnnB8ctB0L3VCYbqvBo1r49IjW1XjKkjRQDDNE_CPmWIqD9L7AAsoAako56Lv50YdB6yPN63sb1jGpJY_cfv9p-UlJTYU2436S2PYemalSFZ4kNfST-BczCAfnewXJglQ21dXUpXxlP77P3AayU4k8Jg0JqNux7oydIuxsbWoilZ7VVuLHPYhNr4Q8bX-T1vyRpMutzuwMF_QpGI3W23zq9x1EV0tI4CSfeK5AuQNHN4KlaNwHn1h3Vlte-XqijyA8DOffiHzYSoCshaVhRVMGQpvapnj5s7ACm7jFHvn3qBQf8PSE4-Gt5af80vJxs1Nkh4Jch7_EEDoGaUvZdxpjiwgzOgT3LI4qhwDc_7Q=w172-h371-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ソースはこちらに。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/pi-chan/ios-sandbox2" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/52f22ccaa7c5d4ca6eeba721a2b6f6fe8e1d591d0c0165f280ca57636177adfa/pi-chan/ios-sandbox2" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - pi-chan/ios-sandbox2&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Contribute to pi-chan/ios-sandbox2 development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>SGTechにて「CodePushでリリース楽しようぜ」的な話をしてきました</title><link>https://blog.piyo.tech/posts/2018-07-21-codepush/</link><pubDate>Sat, 21 Jul 2018 06:48:13 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-21-codepush/</guid><description>&lt;p&gt;してきたというか、開催したというか、そんな感じです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-06-28-sgtech-hamamatsu/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/xo_UAcuXo_3bTbDK40vd9TX5nA8A23R-wGqtlM856Ddp6UWOdjZEF_1O1f-qKHfMWsR7UQluS3IEUV7Eboz2SiqisFGlkvgxrlmdhn0bKIk4-dtHNN50n4S28fxAILAnrw2GFhyeTKla5F3nTcP45mSrq77aqO6zSKMZx-hun4wHEpokcbqdkisdu5CH6y8_mSCUSrnDI2k9cCzSsmsVZILp94jYURgXrGbTQMDx8iavkjiuc1LyNoQdToNfHqsbA-JLmrsLD-RZYkogskUNEWuN5tBOfQ2B_U8Nb31v9K5Fbp-hyQuhCFGD3snnEzDo9ChQoWGCUmeGGUL431sEPa0AMWCCETgGVLTKJr109cB0RzKCQWgXkfZfETcqP0FMALCupikvezvltzR2X0VYd-CcybMLKUWf_RbFKqVhj7eUAW91VHMIeOcHKnXozY3kNLsT1YfHXrWVMewzcU62b_oWHfwMvDB-zrZBGWXnCfUxp7qPLqmvKhvobS3oVOy1irqtBUEz6p9QVConisL_Z3E7r5mLOYG8FZGExo_jCCaIQgx8KO6rzBcx6YxaHky4TMd_jop8yNMZma7FYOUtLKFHeaQfp4OU0nqHQwAzjXKI0Lu1z8Qc-YYrnWG8vxk2mzKyi2iT4SIx53tFxeXvNSOX85iLJlEt=w718-h377-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;7月14日に「SonicGarden Tech 2＠浜松」開催します - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;僕の住む浜松にてSonicGarden Techというイベントの第2回を開催します。今回はReact Nativeをテーマとしています。 ↓↓詳細や参加登録はこちらから↓↓ https://sonicgarden.connpass.com/event/87520/ テーマはReact Nativeですが、ソニックガーデンのメンバーとの交流も兼ねたイベントでもあります。社長はじめエンジニアが数人来て話す予定です。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-07-16-sgtech-hamamatsu/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/nKmhvVgws18XAToZGAfX99wKStkAtDDChg28eMu08NoH-S8eOmeIMqvKii1KIn05UGEWjyXzeQTlyL3x3uPwRSQfl3Ay6kTlz46GIcm894-_52DnCS_iTyVglfo8ZOJpeOPrnKP3vUd5UIZaiZWN9Fm8KFPN65XluEIm5BhgvJpE4yJP5EdT3I_vspO5kPMyvjEKD80V_W5poHoeeGiwBKctLClqlqmnnhqadZdsWa4yVRcJkYnSnu9X4uonDPXXjm0nh8-4xv87wDmHxu0nC6IDqtHmWrhEF0vxjmGw0bCzR5Quzry-VO2Qq4_W7SyVYZprBvxZUhwGrGvX6Nq_0OrZqWM8gDmJ9tvMMbVCQUoGWnF8qv_mIneQkgzsNP-7nJiIO6TGFnRmp12GpW0oAqDnKROA-TAaC9dgUB5PGLePy9Zad31tY3BFUU1hYwF_HZKcz8Ob3j460Z5sDUAQAM4OVSps0LaPMN78gPKr4vEE1sEEJAATI7YDqWoUW3vW5KaMiHUW7PR6MjrYkg16IgIuT5fHDA0gaPU78S_CoJs-bZrPP9F585hRzK5WbozyAbQETEFJMCrhNU3sGgecQQTK24X_jzh7RVOe-TF82G_6o-8FtOY3-fpUS4w_T17k554pP-lu4spC7WaYTPDMDseQMv7hlcygWA=w2104-h1710-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;地元浜松にてSonicGarden Techを開催しました - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;7/14に僕の住む浜松市でSonicGarden Techの第2回を開催し、僕自身も発表して来ました。React NativeがテーマということでCode Pushに関する話をしました。 React NativeのJSとNativeの関係 Code Pushの概要 みたいな話をしています。そのときのスライドはこちらです。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;↑の記事にも載せたスライドを再掲します。&lt;/p&gt;
&lt;script async class="speakerdeck-embed" data-id="a72135006aa543e1b0f4aecd8902c0aa" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"&gt;&lt;/script&gt;
&lt;p&gt;見てもらえば概要はわかるかと思いますが、3行でまとめるとこんな感じ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;アプリ（っていうかiOS）のリリースがめんどい、ちょっとした変更を出すのが億劫&lt;/li&gt;
&lt;li&gt;React NativeだとメインのJS部分がネイティブから独立してるから差し替えられる&lt;/li&gt;
&lt;li&gt;差し替える仕組みとしてCode Pushってのがあるよ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;実際に僕が開発しているアプリではちょっとした不具合修正とかレイアウトの調整みたいなものだけでなく、新しい機能のための1画面を追加するぐらいの勢いでCode Pushを使っています。&lt;/p&gt;
&lt;p&gt;とはいえデメリットもないことはないので、今日はデメリットをちょっとだけ紹介します。&lt;/p&gt;
&lt;h3 id="リジェクトの可能性がわずかながらある"&gt;リジェクトの可能性がわずかながらある&lt;/h3&gt;
&lt;p&gt;これは当日話しました。codepushのIssueにあるように、リジェクトされたという声がときどきあるようです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/microsoft/react-native-code-push/issues/1297" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/a3b9f72bf7125f922bbdfcebd610a1301c51c4331fd3ebe924a61193873108e8/microsoft/react-native-code-push/issues/1297" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Code Push is rejected by Apple again? · Issue #1297 · microsoft/react-native-code-push&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;I submitted a new update to my app and it is rejected by the 2.5.2 guideline and section 3.3.2 agreement. In particular, they asked me to remove all the classes related to Code Push ... Does anyone...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ですが、多くの人はそんなことないよと言っているようなので、これはあまり大きなデメリットにはならないと思います。&lt;/p&gt;
&lt;h3 id="アプリを壊すことがある"&gt;アプリを壊すことがある&lt;/h3&gt;
&lt;p&gt;Code Pushによるアプリ（JS）の更新が行われるのはアプリ起動後に非同期で行われます。その間にアプリの起動自体は動き続けますので、一旦起動したあと画面の読み直しが入るような動きになります。&lt;/p&gt;
&lt;p&gt;（正確にいうと、Code Pushを使っても必ずこのようになるわけではありません。ユーザーに確認を求めたり、次の起動時まで反映しないというやり方も可能です。）&lt;/p&gt;
&lt;p&gt;アプリが壊れるタイミングは、アプリが起動時の処理にバグを含むようなバージョンをCode Pushで配信してしまった場合です。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;正常に起動するバージョンでアプリを起動する&lt;/li&gt;
&lt;li&gt;裏でCode Pushによる更新が入る&lt;/li&gt;
&lt;li&gt;アプリが読み直される&lt;/li&gt;
&lt;li&gt;バグにより起動しない&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;となって起動しなくなります。&lt;/p&gt;
&lt;p&gt;その後Code Pushで修正版を配信したとしても、&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;アプリを起動する&lt;/li&gt;
&lt;li&gt;アプリが死ぬ&lt;/li&gt;
&lt;li&gt;&lt;del&gt;裏でCode Pushによる更新が入る&lt;/del&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Code Pushの更新前にアプリが死ぬため永久にバグったままとなります。&lt;/p&gt;
&lt;p&gt;こうなってしまうとネイティブビルドで配るほかありませんので、通常のネイティブアプリの更新と同じような手順でアップデートしなければなりません。&lt;/p&gt;
&lt;p&gt;気軽に配れるのが仇になる例でした。&lt;/p&gt;</description></item><item><title>プライムデーで買ったフォームローラー（安い版）で筋膜リリース</title><link>https://blog.piyo.tech/posts/2018-07-20-foam-roller-/</link><pubDate>Fri, 20 Jul 2018 06:12:15 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-20-foam-roller-/</guid><description>&lt;p&gt;腰痛肩こり対策のために予てから欲しかったフォームローラー。先日のプライムデーで正規品じゃないけど安いやつを見つけたので1個買いました。&lt;/p&gt;
&lt;p&gt;今回買ったのがこれで、プライムデーで半額ぐらいになっていて、1000円以下で購入。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B01IOXUOAU/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/51xXoGVlElL._AC_SL1000_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;GronG(グロング) フォームローラー 筋膜リリース ローラー ヨガポール Foam Roller オレンジ&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;正規品だと5000円以上することが多いのでだいぶお買い得です。正規品の良さは当然あるでしょうけど、お値段が気軽じゃないのよね。&lt;/p&gt;
&lt;p&gt;ちなみに正規品はこれ。微妙に凹凸の形は配置が異なります。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B01A8DSRYO/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/61WpCOEK9lL._AC_SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;トリガーポイント(TRIGGERPOINT) グリッド フォームローラー ストレッチローラー セルフケア リカバリー EVA素材 高耐久 スポーツ デスクワーク対応&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;このローラーを使った筋膜リリースをする際にはこちらの記事を参考にしています。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://shogokoba.com/blog/archives/395" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;shogokoba.com →&lt;/span&gt;&lt;span&gt;https://shogokoba.com/blog/archives/395&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;パーソナルトレーナーをしている方が動画つきで紹介してくれています。そしてよく効きます。&lt;/p&gt;
&lt;p&gt;一番オススメはこの腰痛予防の記事に書いてある中殿筋の筋膜リリースです。中殿筋は座るときに常に収縮しているので、デスクワークの人は大体硬いらしい。整体なんかに行ったときもこの場所をぐーっと押されることが多いです。ちょっと刺激強いけどテニスボールとかでも代用できるはず。おすすめです。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://shogokoba.com/blog/archives/227" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;shogokoba.com →&lt;/span&gt;&lt;span&gt;https://shogokoba.com/blog/archives/227&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>Railsでメールを配信する直前に処理を挟んで加工する方法</title><link>https://blog.piyo.tech/posts/2018-07-19-mail-interceptor/</link><pubDate>Thu, 19 Jul 2018 06:40:35 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-19-mail-interceptor/</guid><description>&lt;p&gt;RailsGuideにも記述があるのですが、Railsでメールを送る前に任意の処理を挟む方法があります。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://railsguides.jp/action_mailer_basics.html" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://railsguides.jp/images/cover_for_facebook.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Action Mailer の基礎 - Railsガイド&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Action Mailerを使ってメールを送受信する方法について解説します。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://railsguides.jp/railsguides/images/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;railsguides.jp&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;self.delivering_email&lt;/code&gt;を定義したクラスを用意しておいて、ActionMailerに登録しておくと送信前に呼んでくれるようになります。登録するのは&lt;code&gt;delivering_email&lt;/code&gt;に応答するクラスであればなんでもいいはずです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ロードパスのどこか&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;HogehogeInterceptor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;delivering_email&lt;/span&gt;(message)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 何かする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# initallizerのどこか&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ActionMailer&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;register_interceptor(&lt;span style="color:#66d9ef"&gt;SandboxEmailInterceptor&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;env&lt;span style="color:#f92672"&gt;.&lt;/span&gt;staging?
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="サブジェクトを加工する"&gt;サブジェクトを加工する&lt;/h2&gt;
&lt;p&gt;引数に渡ってくる&lt;code&gt;message&lt;/code&gt;は&lt;code&gt;Mail::Message&lt;/code&gt;のインスタンスで、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;subject&lt;/li&gt;
&lt;li&gt;body&lt;/li&gt;
&lt;li&gt;from&lt;/li&gt;
&lt;li&gt;to&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などの値を変更できます。&lt;/p&gt;
&lt;p&gt;よくメールのサブジェクトに&lt;code&gt;【サービス名】&lt;/code&gt;みたいなのをつけて、&lt;code&gt;【サービス名】登録完了のお知らせ&lt;/code&gt;として送るようなケースがあるかと思います。&lt;/p&gt;
&lt;p&gt;Interceptorでは&lt;code&gt;message.subject&lt;/code&gt;を↓のように加工することで、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SubjectInterceptor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;delivering_email&lt;/span&gt;(message)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; message&lt;span style="color:#f92672"&gt;.&lt;/span&gt;subject &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;【サービス名】&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; message&lt;span style="color:#f92672"&gt;.&lt;/span&gt;subject
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;全てのメールに一括で挿入でき、メールが増えたときにも個別対応が要らないのでとても楽です。&lt;/p&gt;
&lt;h2 id="メール送信をやめる"&gt;メール送信をやめる&lt;/h2&gt;
&lt;p&gt;あまりない例になっちゃって申し訳ないですが、例えば夜間はメール送信しないみたいなことがもしかしたらあるかもしれません。ステージング環境とか。&lt;/p&gt;
&lt;p&gt;そういった場合にはInteceptorにて&lt;code&gt;message.perform_deliveries&lt;/code&gt;を&lt;code&gt;false&lt;/code&gt;にしてあげるとメールが送られなくなります。↓こんな感じ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NightTimeInterceptor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;delivering_email&lt;/span&gt;(message)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; hour &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Time&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;current&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hour
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; hour &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; hour &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; message&lt;span style="color:#f92672"&gt;.&lt;/span&gt;perform_deliveries &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;他にも活用できそうですけど、考えたのはこのぐらいです。&lt;/p&gt;</description></item><item><title>Webで複数選択するためのBootstrap Dual Listboxが便利</title><link>https://blog.piyo.tech/posts/2018-07-18-duallistbox/</link><pubDate>Wed, 18 Jul 2018 06:09:18 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-18-duallistbox/</guid><description>&lt;p&gt;複数選択、通常の&lt;code&gt;select&lt;/code&gt;タグを&lt;code&gt;multiple&lt;/code&gt;にすれば選択可能ですが、あまりかっこよくないです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;select&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;list&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;size&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;multiple&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;option&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&amp;gt;選択肢1&amp;lt;/&lt;span style="color:#f92672"&gt;option&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;option&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;2&amp;#34;&lt;/span&gt;&amp;gt;選択肢2&amp;lt;/&lt;span style="color:#f92672"&gt;option&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;option&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;3&amp;#34;&lt;/span&gt;&amp;gt;選択肢3&amp;lt;/&lt;span style="color:#f92672"&gt;option&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;option&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;4&amp;#34;&lt;/span&gt;&amp;gt;選択肢4&amp;lt;/&lt;span style="color:#f92672"&gt;option&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;option&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;5&amp;#34;&lt;/span&gt;&amp;gt;選択肢5&amp;lt;/&lt;span style="color:#f92672"&gt;option&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;select&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/-P0idP6fPYTjvc4cy_XKj_ShWC2kVXsYgrGN1Z3og08YxlMBR_jv8Zv-tT0mhbO_fA1VV63iCv1u9dEDkHrWnuYlNZ4KLNh0wF7INzOADHsSCUsju9l1lOWgNhrZhiCugBnmigVM_IdF9Isl_vq0AkeHQ0CFdBg4c-yRVX-BwEiYSuqWZ6EctFJn8L_ImejmIAeOtKptgEZG5iegbG8BjZWC_wvBB88need12pi-JFiaN7vAgrYBWXZJT7low-UbbbtLLoKpqOvynHB3BcV6vW2HLc0eCc1Ly9iaN2tnCcBCLOSxEsPodQv-SamLlkpSSjQX3B6U-sS1kWXSjNZYmRUmMPt53rj2L6qB5B_IwBcV-kgK2Jqf3TGQ0AT9yvmN1RQnL8WYKrE5BqLaVUuZ9NvA9bOKKRPDFAOB-t-17IUlvHUWPhk_3HRY4P0S2imc5GYE42QQXIdNF-n9RcAT-Y-4cE5c3FVFluI47_Q6P46UXPRKhIp6kfluvx7u6GexrHtuLgheYDtS94gEqWVNLkTHTjRJRoQcAr1o8Ad420U03DxJgu6fduScxt_qm7Dri5_FDI26rLGJ-f_sArElLVFBq9LUMYWTtaZABll3AfmybbO8OLKBVm5adHTD6snjihYO0OulFRkN1Y5NpF04GxIa_4c6Htgq=w342-h325-no"&gt;&lt;img src="https://lh3.googleusercontent.com/-P0idP6fPYTjvc4cy_XKj_ShWC2kVXsYgrGN1Z3og08YxlMBR_jv8Zv-tT0mhbO_fA1VV63iCv1u9dEDkHrWnuYlNZ4KLNh0wF7INzOADHsSCUsju9l1lOWgNhrZhiCugBnmigVM_IdF9Isl_vq0AkeHQ0CFdBg4c-yRVX-BwEiYSuqWZ6EctFJn8L_ImejmIAeOtKptgEZG5iegbG8BjZWC_wvBB88need12pi-JFiaN7vAgrYBWXZJT7low-UbbbtLLoKpqOvynHB3BcV6vW2HLc0eCc1Ly9iaN2tnCcBCLOSxEsPodQv-SamLlkpSSjQX3B6U-sS1kWXSjNZYmRUmMPt53rj2L6qB5B_IwBcV-kgK2Jqf3TGQ0AT9yvmN1RQnL8WYKrE5BqLaVUuZ9NvA9bOKKRPDFAOB-t-17IUlvHUWPhk_3HRY4P0S2imc5GYE42QQXIdNF-n9RcAT-Y-4cE5c3FVFluI47_Q6P46UXPRKhIp6kfluvx7u6GexrHtuLgheYDtS94gEqWVNLkTHTjRJRoQcAr1o8Ad420U03DxJgu6fduScxt_qm7Dri5_FDI26rLGJ-f_sArElLVFBq9LUMYWTtaZABll3AfmybbO8OLKBVm5adHTD6snjihYO0OulFRkN1Y5NpF04GxIa_4c6Htgq=w342-h325-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そこでDual Listboxです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="http://www.virtuosoft.eu/code/bootstrap-duallistbox/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="http://www.virtuosoft.eu/code/bootstrap-duallistbox/preview/bootstrap-duallistbox.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Bootstrap Dual Listbox&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Bootstrap Dual Listbox is a responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://www.virtuosoft.eu/favicon.ico?v=2" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;www.virtuosoft.eu&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;こちらはBootstrapベースのコントロールで、左右に並んだリストがあって選択済みを右側のリストに入れていくようなコントロールです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;select&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;list2&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;duallistbox&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;size&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;multiple&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;option&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&amp;gt;選択肢1&amp;lt;/&lt;span style="color:#f92672"&gt;option&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;option&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;2&amp;#34;&lt;/span&gt;&amp;gt;選択肢2&amp;lt;/&lt;span style="color:#f92672"&gt;option&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;option&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;3&amp;#34;&lt;/span&gt;&amp;gt;選択肢3&amp;lt;/&lt;span style="color:#f92672"&gt;option&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;option&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;4&amp;#34;&lt;/span&gt;&amp;gt;選択肢4&amp;lt;/&lt;span style="color:#f92672"&gt;option&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;option&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;5&amp;#34;&lt;/span&gt;&amp;gt;選択肢5&amp;lt;/&lt;span style="color:#f92672"&gt;option&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;select&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(document).&lt;span style="color:#a6e22e"&gt;ready&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;#duallistbox&amp;#34;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;bootstrapDualListbox&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/xaHTiDYdzoLQ5o_zG6pqCqo42uSI4_ltvOTZoG_LOK2hC68McP-ULV3Vj-azSQNB1qFYGl9XbbZiGn-_HUdBOPEE7eeWcsspGmRrTZBnX9BYuG_irBDrRhPu25-39z8hnIFB6N7hvP_8wFD-LwQk4bRxgTqLTgJmn79ssKEQHpo-6A7PVciogRt_6-2FcEkQByM0YKfMVrHQbzgD46au3S0zZxVYdVKoZsG8Xry8L5oR8p_M71TIKkZvvFTEL-MFdJtvb9W_GIuyF2htLV-R4gSmyvmKteDpVpjtwVcs_OSwL-9kT99uf4w2qGCWyOqb2D0pfphQLZorz1DuiVHCF7-8QPw4keJUmv1FrHu0wXQxdMidH3H6o-qinmPujpxyLCEX8y1Ouxo96FI6VKwc_yhVq7-rZc1c1t53EKIX5Rs-QqnEMKrq-eOMTXDI2FyBVD3CjR9-5vcPEAMg5PyZZZCk6m1mkzSwCR9Oalj4vD1UT-8HnRO-ChyT2hNSmLQV2IT-MyLL14WNQoMeCCiU0Vwtdg44r8W1fvEdhpVSyBNpSe5TImdf1R2KngzL14JgrihqgvTfjRqVVbF91MAQtwp4TCM2GNoDIrfj77RX5eM0_NDvbDircco0g3oqLDOQc-1xTsP-yafJqPN2vDEAGR9HKljWkBLn=w744-h412-no"&gt;&lt;img src="https://lh3.googleusercontent.com/xaHTiDYdzoLQ5o_zG6pqCqo42uSI4_ltvOTZoG_LOK2hC68McP-ULV3Vj-azSQNB1qFYGl9XbbZiGn-_HUdBOPEE7eeWcsspGmRrTZBnX9BYuG_irBDrRhPu25-39z8hnIFB6N7hvP_8wFD-LwQk4bRxgTqLTgJmn79ssKEQHpo-6A7PVciogRt_6-2FcEkQByM0YKfMVrHQbzgD46au3S0zZxVYdVKoZsG8Xry8L5oR8p_M71TIKkZvvFTEL-MFdJtvb9W_GIuyF2htLV-R4gSmyvmKteDpVpjtwVcs_OSwL-9kT99uf4w2qGCWyOqb2D0pfphQLZorz1DuiVHCF7-8QPw4keJUmv1FrHu0wXQxdMidH3H6o-qinmPujpxyLCEX8y1Ouxo96FI6VKwc_yhVq7-rZc1c1t53EKIX5Rs-QqnEMKrq-eOMTXDI2FyBVD3CjR9-5vcPEAMg5PyZZZCk6m1mkzSwCR9Oalj4vD1UT-8HnRO-ChyT2hNSmLQV2IT-MyLL14WNQoMeCCiU0Vwtdg44r8W1fvEdhpVSyBNpSe5TImdf1R2KngzL14JgrihqgvTfjRqVVbF91MAQtwp4TCM2GNoDIrfj77RX5eM0_NDvbDircco0g3oqLDOQc-1xTsP-yafJqPN2vDEAGR9HKljWkBLn=w744-h412-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;右側が選択済みのリストです。通常の&lt;code&gt;select&lt;/code&gt;タグだとctrlやcmdを押しながらクリックしてないといけないですが、DualListboxだとクリックだけで追加削除ができます。&lt;/p&gt;
&lt;p&gt;その他一括追加や絞り込みなどいろいろな機能を必要に応じて有効にできます。&lt;/p&gt;</description></item><item><title>iOSで画面表示されているUIViewをUIImageに変換する</title><link>https://blog.piyo.tech/posts/2018-07-17-ios-capture-uiview/</link><pubDate>Tue, 17 Jul 2018 06:06:35 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-17-ios-capture-uiview/</guid><description>&lt;p&gt;iOSのUIをそのまま画像にする方法です。AVCaptureOutputで撮った写真と何かのViewを合成した画像を出したいみたいなときに使えます。&lt;/p&gt;
&lt;p&gt;以下のコードでUIImageに変換ができます。ここでのViewは色々なSubviewなんかが入っている、画像として取り出したいViewです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;convertToUIImage&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; view: UIView) -&amp;gt; UIImage {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; UIGraphicsBeginImageContext(view.bounds.size)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; context = UIGraphicsGetCurrentContext()&lt;span style="color:#f92672"&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; view.layer.render(&lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;: context)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; image = UIGraphicsGetImageFromCurrentImageContext()&lt;span style="color:#f92672"&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; UIGraphicsEndImageContext()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; image
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ところが、これだと画面上のサイズそのままで出力されてしまいます。Retinaディスプレイなど解像度が高いディスプレイではその倍の情報があるにも関わらず半分になってしまいます。例えば画面上で300x300のViewであれば600x600の画像にできるはずなのですが、↑の書き方だと300x300になってしまう。&lt;/p&gt;
&lt;p&gt;これだと勿体ないので少し変更します。&lt;code&gt;UIGraphicsBeginImageContext&lt;/code&gt;するところを、&lt;code&gt;UIGraphicsBeginImageContextWithOptions&lt;/code&gt;を使ってスケールの指定をします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Before&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// UIGraphicsBeginImageContext(view.bounds.size)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// After&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;UIGraphicsBeginImageContextWithOptions(view.bounds.size, &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;3番目の引数の0がスケールで、ここをゼロにすると端末のスクリーンに応じてスケールを変えてくれるそうです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://docs.developer.apple.com/documentation/uikit/uigraphicsbeginimagecontextwithoptions%28_:_:_:%29" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://docs.developer.apple.com/tutorials/developer-og.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;UIGraphicsBeginImageContextWithOptions(_:_:_:) | Apple Developer Documentation&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Creates a bitmap-based graphics context with the specified options.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://developer.apple.com/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;developer.apple.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>地元浜松にてSonicGarden Techを開催しました</title><link>https://blog.piyo.tech/posts/2018-07-16-sgtech-hamamatsu/</link><pubDate>Mon, 16 Jul 2018 06:36:47 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-16-sgtech-hamamatsu/</guid><description>&lt;p&gt;7/14に僕の住む浜松市でSonicGarden Techの第2回を開催し、僕自身も発表して来ました。React NativeがテーマということでCode Pushに関する話をしました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;React NativeのJSとNativeの関係&lt;/li&gt;
&lt;li&gt;Code Pushの概要&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;みたいな話をしています。そのときのスライドはこちらです。&lt;/p&gt;
&lt;script async class="speakerdeck-embed" data-id="a72135006aa543e1b0f4aecd8902c0aa" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"&gt;&lt;/script&gt;
&lt;p&gt;詳細は気が向いたら別途書こうかなーと思います。&lt;/p&gt;
&lt;p&gt;またこの勉強会では、前日から宿泊して行っていた社内ハッカソンで作った質問サイトを使って匿名で質問を受け付けられるようにしました。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="http://www.meetup-qa.com/p/meetups/UX1hSg5uFQrsQbFtZX6YcpPF" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;www.meetup-qa.com →&lt;/span&gt;&lt;span&gt;http://www.meetup-qa.com/p/meetups/UX1hSg5uFQrsQbFtZX6YcpPF&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;発表者としてはフィードバックが何もないとつらい、質問する人にとっては質問するハードルが高い、初歩的だと思われることをききにくいという課題は勉強会におけるあるあるだと思います。質疑は誰かがまとめない限り残されないことが多いはず。そのあたりを解決するためにこのサイトを作りました。&lt;/p&gt;
&lt;p&gt;まだまだ粗い部分が多いですが（OGPもないし）、少なくとも今回の勉強会ではよく使えていた気がします。&lt;/p&gt;
&lt;p&gt;とはいえ、改善点も色々ありそうですね。&lt;/p&gt;
&lt;p&gt;例えば質問に答えたはけど意図が合っているかどうかわからないことがありました。匿名とはいえ、場合によっては質問者の方を探して意図を確認したり、回答からさらに踏み込んだ議論ができるともっとよさそうです。&lt;/p&gt;
&lt;p&gt;他に感じたのはTwitterが静かになることですね。皆さんQAのサイトに書いてくれるためダイレクトに反応がえられるのですが、せっかくのハッシュタグに投稿が少ないような気がしました。&lt;/p&gt;
&lt;p&gt;というのはまたこれから考えていきます。&lt;/p&gt;
&lt;p&gt;SonicGarden Techはこれからも開催予定です。次回のテーマはまだ決まっていませんが、メンバーがいるどこかの地方で実施するはずです。ウワサでは次回は福岡だとか、そうじゃないとか。奮ってご参加ください。&lt;/p&gt;
&lt;h2 id="以下余談"&gt;以下余談&lt;/h2&gt;
&lt;p&gt;今回の合宿は僕ともう一人のメンバーが夏ぐらいにハッカソンでもやろうという話から場所が決まり、他のメンバーも決まり、せっかく集まるなら勉強会でも開いて地域の人と交流しようということで、最終的には合宿→勉強会という流れになりました。&lt;/p&gt;
&lt;p&gt;開発と観光を織り交ぜつつ、濃い時間を過ごせました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;さわやか&lt;/li&gt;
&lt;li&gt;ハッカソン&lt;/li&gt;
&lt;li&gt;温泉&lt;/li&gt;
&lt;li&gt;うなぎ&lt;/li&gt;
&lt;li&gt;勉強会&lt;/li&gt;
&lt;li&gt;懇親会&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;特にソニックガーデンのメンバーを（静岡県民のソウルフードである）炭焼きハンバーグのさわやかに連れていけたので非常に満足です。&lt;/p&gt;</description></item><item><title>iOSのカメラでLightroomのように撮影条件を変更する</title><link>https://blog.piyo.tech/posts/2018-07-15-ios-camera-like-lightroom/</link><pubDate>Sun, 15 Jul 2018 06:36:57 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-15-ios-camera-like-lightroom/</guid><description>&lt;p&gt;iOSのカメラというかAVFoundationにはAdobeのLightroomアプリのようにホワイトバランスやシャッタースピードなどをカスタマイズするAPIがあります。&lt;/p&gt;
&lt;p&gt;ドキュメントを読んでみて難しい部分があったので整理しておこうと思います。&lt;/p&gt;
&lt;h1 id="lightroom"&gt;Lightroom&lt;/h1&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://itunes.apple.com/jp/app/adobe-lightroom-cc/id878783582?mt=8" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;itunes.apple.com →&lt;/span&gt;&lt;span&gt;https://itunes.apple.com/jp/app/adobe-lightroom-cc/id878783582?mt=8&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;LightroomのiPhone版では撮影時に微調整しながら撮影できます。&lt;/p&gt;
&lt;p&gt;↑の矢印部分をタップしてプロに切り替える（元々はAuto）と、シャッタースピードやISO感度、ホワイトバランスを調整するコントロールが現れます。ここで色々いじると設定を変えられるわけですね。&lt;/p&gt;
&lt;h1 id="iosでの実装"&gt;iOSでの実装&lt;/h1&gt;
&lt;h2 id="ベース部分"&gt;ベース部分&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;AVFoundation&lt;/code&gt;の&lt;code&gt;AVCapturePhotoOutput&lt;/code&gt;を使います。よくあるコードなので特に解説しませんが、こんな感じになりますよね。&lt;/p&gt;
&lt;p&gt;deviceの設定をする&lt;code&gt;configureDevice&lt;/code&gt;というfunctionが最後にあります。今はオートフォーカスを有効にすることしかしていませんが、ここで色々設定を変更していきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UIKit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AVFoundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CameraViewController&lt;/span&gt;: AppViewController {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; captureSession = AVCaptureSession()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; photoOutput : AVCapturePhotoOutput!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.viewDidLoad()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; configure()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;viewWillAppear&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; animated: Bool) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; captureSession.startRunning()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.viewWillAppear(animated)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;viewWillDisappear&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; animated: Bool) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; captureSession.stopRunning()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.viewWillDisappear(animated)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getDevice&lt;/span&gt;() -&amp;gt; AVCaptureDevice? {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; discoverSession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera, .builtInTelephotoCamera, .builtInWideAngleCamera], mediaType: .video, position: .back)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; discoverSession.devices.first
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;configure&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; device = getDevice() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt; device.lockForConfiguration()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.configureDevice(device: device)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; device.unlockForConfiguration()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt; { print(&lt;span style="color:#e6db74"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; input = &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt; AVCaptureDeviceInput(device: device)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; captureSession.addInput(input)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt; { print(&lt;span style="color:#e6db74"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;42&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;43&lt;/span&gt;&lt;span&gt; photoOutput = AVCapturePhotoOutput()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;44&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; captureSession.canAddOutput(photoOutput) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;45&lt;/span&gt;&lt;span&gt; captureSession.addOutput(photoOutput)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;46&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;47&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; captureVideoLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer.&lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(session: captureSession)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;48&lt;/span&gt;&lt;span&gt; captureVideoLayer.frame = &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.imageView.bounds
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;49&lt;/span&gt;&lt;span&gt; captureVideoLayer.videoGravity = .resizeAspectFill
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;50&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.imageView.layer.addSublayer(captureVideoLayer)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;51&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;52&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;53&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;54&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;55&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;configureDevice&lt;/span&gt;(device: AVCaptureDevice) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;56&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; device.isFocusModeSupported(.continuousAutoFocus) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;57&lt;/span&gt;&lt;span&gt; device.focusMode = .continuousAutoFocus
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;58&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;59&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;60&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// その他設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;61&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;62&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="シャッタースピードとiso"&gt;シャッタースピードとISO&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;AVCaptureDevice&lt;/code&gt;の&lt;code&gt;setExposureModeCustom&lt;/code&gt;を使います。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://docs.developer.apple.com/documentation/avfoundation/avcapturedevice/setexposuremodecustom%28duration:iso:completionhandler:%29" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://docs.developer.apple.com/tutorials/developer-og.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;setExposureModeCustom(duration:iso:completionHandler:) | Apple Developer Documentation&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Sets the exposure mode to a custom state, and locks exposure duration and ISO at explicit values.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://developer.apple.com/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;developer.apple.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;先程の&lt;code&gt;configureDevice&lt;/code&gt;に追記するとして、たとえばシャッタースピードを1/400、ISOを800にするのであれば↓のように設定できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; shutterSpeed = CMTimeMake(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;400&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;device.setExposureModeCustom(duration: shutterSpeed, iso: &lt;span style="color:#ae81ff"&gt;800&lt;/span&gt;, completionHandler: &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ホワイトバランス"&gt;ホワイトバランス&lt;/h2&gt;
&lt;p&gt;ホワイトバランスのほうは少々厄介でして、iOS側のAPIは&lt;code&gt;WhiteBlanceGains&lt;/code&gt;というstructを使用します。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://docs.developer.apple.com/documentation/avfoundation/avcapturedevice/whitebalancegains" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://docs.developer.apple.com/tutorials/developer-og.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;AVCaptureDevice.WhiteBalanceGains | Apple Developer Documentation&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;A structure that defines RGB white balance gain values.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://developer.apple.com/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;developer.apple.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Lightroomのアプリにおけるホワイトバランスの設定は「蛍光灯」や「昼光」など、色温度ベースとなっています。そこで色温度などから&lt;code&gt;WhiteBalanceGains&lt;/code&gt;に変換する必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; k = &lt;span style="color:#ae81ff"&gt;6000&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 色温度&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; tint = &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#75715e"&gt;// -150.0〜+ 150.0の範囲のホワイトバランスの色合い値&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; values = AVCaptureDevice.WhiteBalanceTemperatureAndTintValues(temperature: k, tint: tint)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; gains = device.deviceWhiteBalanceGains(&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;: values)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;device.setWhiteBalanceModeLocked(with: gains, completionHandler: &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;まず、&lt;code&gt;AVCaptureDevice.WhiteBalanceTemperatureAndTintValues&lt;/code&gt;を色温度と色合いの値を使って初期化し、それを元にWhiteBalanceGainsにします。次に&lt;code&gt;setWhiteBalanceModeLocked&lt;/code&gt;によりホワイトバランスを設定します。&lt;/p&gt;
&lt;p&gt;こちらは色温度だけでなくtintValueの影響もあるので欲しい設定にするには微調整が必要そう。&lt;/p&gt;
&lt;p&gt;ともかくこれでよくやりそうな設定は変更できました。&lt;/p&gt;</description></item><item><title>forestry.ioのCMSでブログを修正したら公開日のタイムゾーンが変わってしまう</title><link>https://blog.piyo.tech/posts/2018-07-14-forestry-timezone/</link><pubDate>Sat, 14 Jul 2018 06:37:16 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-14-forestry-timezone/</guid><description>&lt;p&gt;普段はPCで書いているブログですが、たまにスマホでチェックしてて誤字に気づくことがあります。そんなときはそのままスマホで修正できるようにforestry.ioのCMS機能を使います。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-04-10-forestry-cms/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/8bjrRn14UbCydhgopSyjRUb3NZ-U4-yoWjxgmohyzKR_Ezf4GaQ01xywkmXzSTJeN-8ecL574T0b_UmB6srl-rCcWAVOs0kp1cwICaeoA53nk4e5Dg__FKTs57gaZR5d6XPXFFKNf6-7uCxeoZfbazBrlKCoK0AeY4Q4Vjepv2DuP6N74rhc_c5dbOwnvNkw5OmHyNSZPKEjDAgS4JVeQBXWVI7XiPaN2RM2sgvAfQPtMgkpOlyZsmAMv42PCsgEQQvLMaKLdag5k8vztUP0rcYotLNEfzIhgM9CcN32LEPvyG3YSQzhqHiGQ_EH7L8uiVfcf_euMXBG2bzRuK1ChBqbl6-PvcyPw0DLHw0xBoFiwhq70RTp9ibXyPlVVbF_o50xvbNZtchb5z1m6QgLCm8aM-Q9EAz4-Fe4RxrWIFITP1Gq9r3vVgFeKKliTYbCexkoOWJnZ47_qapJnXWvoZJOQQSoVdw97VhFCR11Y-iG0Q7Igcg5qn4JAcLk798HWsJFDIdXbNMI7DkhUEyet1VkuFrPYatdWuaZIEfgPRtI4I3opnqi7yQX7y8OQ4L1H1rXfmToPcjw-voZTQfu-Hzb3x_Cmtc7_l0NOf_ZU6giy90SaAfRzDvhsj3dUrtkYGK-C4rmzJtJBk3XMNUT-TTGW4fybJncYw=w647-h340-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;forestry.ioでHugoブログにCMS機能を一瞬で追加した - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;description Hugoのブログは手元で書いてNetlifyビルドしてNetlifyで配信しています。ちょっとしたした修正もPCが必要なのが不便だったのでCMS機能をforestry.ioで用意しました。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;これは便利で手軽で良いんですが、forestry側で修正すると公開日情報のタイムゾーンが変わってしまうという現象が起きていました。&lt;/p&gt;
&lt;p&gt;だいたい朝7時頃公開するつもりで自動ビルドをかけていますので、ブログのメタデータには、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;date: 2018-07-14T07:00:00+09:00
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;のように書いてあります。このpostをforestryで修正した場合には&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;date: 2018-07-13 22:00:00 +0000
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;のように変わります。指し示す時刻は変わっていないもののタイムゾーンが変わっちゃうんですよね。これで何が起こるかというと、ブログの公開日が変わってしまいます。7/13の記事ですって出したいのに7/12と出てしまう。&lt;/p&gt;
&lt;p&gt;なんか気持ち悪いので直したいと思いforestryの設定画面にいったらタイムゾーンの設定欄がありました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/vTh8JheYrPeXveUMcWPFx49AeOFRWcbhKyPWNZgF_RVtA0GYMMCzIJGmiUdm50i01Ocm_hMLlEIPkwlhy_HYcxXauEePeOq5MyPpyVK5gje0mbdPMEoNMdJI4RNXFBxdEw7fmFTlUEE-TOh4PfdzF8xo3186SHHtQ4JmJE0-fKpoNqVxsSpcNRV7cObf5IhHIijrjYVHsVPXScwNzINfjf9KBTOJIB0SLL2nxU172EPjHBJFH6XpTzWGKivAHBpkymEDyLGUkpcnU-KOV7acHZo9jE_wjZNYUpDVjV31eoia-CBOGXT1FIclIeTf5j92d90jic-iXY9l7BehcTRYlVghbORZHGvLgeRjNHYmYARSHQY09y8DnKZ_9-p-lr62Jf-U_1QVz0dYnIWGm08UsDZhVwdlgYEgx2BkoWaT-LGABocEzdqiFtTazSwqH5VthvYedVCWfJK3i8-Ay6_hsXGbE-Cdf3AzYNtVTuPfnDCIlWh_zdr1nCljxrpftB3BjaHOgg72i7DFFgTzqNOYfxQD7bdNuNftXnx9uYbC9airMSq6TTW9fmXsIB_8xUimcQlY9jU14WMxXKwvKrG4jd0MlDncVfcbK7poSwjZUC2OD_dE2BykQB4pplQ0TTG7_NonBofx3_eVAiGNxeU6Ua2CMceyz1PE=w1252-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/vTh8JheYrPeXveUMcWPFx49AeOFRWcbhKyPWNZgF_RVtA0GYMMCzIJGmiUdm50i01Ocm_hMLlEIPkwlhy_HYcxXauEePeOq5MyPpyVK5gje0mbdPMEoNMdJI4RNXFBxdEw7fmFTlUEE-TOh4PfdzF8xo3186SHHtQ4JmJE0-fKpoNqVxsSpcNRV7cObf5IhHIijrjYVHsVPXScwNzINfjf9KBTOJIB0SLL2nxU172EPjHBJFH6XpTzWGKivAHBpkymEDyLGUkpcnU-KOV7acHZo9jE_wjZNYUpDVjV31eoia-CBOGXT1FIclIeTf5j92d90jic-iXY9l7BehcTRYlVghbORZHGvLgeRjNHYmYARSHQY09y8DnKZ_9-p-lr62Jf-U_1QVz0dYnIWGm08UsDZhVwdlgYEgx2BkoWaT-LGABocEzdqiFtTazSwqH5VthvYedVCWfJK3i8-Ay6_hsXGbE-Cdf3AzYNtVTuPfnDCIlWh_zdr1nCljxrpftB3BjaHOgg72i7DFFgTzqNOYfxQD7bdNuNftXnx9uYbC9airMSq6TTW9fmXsIB_8xUimcQlY9jU14WMxXKwvKrG4jd0MlDncVfcbK7poSwjZUC2OD_dE2BykQB4pplQ0TTG7_NonBofx3_eVAiGNxeU6Ua2CMceyz1PE=w1252-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここで日本のタイムゾーンを選んでおけばおそらく問題ないでしょう。ちなみに、本来Tokyoを選べびたかったのですが、なぜかOsakaしか選べませんでした。&lt;/p&gt;</description></item><item><title>Chart.jsなどのWeb用のJSライブラリをReact Nativeで使う</title><link>https://blog.piyo.tech/posts/2018-07-13-chartjs-on-react-native/</link><pubDate>Fri, 13 Jul 2018 06:18:33 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-13-chartjs-on-react-native/</guid><description>&lt;p&gt;React Nativeでチャート（グラフ）を描画するためのライブラリがいくつかあります。例えばこのへんとか↓&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/JesperLekland/react-native-svg-charts"&gt;JesperLekland/react-native-svg-charts: 📈 One library to rule all charts for React Native 📊&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;とはいうものの、できることが少なかったりなかなか思うようにいかないことがあったりします。&lt;/p&gt;
&lt;p&gt;WebにもJSのチャート系ライブラリはいくつかあります。例えば有償のHighchartsなんかはかなり協力です。これから登場するChart.jsのようにMITライセンスのものもあります。&lt;/p&gt;
&lt;p&gt;そういったWebのライブラリを使ったほうが案外良い結果になることもあるかも、という提言として今回の例を紹介してみます。&lt;/p&gt;
&lt;p&gt;React NativeにはWebViewがあるため、Javascriptを有効にした状態で通常のWebと同じHTMLをレンダリングすることが可能です。そのHTML内でChart.jsをロードし、Webでのようにデータを登録することでグラフを描画できてしまいます。&lt;/p&gt;
&lt;p&gt;ちょっと長いですが、まずコードから見てみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt;, { &lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;PropTypes&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;View&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;WebView&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Dimensions&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react-native&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;width&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Dimensions&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;window&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ChartView&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;chartHTML&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`&amp;lt;html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;meta name=&amp;#34;viewport&amp;#34; content=&amp;#34;width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no&amp;#34; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;style media=&amp;#34;screen&amp;#34; type=&amp;#34;text/css&amp;#34;&amp;gt;#container{width:100%;height:100%;top:0;left:0;right:0;bottom:0;position:absolute;}&amp;lt;/style&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;script src=&amp;#34;https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; document.addEventListener(&amp;#34;DOMContentLoaded&amp;#34;, function() {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; var ctx = document.getElementById(&amp;#34;container&amp;#34;).getContext(&amp;#39;2d&amp;#39;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; var myChart = new Chart(ctx, {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; type: &amp;#39;bar&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; data: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; labels: [&amp;#34;Red&amp;#34;, &amp;#34;Blue&amp;#34;, &amp;#34;Yellow&amp;#34;, &amp;#34;Green&amp;#34;, &amp;#34;Purple&amp;#34;, &amp;#34;Orange&amp;#34;],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; datasets: [{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; label: &amp;#39;# of Votes&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; data: [12, 19, 3, 5, 2, 3],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; backgroundColor: [
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#39;rgba(255, 99, 132, 0.2)&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#39;rgba(54, 162, 235, 0.2)&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#39;rgba(255, 206, 86, 0.2)&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#39;rgba(75, 192, 192, 0.2)&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#39;rgba(153, 102, 255, 0.2)&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#39;rgba(255, 159, 64, 0.2)&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; borderColor: [
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#39;rgba(255,99,132,1)&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#39;rgba(54, 162, 235, 1)&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#39;rgba(255, 206, 86, 1)&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#39;rgba(75, 192, 192, 1)&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#39;rgba(153, 102, 255, 1)&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#39;rgba(255, 159, 64, 1)&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; borderWidth: 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;42&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; options: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;43&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; scales: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;44&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; yAxes: [{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;45&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ticks: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;46&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; beginAtZero:true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;47&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;48&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;49&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;50&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;51&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;52&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;53&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;/script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;54&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;/head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;55&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;56&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;canvas id=&amp;#34;container&amp;#34; width=&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;width&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34; height=&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;width&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;57&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;58&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;/html&amp;gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;59&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;60&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;61&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;62&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;chartHTML&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;63&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;64&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;View&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;}&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;65&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;WebView&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;66&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{&lt;span style="color:#a6e22e"&gt;flex&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;backgroundColor&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;transparent&amp;#39;&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;67&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;source&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;baseUrl&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;web/&amp;#39;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;68&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;originWhitelist&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{[&lt;span style="color:#e6db74"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;]}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;69&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;javaScriptEnabled&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;70&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;domStorageEnabled&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;71&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;scalesPageToFit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;72&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;scrollEnabled&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;73&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;automaticallyAdjustContentInsets&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;74&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;75&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/View&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;76&lt;/span&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;77&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;78&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;render()&lt;/code&gt;では実質的に&lt;code&gt;WebView&lt;/code&gt;しかありません。そこで&lt;code&gt;source&lt;/code&gt;プロパティにhtml文字列を渡します。中身は&lt;code&gt;chartHTML()&lt;/code&gt;に書いてあります。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;の中に&lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;が1個だけあり、&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;に描画内容が書いてあるという感じです。割と力技です。&lt;/p&gt;
&lt;p&gt;中身はこちらのドキュメントのサンプルをそのまま転載しています。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="http://www.chartjs.org/docs/latest/#creating-a-chart" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Chart.js | Chart.js&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Open source HTML5 Charts for your website&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="http://www.chartjs.org/docs/latest/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;www.chartjs.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;で、画面はというと次のようになります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/VFJJAMQ4CeSbSUGLJ9gngyP5WNA4JBgT8PnMscgI5XT2csRNBc524vPwyYpMstkjiaP2OscBXH213waRxXxcX8it7GhMut0Py8H8LOJ9tZC2ptYN2DD1l0X1-sKhRl8my4FjGhl_qh4Jhc4rXSe0XfqIQO5nrmhyR7iT0yEn7I4M5quVs37D3Wh88X6APxlWxfWnfYFZyB0bLL8EyyoHdCtVeNIE_UO54vukqdVPZlOqI1SKvsetnLT_U0ySzPQbYBZDQI92G95F2MmYbFJ3oN53IgCyGt9cqbXINUyfbVcFDZpEPh3RwqAUDt6P30piro8YySEs93WN1it23tEJPGfwomcHJ4sT7GuIcqGevx-heDl1VthXi6uyfM-KgfXptjxtKhFCbXtOTdSEEpNY2vi-fRaIt5UBBsD4uV9k01RWh-Gl-IQeVHNck18Sbg0oOzAaWWHfsKkMk5BOS7v1G052SbSFySkWz9TVgj8wTY5perjHWG6Yzs1IVfNeWrZW4IU6Al9QAQKwpwZ_Kwf9v0VgsIDAb0exzYqKOnw7KjS0D5UX9ljes0YtXxSygB9mLSwpcaHOOMb4MKFwN2XGcSkSu_msussovE1wxUhDPgpYJqIoxc8QJOxoX5oMd5ox2p349lR92KqKIz78WakxXGEMQ8llIgQS=w750-h1334-no"&gt;&lt;img src="https://lh3.googleusercontent.com/VFJJAMQ4CeSbSUGLJ9gngyP5WNA4JBgT8PnMscgI5XT2csRNBc524vPwyYpMstkjiaP2OscBXH213waRxXxcX8it7GhMut0Py8H8LOJ9tZC2ptYN2DD1l0X1-sKhRl8my4FjGhl_qh4Jhc4rXSe0XfqIQO5nrmhyR7iT0yEn7I4M5quVs37D3Wh88X6APxlWxfWnfYFZyB0bLL8EyyoHdCtVeNIE_UO54vukqdVPZlOqI1SKvsetnLT_U0ySzPQbYBZDQI92G95F2MmYbFJ3oN53IgCyGt9cqbXINUyfbVcFDZpEPh3RwqAUDt6P30piro8YySEs93WN1it23tEJPGfwomcHJ4sT7GuIcqGevx-heDl1VthXi6uyfM-KgfXptjxtKhFCbXtOTdSEEpNY2vi-fRaIt5UBBsD4uV9k01RWh-Gl-IQeVHNck18Sbg0oOzAaWWHfsKkMk5BOS7v1G052SbSFySkWz9TVgj8wTY5perjHWG6Yzs1IVfNeWrZW4IU6Al9QAQKwpwZ_Kwf9v0VgsIDAb0exzYqKOnw7KjS0D5UX9ljes0YtXxSygB9mLSwpcaHOOMb4MKFwN2XGcSkSu_msussovE1wxUhDPgpYJqIoxc8QJOxoX5oMd5ox2p349lR92KqKIz78WakxXGEMQ8llIgQS=w750-h1334-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;タップ操作で自然に反応してくれるため思ったより使い勝手が良いです。&lt;/p&gt;
&lt;p&gt;ただし、今のコードはCDNからライブラリを読むためネットワークが必要です。オフラインでも使えるようなアプリにする場合はライブラリのコードをなんとかしてアプリに入れておく必要があるので工夫が必要のはず。うまくいかない可能性もありそう。未検証です。&lt;/p&gt;
&lt;p&gt;canvasに描画するようなタイプのライブラリを使いたいような場合には案外現実的な選択肢にしてもいいのではないかと個人的には思います。&lt;/p&gt;</description></item><item><title>React NativeでMarkdownを表示する方法をいくつか比較してみた</title><link>https://blog.piyo.tech/posts/2018-07-12-markdown-on-react-native/</link><pubDate>Thu, 12 Jul 2018 06:31:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-12-markdown-on-react-native/</guid><description>&lt;p&gt;GitHubのようにMarkdownが書けるようなサイトが増えています。僕の働いているソニックガーデンが使っているオフィスツールRemottyでもMarkdownのような記法を一部サポートしています。&lt;/p&gt;
&lt;p&gt;WebでMarkdownを扱うにはMarkdown形式の文字列をサーバーサイドなりクライアントサイドでHTML化して表示するだけなのでとても簡単です。また、
ただのHTMLなのでCSSにより見た目もかなり柔軟に変えることができます。&lt;/p&gt;
&lt;p&gt;ではReact Nativeアプリではどうしたらいいだろうか、というのが最近の課題です。実はRemottyのモバイルアプリでちょっとしたマークダウン的なものをどのように表示すべきなのかというのは悩んでいて、現状では開発した当時一番マシかなと思ったものを使っています。&lt;/p&gt;
&lt;p&gt;Markdownを表示するためにライブラリ（または標準コンポーネント）を使います。使い方には大きく2通りあって、Markdown文字列のまま処理してくれるものと一度HTMLに変換してHTMLをレンダリングするものとがあります。さらに内部実装でHTMLを表示できるWebViewを使っているのかMarkdownからHTMLにして、そのHTMLの構文解析をしてコンポーネント化しているのか、という分類もできそうです。&lt;/p&gt;
&lt;p&gt;ライブラリはこのあたりで検索します。また、Googleでも色々と検索してヒットしたものを使ってみました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/jondot/awesome-react-native" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/dc24926ebc2190585d51ef6a62769338a79bbb7e742b7cae007dd646a1b6ad51/jondot/awesome-react-native" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - jondot/awesome-react-native: Awesome React Native components, news, tools, and learning material!&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Awesome React Native components, news, tools, and learning material! - jondot/awesome-react-native&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;今日は以下の6種類を比較してみます。と言ってもメンテされていなくて最新のRNでは動かないものもあります。一部手元で手直しすれば動いたものもあるので補足しつつ書いてみます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Markdownで渡す系
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/CharlesMangwa/react-native-simple-markdown"&gt;react-native-simple-markdown&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jerolimov/react-native-showdown"&gt;react-native-showdown&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mientjan/react-native-markdown-renderer"&gt;react-native-markdown-renderer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;HTMLで渡す系
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jsdf/react-native-htmlview"&gt;react-native-htmlview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/iou90/react-native-autoheight-webview"&gt;react-native-autoheight-webview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://facebook.github.io/react-native/docs/webview.html"&gt;WebView&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="前提"&gt;前提&lt;/h1&gt;
&lt;p&gt;Markdownのサンプルとして、いくつかの要素を含んだ次のようなものを考えます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;markdown&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;# 見出し
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;- 箇条書き
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; - 入れ子
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; - 入れ子
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;- 箇条書き
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;- 箇条書き
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;[Google](https://www.google.co.jp/)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;gt; 引用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;**太字太字**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;![画像](https://blog.piyo.tech/images/prof.png)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;せめてこのぐらいはちゃんと表示してほしいなという気持ちで例文を作りました。&lt;/p&gt;
&lt;p&gt;また、HTMLを受け取るコンポーネントがあるため、このMarkdown文字列をmarkedライブラリに食わせてHTML化します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;marked&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;markdown&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ライブラリの使い方は全部シンプルなのでドキュメントをみてくれれば大丈夫です。特に紹介しません。&lt;/p&gt;
&lt;p&gt;また、各ライブラリはそれぞれスタイルの調整はある程度できそうですが、一旦は何も指定しない状態で試しています。&lt;/p&gt;
&lt;h1 id="markdownで渡す系"&gt;Markdownで渡す系&lt;/h1&gt;
&lt;h2 id="react-native-simple-markdown"&gt;react-native-simple-markdown&lt;/h2&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/CharlesMangwa/react-native-simple-markdown" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/dfa82b6035f76b7843bff3fad6f8a3ea88614e813a422b728e4150c03807a9df/CharlesMangwa/react-native-simple-markdown" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - CharlesMangwa/react-native-simple-markdown: 📜 React Native Markdown component (iOS &amp;amp; Android).&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;📜 React Native Markdown component (iOS &amp;amp; Android). - CharlesMangwa/react-native-simple-markdown&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;コードが古いせいか使えませんでした。残念。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/03DJ0Evho1sMU3Zk9CrGVbj42RFHskSfiLtI8Y8TU2xwgiA4L0RnytIHNK_SoVhSqk0guUaGqdLlyCpRJbs-uSMIFKQL2ERbIG-jsHCPhVjtJKIcGq6ql0y5COBfhEYmgeZrrMacJkxetqxPk8AHPMZPtJU08X72RKZlARsD8LMOQbsOCdXEYAEn3QxqsBFq1fZkSAkk-GkqOLZpH25ddYXoeiM8hSTTkMAYC41tWKOCMVpjgndTVKwCy563-mBKngrP5SoDNeYKEvNn-pcc1w8oxJagcrhGUic7fVBviPi_qCfGTHC4GgRRIj9MSX7K01MNTPAeDAuJEg9p9pbJGZZ7SS03gRDLGzGTTxgFHky3UexRluXV6liNVVhxhGDmQsvsS6HRp98h556zDjw6rD8IoFfUE3lvD4XBjmGhD80EDSQxrgx1qLDLfkU7w0rTWkBTX7wN8NkVy6jiVhph-L4QDoz5Ssgf1yfaeBS8k82iaB8gCAWdwxp5U134p-FamQDGxxpNbT8OozrdfBUgVc3gAdk33L5MZ3zsLlFtlbCLQ5UHBLSJhx4uk_vl-YsSEnb7DLmLmWiQRGKhfIDxTH6HBK6OYuaAlub54wj6DbYuxO43XBFwq0o0rxkXIRhTKJezNpo7-dZ3QRf1YKKMmcLsHDkRj3Vz=w522-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/03DJ0Evho1sMU3Zk9CrGVbj42RFHskSfiLtI8Y8TU2xwgiA4L0RnytIHNK_SoVhSqk0guUaGqdLlyCpRJbs-uSMIFKQL2ERbIG-jsHCPhVjtJKIcGq6ql0y5COBfhEYmgeZrrMacJkxetqxPk8AHPMZPtJU08X72RKZlARsD8LMOQbsOCdXEYAEn3QxqsBFq1fZkSAkk-GkqOLZpH25ddYXoeiM8hSTTkMAYC41tWKOCMVpjgndTVKwCy563-mBKngrP5SoDNeYKEvNn-pcc1w8oxJagcrhGUic7fVBviPi_qCfGTHC4GgRRIj9MSX7K01MNTPAeDAuJEg9p9pbJGZZ7SS03gRDLGzGTTxgFHky3UexRluXV6liNVVhxhGDmQsvsS6HRp98h556zDjw6rD8IoFfUE3lvD4XBjmGhD80EDSQxrgx1qLDLfkU7w0rTWkBTX7wN8NkVy6jiVhph-L4QDoz5Ssgf1yfaeBS8k82iaB8gCAWdwxp5U134p-FamQDGxxpNbT8OozrdfBUgVc3gAdk33L5MZ3zsLlFtlbCLQ5UHBLSJhx4uk_vl-YsSEnb7DLmLmWiQRGKhfIDxTH6HBK6OYuaAlub54wj6DbYuxO43XBFwq0o0rxkXIRhTKJezNpo7-dZ3QRf1YKKMmcLsHDkRj3Vz=w522-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="react-native-showdown"&gt;react-native-showdown&lt;/h2&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/christoph-jerolimov/react-native-showdown" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/b40034f128c806ef18e9306e16186703c9466df4e9bbf9ae55eba6cb96f97d5b/christoph-jerolimov/react-native-showdown" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - christoph-jerolimov/react-native-showdown: React-native component which renders markdown into a webview!&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;React-native component which renders markdown into a webview! - christoph-jerolimov/react-native-showdown&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;こちらは実はそのままでは警告により正しく描画されません。内部的にReact NativeのWebViewが使われています。最近のWebViewはHTML文字列を使う際には&lt;code&gt;originWhitelist={\\\['\\\*'\\\]}&lt;/code&gt;というプロパティが必要になったため、警告が出ていました。&lt;/p&gt;
&lt;p&gt;その箇所を（行儀が悪いですが）ローカルで修正し実行したのがこちらです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/i5opNVZI2YCbDWPu6zQqRukRSSIXMOAr6JWj3Yq_LET-35ysSh3CrqFDuuKGl_pztRBFE0G1zW3yRhJuT9R7-HTieM85PeBvUHI9SfmO_Wa8MpCBZY7DEYYqbGQQY6yhd42YayJwNVr4Ixi9H21tGjSrCXT7bER3rwlV5822R8V73hR9tfgfq1OnWGV4Z1wzXRzLJs6d4-wXQWP0czOnAPpiW7JHXh_dwOFTwpj7nsEA9V3O_V0Bg3MazJmfVKHe_VhKfkeHLuYquoTIqn219VGaU0ie5FEbYPbaDNQxo2-YBsmv_EeRBvK5x0PgPZ3WtqnVwYZBLad6JjSGR3wIrgZFCLrtZTofJ-dss1X498RpcpKN68vAMb7y1fVqWaK2USBquXEqm5OllQZYIWosUJUHMRqiRBUkX2yWfyjPL3d22E2YmiedYTC7f6ZHODFYTshKiQkil9P8NTofcnkr92Fi5Vzv_fz5pQShH3TMaKZm83OEY3g9TqwHsmhQrUINb0XtqD1j1f4g69L9FP0g1XDsw0c8LF4TTsPXmbY5aTFQQipG-skhgid19F6TB52jhPr34GW3zQ___Pi6KJmb0y8NCIyO9V097xGVdYwCOwKOLt-Rd2GIfLVdCtPuPjzRd2R9StMDhX1z0m865oTlPCHarVR-l_Uo=w522-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/i5opNVZI2YCbDWPu6zQqRukRSSIXMOAr6JWj3Yq_LET-35ysSh3CrqFDuuKGl_pztRBFE0G1zW3yRhJuT9R7-HTieM85PeBvUHI9SfmO_Wa8MpCBZY7DEYYqbGQQY6yhd42YayJwNVr4Ixi9H21tGjSrCXT7bER3rwlV5822R8V73hR9tfgfq1OnWGV4Z1wzXRzLJs6d4-wXQWP0czOnAPpiW7JHXh_dwOFTwpj7nsEA9V3O_V0Bg3MazJmfVKHe_VhKfkeHLuYquoTIqn219VGaU0ie5FEbYPbaDNQxo2-YBsmv_EeRBvK5x0PgPZ3WtqnVwYZBLad6JjSGR3wIrgZFCLrtZTofJ-dss1X498RpcpKN68vAMb7y1fVqWaK2USBquXEqm5OllQZYIWosUJUHMRqiRBUkX2yWfyjPL3d22E2YmiedYTC7f6ZHODFYTshKiQkil9P8NTofcnkr92Fi5Vzv_fz5pQShH3TMaKZm83OEY3g9TqwHsmhQrUINb0XtqD1j1f4g69L9FP0g1XDsw0c8LF4TTsPXmbY5aTFQQipG-skhgid19F6TB52jhPr34GW3zQ___Pi6KJmb0y8NCIyO9V097xGVdYwCOwKOLt-Rd2GIfLVdCtPuPjzRd2R9StMDhX1z0m865oTlPCHarVR-l_Uo=w522-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="react-native-markdown-renderer"&gt;react-native-markdown-renderer&lt;/h2&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/mientjan/react-native-markdown-renderer" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/d63a2fffd6de40b5a79c6c7abaaf9f5b6d742d0f6fe744763cd07e9cc9d6e4e7/mientjan/react-native-markdown-renderer" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - mientjan/react-native-markdown-renderer: React Native 100% compatible CommonMark renderer&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;React Native 100% compatible CommonMark renderer. Contribute to mientjan/react-native-markdown-renderer development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;こちらはMarkdownを一度HTMLにパースした後、HTMLのツリー構造を解釈して適切なReact Nativeコンポーネントに置き換えるようなことを（どうやら）やってくれているように見えます。&lt;/p&gt;
&lt;p&gt;例えばこのようなコードがあり、&lt;code&gt;link&lt;/code&gt;はスタイル付きのテキストのようなルール付がされています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// a
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;link&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;node&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;children&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;parent&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Text&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;node&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;} &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;link&lt;/span&gt;} &lt;span style="color:#a6e22e"&gt;onPress&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{() =&amp;gt; &lt;span style="color:#a6e22e"&gt;openUrl&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;node&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;attributes&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;)}&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;children&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/Text&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/XvutwINbYRfnuK6Kwt-Gd88vE0xXHqLw6uv5FxcHgkMISsEKGMtfPDKP2RNEmZDADfHz5_B8w7YD-p0IneV9AtfVg2oIUvgA2ypz7Pj-1CBP-289i1K-fqdBHdFSGlRX4qPDZL9mHWxKGgPIyH21PcY1pYHGio3_tmu2mQLK18p4hZHRGtTokM-iLlQzAotw2S_M-zCuacR2GQ0im2Ahc_LJ__SQLGU9S1cS6GjQH8tnIwIJp1KemSw6CN162oxEM0qfnacuBI3WJcZkZfYLJZvpbctrbjoH_foJ08JGtTF55f3QHxcBrtuegDcLyMufUYhSyRQY9PKfLvxiyg9rZUhrFmQJE1F6jjM3SgfjS0a0tomKZZXupxxnvoFcQWhWRQ0Y_GKSo9W0vVqWjhKi_cX2Uw-tWc61JfRQsHCHBSPYLDPCIXuM9o0sddj6wqoKeTvZalFwpB2dnTmN0sQP0mJ2mJs3YKhhVzCklgxLIO9rILtTLCBByWYG-Mu94U8fGiqwtudA36tA2M6ahVd-EL9qiaBvhgUAm9_ueFgHJR3a7aezdy6X547KoRFH-su7w1FubQ_DNDYh6nIg-Fdsc_Q1oqLKpi2abYNEENLYlphBfPnWrt8aU7q-KH062vI2ybRiDZW-NCPdFG77CQERWP5FWRXr8LgR=w522-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/XvutwINbYRfnuK6Kwt-Gd88vE0xXHqLw6uv5FxcHgkMISsEKGMtfPDKP2RNEmZDADfHz5_B8w7YD-p0IneV9AtfVg2oIUvgA2ypz7Pj-1CBP-289i1K-fqdBHdFSGlRX4qPDZL9mHWxKGgPIyH21PcY1pYHGio3_tmu2mQLK18p4hZHRGtTokM-iLlQzAotw2S_M-zCuacR2GQ0im2Ahc_LJ__SQLGU9S1cS6GjQH8tnIwIJp1KemSw6CN162oxEM0qfnacuBI3WJcZkZfYLJZvpbctrbjoH_foJ08JGtTF55f3QHxcBrtuegDcLyMufUYhSyRQY9PKfLvxiyg9rZUhrFmQJE1F6jjM3SgfjS0a0tomKZZXupxxnvoFcQWhWRQ0Y_GKSo9W0vVqWjhKi_cX2Uw-tWc61JfRQsHCHBSPYLDPCIXuM9o0sddj6wqoKeTvZalFwpB2dnTmN0sQP0mJ2mJs3YKhhVzCklgxLIO9rILtTLCBByWYG-Mu94U8fGiqwtudA36tA2M6ahVd-EL9qiaBvhgUAm9_ueFgHJR3a7aezdy6X547KoRFH-su7w1FubQ_DNDYh6nIg-Fdsc_Q1oqLKpi2abYNEENLYlphBfPnWrt8aU7q-KH062vI2ybRiDZW-NCPdFG77CQERWP5FWRXr8LgR=w522-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="htmlで渡す系"&gt;HTMLで渡す系&lt;/h1&gt;
&lt;h2 id="react-native-htmlview"&gt;react-native-htmlview&lt;/h2&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/jsdf/react-native-htmlview" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/9277b7af73827c06b6487ebf90ec7b87c8bfc3ff0596bf2acabe2073dcf840e3/jsdf/react-native-htmlview" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - jsdf/react-native-htmlview: A React Native component which renders HTML content as native views&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;A React Native component which renders HTML content as native views - jsdf/react-native-htmlview&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;こちらが現状のRemottyで使っているライブラリです。MarkdownをHTMLにしたあとでReactNativeコンポーネントにするというのは変わらないですが、&lt;code&gt;li&lt;/code&gt;の入れ子などが考慮されていないため残念な見た目になります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/ZugzNWhQOnlij5P52XMlBKwLrEaGq0z2_oFOVh1fkaQ3WHSHN8KaVW5uuld-9ahsHa24MgMBLtCFZ4ndOoZeXhBkNlasdrYemRf6GZZc-j0TeiSj6NfR0NnboalZUw9bPZfwL6NRFq-kKqTnqgPHvKPVQQjvxxd345VmPuZ8V9SJmjGZCh1n4NmqjnZ9yHtOxav3DTIVMXQ1DM0LH5Xql6pM-qLLAHh_iJam3WyfmuWANtW1d99Ma6OQx3i8CA-XKpniJrl8fMh_0MVOfGOHkE5FyRRRiQQY1TcWC0U9hYwgq4ZNYegHgIQOTOtW-GuVkKV7u2AoRTF3wZZMKoW7jUxx7nqcNg1XiW8bRcBfJxh6kkd066eubrBWxuXLMRyNxwwfIBiKRjAZxqDkOvu0XKri6ZMUHh34Qrr5QIy21hA1IdzNdUUz5VeSlBycufV0ocnv28FalRj5dxMLLJshyZwiMrRGpic600-XbWJycwblg_zktVB0WAuJ6JkoG67ImMnzQD3GOOZelM5CFqtZX0Pp5ChOyr60FLaVyBtaq1L1427XVwNWKLoDj138IYOY9OHbQZFrA7Q7MuOrxkZg1yBXwno_FDp9mheg3wS3hst9K2fR4Ne8umDtLZztjU8U1Dkz4vTjLCj6EirIZgbBdT-Qns-HhuPN=w522-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/ZugzNWhQOnlij5P52XMlBKwLrEaGq0z2_oFOVh1fkaQ3WHSHN8KaVW5uuld-9ahsHa24MgMBLtCFZ4ndOoZeXhBkNlasdrYemRf6GZZc-j0TeiSj6NfR0NnboalZUw9bPZfwL6NRFq-kKqTnqgPHvKPVQQjvxxd345VmPuZ8V9SJmjGZCh1n4NmqjnZ9yHtOxav3DTIVMXQ1DM0LH5Xql6pM-qLLAHh_iJam3WyfmuWANtW1d99Ma6OQx3i8CA-XKpniJrl8fMh_0MVOfGOHkE5FyRRRiQQY1TcWC0U9hYwgq4ZNYegHgIQOTOtW-GuVkKV7u2AoRTF3wZZMKoW7jUxx7nqcNg1XiW8bRcBfJxh6kkd066eubrBWxuXLMRyNxwwfIBiKRjAZxqDkOvu0XKri6ZMUHh34Qrr5QIy21hA1IdzNdUUz5VeSlBycufV0ocnv28FalRj5dxMLLJshyZwiMrRGpic600-XbWJycwblg_zktVB0WAuJ6JkoG67ImMnzQD3GOOZelM5CFqtZX0Pp5ChOyr60FLaVyBtaq1L1427XVwNWKLoDj138IYOY9OHbQZFrA7Q7MuOrxkZg1yBXwno_FDp9mheg3wS3hst9K2fR4Ne8umDtLZztjU8U1Dkz4vTjLCj6EirIZgbBdT-Qns-HhuPN=w522-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="react-native-autoheight-webview"&gt;react-native-autoheight-webview&lt;/h2&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/iou90/react-native-autoheight-webview" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/453561431870034dbc10c87ce49ac3f8d0f13ef9c44853d06516f1e43526bc2a/iou90/react-native-autoheight-webview" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - iou90/react-native-autoheight-webview: An auto height webview for React Native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;An auto height webview for React Native. Contribute to iou90/react-native-autoheight-webview development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;こちらは内部でWebViewを使っており、&lt;code&gt;react-native-showdown&lt;/code&gt;と同様&lt;code&gt;originWhitelist={\\\['\\\*'\\\]}&lt;/code&gt;が必要でした。画像がはみ出るものの比較的いい感じで表示できました。高さを開発者が指定しなくていいのが良いです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Dlai6OnDAxvHhqXrgjMfSkJ6BCO63OK22n_XwYjrwBlrL_AypD5Yl4feYuNNAoTwmYSklURJBt0Y5FNwlbhGeP9RfgG4wND4tnX935H1XJB8ob4CdTMMbCU3D8NqeBPim53zasuDWd9SURh7eFaUKDV0uH4wTs4SQeLIlDOzZdItcO3bnrAZCHX2imrFreATb_zp2RejjNWjpYGH5K00IPS7qb1wjfF1mQJhxS78TuDi7TI1shhdfDSsI9VytEdF_gBDrX9UBCmc0lJt2Hup-wRDlHqDkR8qNoX7DjQB8PQAL9NZz7c9OUst5wBPEXlmAwsi7qxANUhBoD5PrvmlyuKbRh6hYYA6dOc0p4bttavhVbMHUWJd0_2y6Kp--G4jx_kaDNc-NBWl1UrlIfIhyFAxGvdksVM4pBJ9y6k1IJx5AZSyWggWsfCaxCMc9EMS4DFrWTgDIZJVoBPbMmTBx-lVy5jDoe4UaCdVj8J8Uyho6kHP4qYblmMgFQQZnQbgYMhqoHCcJ7PRm3e7GGRrPOEfDAdJb1dCbva73E8b44p8csyStrqmB9Kenf8FtfbW13NHmEz6LYsDXPRCqdko0BLAzzjhuIWNf5TnciYBld_5CSd94V7gnM2VnytIkvlaLVyIyzukVEn1A0HrRT6X1l_q2jR45ekK=w522-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Dlai6OnDAxvHhqXrgjMfSkJ6BCO63OK22n_XwYjrwBlrL_AypD5Yl4feYuNNAoTwmYSklURJBt0Y5FNwlbhGeP9RfgG4wND4tnX935H1XJB8ob4CdTMMbCU3D8NqeBPim53zasuDWd9SURh7eFaUKDV0uH4wTs4SQeLIlDOzZdItcO3bnrAZCHX2imrFreATb_zp2RejjNWjpYGH5K00IPS7qb1wjfF1mQJhxS78TuDi7TI1shhdfDSsI9VytEdF_gBDrX9UBCmc0lJt2Hup-wRDlHqDkR8qNoX7DjQB8PQAL9NZz7c9OUst5wBPEXlmAwsi7qxANUhBoD5PrvmlyuKbRh6hYYA6dOc0p4bttavhVbMHUWJd0_2y6Kp--G4jx_kaDNc-NBWl1UrlIfIhyFAxGvdksVM4pBJ9y6k1IJx5AZSyWggWsfCaxCMc9EMS4DFrWTgDIZJVoBPbMmTBx-lVy5jDoe4UaCdVj8J8Uyho6kHP4qYblmMgFQQZnQbgYMhqoHCcJ7PRm3e7GGRrPOEfDAdJb1dCbva73E8b44p8csyStrqmB9Kenf8FtfbW13NHmEz6LYsDXPRCqdko0BLAzzjhuIWNf5TnciYBld_5CSd94V7gnM2VnytIkvlaLVyIyzukVEn1A0HrRT6X1l_q2jR45ekK=w522-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="webview"&gt;WebView&lt;/h2&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://facebook.github.io/react-native/docs/webview.html" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;facebook.github.io →&lt;/span&gt;&lt;span&gt;https://facebook.github.io/react-native/docs/webview.html&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;標準のコンポーネントでも試しました。高さ指定が必要で無指定だと何もヒョ時されません。コンテンツが色々動的に変わるんだとしたら実際に使うのはなかなかに大変そうです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/4E3kcqhzlQHA_17fTQZuIDoECfHqFIlyjlJRMW91-KMuNZ0lgpLgekwcn02uiJKHDGEOHFxhF93mmQcOTF-pfMrjYelmEDaOu0DiZ24RguAf61aD37Z0oppqNxzgoWFCEnjBME_2zVVSdAoKzpmWclTlwLA_Q9ICiDdOh_Jjqf53GRHbkq5BYtuGeuIkeUsDAVJquIa-kbamqUXObK4vRLje6fEEHzr3MTHusaM7vKxoWkppqAQad6usgHwCV7HFaKnHO4ebRIugLgmdOf9gp07a4R-7K_HIoCEBiWFa7z2fszv-IOnD2LuR-ESflSt6YJhcnLyDVEaREeHvktkq8seaSuc9T2YB7XSR4xZ9ZeIt6dlaDkUsuWGJokQX3yeJs6tPZDPoyFjTKK3acGfiK2ADCW0b2LDbxe-wFZgLxOOsTSADdOxtoZfV8Y7z390ScI7o6z25GzhnBeIXWHcYw_SL5ld21UdvO1e6f2OcpbEH6G3eMtwHxeQS-pZztcjSwQKE8e0ajPXyH7aKhESbyVQYs1cKtYPzWWoaz8n6m2OCmdbwjv__mjII6X0Pbk4TeC-PJInqKBHoqOF8eQ4Arf2GKDyNg4medT_JVNem4mBa1Ea6wO581fWxJFJBfeM3eD4v0zHLeHdJKIYM8ID_vHbjhRtqUYoc=w522-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/4E3kcqhzlQHA_17fTQZuIDoECfHqFIlyjlJRMW91-KMuNZ0lgpLgekwcn02uiJKHDGEOHFxhF93mmQcOTF-pfMrjYelmEDaOu0DiZ24RguAf61aD37Z0oppqNxzgoWFCEnjBME_2zVVSdAoKzpmWclTlwLA_Q9ICiDdOh_Jjqf53GRHbkq5BYtuGeuIkeUsDAVJquIa-kbamqUXObK4vRLje6fEEHzr3MTHusaM7vKxoWkppqAQad6usgHwCV7HFaKnHO4ebRIugLgmdOf9gp07a4R-7K_HIoCEBiWFa7z2fszv-IOnD2LuR-ESflSt6YJhcnLyDVEaREeHvktkq8seaSuc9T2YB7XSR4xZ9ZeIt6dlaDkUsuWGJokQX3yeJs6tPZDPoyFjTKK3acGfiK2ADCW0b2LDbxe-wFZgLxOOsTSADdOxtoZfV8Y7z390ScI7o6z25GzhnBeIXWHcYw_SL5ld21UdvO1e6f2OcpbEH6G3eMtwHxeQS-pZztcjSwQKE8e0ajPXyH7aKhESbyVQYs1cKtYPzWWoaz8n6m2OCmdbwjv__mjII6X0Pbk4TeC-PJInqKBHoqOF8eQ4Arf2GKDyNg4medT_JVNem4mBa1Ea6wO581fWxJFJBfeM3eD4v0zHLeHdJKIYM8ID_vHbjhRtqUYoc=w522-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="結論"&gt;結論&lt;/h1&gt;
&lt;p&gt;ここまで比較してみて、今使っている&lt;code&gt;react-native-htmlview&lt;/code&gt;は相当イケてないなということがわかりましたので、早急に対応すべきな気がしてきましたｗ&lt;/p&gt;
&lt;p&gt;React Nativeのコンポーネントに直してくれる&lt;code&gt;react-native-markdown-renderer&lt;/code&gt;が良さそうだなという感覚がありますね。うまくコンポーネントにしてくれるならレイアウトが楽になりそうです。&lt;/p&gt;
&lt;p&gt;それで難しいのであれば、次点は&lt;code&gt;react-native-autoheight-webview&lt;/code&gt;でしょうか。MarkdownがHTMLを書くための記法だと思えばWebViewに表示を任せるのは悪くない選択肢かと思います。こちらは速度に課題があるかもしれません。&lt;/p&gt;
&lt;p&gt;今回試すにあたり作ったサンプルアプリをGitHubに上げておきました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/pi-chan/ReactNativeMarkdownSample" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/02ed2161748a3df9c4f5f8c431dc55aa193e91030a848a322a94c9432e6f09ae/pi-chan/ReactNativeMarkdownSample" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - pi-chan/ReactNativeMarkdownSample&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Contribute to pi-chan/ReactNativeMarkdownSample development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>High Sierraでスリープ明けにWi-Fiがオフになっている問題が発生</title><link>https://blog.piyo.tech/posts/2018-07-11-high-sierra-wifi/</link><pubDate>Wed, 11 Jul 2018 06:54:20 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-11-high-sierra-wifi/</guid><description>&lt;p&gt;2018/07/10時点で最新のmacOS High Sierraでスリープ明けにWi-Fiがオフになっている現象に遭遇しました。こうなってしまうとAppleWatchによるスリープの解除ができず、想像しているよりも不便でした。&lt;/p&gt;
&lt;p&gt;High Sierraがリリースされたばかりの頃にスリープ明けにWi-Fiが切断する現象があるという話をよく見かけました。今回はWi-Fiがオフになっているのでそれとは違うのかな、どうしようかなと数日困っていました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;再起動で直った&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;結果的には再起動で直りました。ドライバか何かの状態がおかしかったんでしょうか。もっと早いとこ基本の再起動に立ち戻ればよかったです。&lt;/p&gt;</description></item><item><title>iOSのVisionフレームワークで顔のパーツ認識を試せるサンプルアプリ</title><link>https://blog.piyo.tech/posts/2018-07-10-ios11-face-detection/</link><pubDate>Tue, 10 Jul 2018 06:57:34 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-10-ios11-face-detection/</guid><description>&lt;p&gt;iOS11から使えるようになったVisionフレームワークというのを使うとものすごく簡単に顔認識が可能です。裏ではCoreMLが使われているということで機械学習ベースの顔認識のようです。&lt;/p&gt;
&lt;p&gt;ちょっと動かしてみようと思ったときに最適なサンプルアプリケーションをGitHubで見つけましたので紹介しておきます。おかげで同じようなことを実施するアプリを作るときの参考になりました。&lt;/p&gt;
&lt;p&gt;それがこちらです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/mattlawer/FaceLandmarksDetection" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/0eb2d983f3b625dcab94ad419cd99fbf7aa0eacd5d49257a856397940f42d542/mattlawer/FaceLandmarksDetection" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - mattlawer/FaceLandmarksDetection: Finds facial features such as face contour, eyes, mouth and nose in an image.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Finds facial features such as face contour, eyes, mouth and nose in an image. - mattlawer/FaceLandmarksDetection&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;昨日UIImageのところでちょろっと触れた件でもあります。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-07-09-fix-uiimage-orientation/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/PFwdExRpr7BU5lXpwHpRLaigiiscZC7NhiO1Y8z0Dx7G-c9KzZaSU-KiU-0cab0bFrlFhP2u8hLN79XqgnoOxwYktH6MGJReAPjjifUVEYITHvaoCWvCShWkMakIUCbY2-X9EauukRm4fijNN5uP4EnICLu1eokr8sSKqBHXG7cFJJDs7t8aBB4t0v2emidWzXC7agnV9NtAvZEed6wfIQHexBCE4CGoyQnlT1qG2fdDlyggon8vS3IHYHGhWbbqVCG2rtQXR4NcDJPOiffOH9dXSKw684200f1RSrk92aoIA3PZ6h833Q7Mss5Y19LOp4B4h2qwhNsTmJotSU9Txs5EP5xCNgurm-Zbc8Ngdgr5ydbnZMOqxUgk8IGuhYWu5Nd4ldn491Trfj5mi99IdgC4rCXmOJ12NdM2KkqC_T_lV9xJb7rXkMIFcvxU644UYLuVVncJUu9fbZnxZYQY_yuiwP6nsyIOOOex231VPXihWxsCr6fyRDzFZszCx_vCNbilklYGbfi2VZlaxa83HcBK5XSRKM6tp8JDVZc1bdJnwWUi4y_wB1A0Pt9a1vB-egof7d_XFgNoByKdjRkFGyxI0__0cCrahJWQbA_EbgFIRIhyXmGuUZxzUTOwZyKqCygEAGEmdXXmzU1qHyovio9wnnNy1xPf=w1500-h756-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;AVCaptureOutputで撮影した写真のimageOrientationを修正する - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;AVCaptureOutputで撮影した写真は UIImageView に表示したり本体のフォトアルバムに保存する限りは問題ないのですが、別のソフトウェアやライブラリが向きを正しく解釈してくれなくてうまくいかないというケースが起こります。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;このリポジトリをcloneして手元で動かせばすぐに試すことができます。&lt;/p&gt;
&lt;p&gt;重要なのはこちらのファイル↓です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mattlawer/FaceLandmarksDetection/blob/master/DetectFaceLandmarks/FaceLandmarksDetector.swift"&gt;FaceLandmarksDetection/FaceLandmarksDetector.swift&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;↑このファイルで定義されているクラスが、画像を受け取って顔認識にかけ認識結果を書き込んだ画像にして呼び出し元に返す、という処理をしています。この手の処理は座標合わせが往々にして面倒なのですが、ちゃんと考慮してくれているので変にハマらなくて済みます。&lt;/p&gt;
&lt;p&gt;余談ですが元々3D系の仕事をしてたので計算できないわけじゃないけど、あまり得意ではない（直感的に理解できない）のでできれば避けたいのです。&lt;/p&gt;
&lt;p&gt;というわけで顔認識をやりたい場合はこういったサンプルコードから習得していくのも良いんじゃないかなと思いました。&lt;/p&gt;
&lt;p&gt;認識には&lt;code&gt;VNDetectFaceLandmarksRequest&lt;/code&gt;というクラスを使うので、GitHub上でこのクラスを検索すると他の例も見つかりそう。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/search?utf8=%E2%9C%93&amp;amp;q=VNDetectFaceLandmarksRequest&amp;amp;type="&gt;Search · VNDetectFaceLandmarksRequest&lt;/a&gt;&lt;/p&gt;</description></item><item><title>AVCaptureOutputで撮影した写真のimageOrientationを修正する</title><link>https://blog.piyo.tech/posts/2018-07-09-fix-uiimage-orientation/</link><pubDate>Mon, 09 Jul 2018 06:59:56 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-09-fix-uiimage-orientation/</guid><description>&lt;p&gt;AVCaptureOutputで撮影した写真は&lt;code&gt;UIImageView&lt;/code&gt;に表示したり本体のフォトアルバムに保存する限りは問題ないのですが、別のソフトウェアやライブラリが向きを正しく解釈してくれなくてうまくいかないというケースが起こります。&lt;/p&gt;
&lt;p&gt;↓は典型的なAVFoundationを用いた写真撮影のコードです。だいぶ端折って書いてますが、だいたいこんな感じになるはずです。ボタンを押すと写真を撮影できるというイメージです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CameraViewController&lt;/span&gt; : UIViewController {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; photoOutput : AVCapturePhotoOutput!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.viewDidLoad()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// カメラ色々&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; configureDevice()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 撮影ボタン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBAction&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;takePhoto&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; sender: Any) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; settingsForMonitoring = AVCapturePhotoSettings()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; settingsForMonitoring.isAutoStillImageStabilizationEnabled = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; photoOutput?.capturePhoto(with: settingsForMonitoring, delegate: &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;extension&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CameraViewController&lt;/span&gt; : AVCapturePhotoCaptureDelegate {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;photoOutput&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; imageData = photo.fileDataRepresentation()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; image = UIImage(data: imageData!)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// imageのimageOrientationは .right&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;didFinishProcessingPhoto&lt;/code&gt;の中で撮影結果がえられるので、&lt;code&gt;Data&lt;/code&gt;を経由して&lt;code&gt;UIImage&lt;/code&gt;にしています。&lt;/p&gt;
&lt;p&gt;これを&lt;code&gt;UIImageView&lt;/code&gt;に設定したりアルバムに保存したりしても画像の向きの問題は起こりません。&lt;/p&gt;
&lt;p&gt;僕が気がついたのは、iOSで使えるVisionフレームワークを使った顔認識機能に画像を渡したときです。&lt;code&gt;AVCapturePhotoOutput&lt;/code&gt;から得られた&lt;code&gt;UIImage&lt;/code&gt;を使って顔認識をしようとしたところ、まっすぐ撮影した画像ではだめで、90度横にした場合に顔認識の結果が描画（目の位置や口の位置などのマーク）されたのです。&lt;/p&gt;
&lt;p&gt;詳細は今度紹介しますが、コードは↓のようなイメージです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Vision&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;FaceLandmarksDetector&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; open &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;highlightFaces&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; source: UIImage, complete: @escaping (UIImage) -&amp;gt; Void) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; resultImage = source
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; detectFaceRequest = VNDetectFaceLandmarksRequest { (request, error) &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; complete(resultImage)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; vnImage = VNImageRequestHandler(cgImage: source.cgImage!, options: [:])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt;? vnImage.perform([detectFaceRequest])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;顔認識の詳細はさておき、考えられるのは&lt;code&gt;imageOrientation&lt;/code&gt;が考慮されていないということです。&lt;code&gt;imageOrientation&lt;/code&gt;が&lt;code&gt;.up&lt;/code&gt;の状態で正しい向きになっている写真にしてから顔認識にかける必要が、どうやらありそうです。&lt;/p&gt;
&lt;p&gt;現在の&lt;code&gt;imageOrientation&lt;/code&gt;を元に元画像を回転させたうえで、新しい&lt;code&gt;imageOrientation&lt;/code&gt;を&lt;code&gt;.up&lt;/code&gt;として画像を再生成するような対応をすれば解決しそうです。&lt;/p&gt;
&lt;p&gt;その手のコードはしっかり書こうとすると大変なんですが、同じようなことで困っている人はたくさんいるはずなので色々探してみたら良い感じのGistのコードを見つけました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://gist.github.com/schickling/b5d86cb070130f80bb40" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://github.githubassets.com/assets/gist-og-image-54fd7dc0713e.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Extension to fix orientation of an UIImage (Sets orientation to portrait)&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Extension to fix orientation of an UIImage (Sets orientation to portrait) - UIImageFixedOrientationExtension.swift&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;gist.github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;このリンク先のGistに&lt;code&gt;Swift 4 tested ( + handled some cases)&lt;/code&gt;というバージョンがあり、読んだ感じちゃんと動きそうだったので使ってみました。これによって無事顔認識が動いてくれました。&lt;/p&gt;
&lt;p&gt;以下フルバージョンです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;extension&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UIImage&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fixedOrientation&lt;/span&gt;() -&amp;gt; UIImage? {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;guard&lt;/span&gt; imageOrientation &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; UIImageOrientation.up &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//This is default orientation, don&amp;#39;t need to do anything&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.copy() &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt;? UIImage
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;guard&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; cgImage = &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.cgImage &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//CGImage is not available&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;guard&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; colorSpace = cgImage.colorSpace, &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; ctx = CGContext(data: &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;, width: Int(size.width), height: Int(size.height), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; &lt;span style="color:#75715e"&gt;//Not able to create CGContext&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; transform: CGAffineTransform = CGAffineTransform.identity
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; imageOrientation {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .down, .downMirrored:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; transform = transform.translatedBy(x: size.width, y: size.height)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; transform = transform.rotated(by: CGFloat.pi)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .&lt;span style="color:#66d9ef"&gt;left&lt;/span&gt;, .leftMirrored:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; transform = transform.translatedBy(x: size.width, y: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; transform = transform.rotated(by: CGFloat.pi &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2.0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .&lt;span style="color:#66d9ef"&gt;right&lt;/span&gt;, .rightMirrored:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; transform = transform.translatedBy(x: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, y: size.height)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; transform = transform.rotated(by: CGFloat.pi &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2.0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .up, .upMirrored:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Flip image one more time if needed to, this is to prevent flipped image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; imageOrientation {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .upMirrored, .downMirrored:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt; transform.translatedBy(x: size.width, y: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;42&lt;/span&gt;&lt;span&gt; transform.scaledBy(x: &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, y: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;43&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;44&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .leftMirrored, .rightMirrored:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;45&lt;/span&gt;&lt;span&gt; transform.translatedBy(x: size.height, y: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;46&lt;/span&gt;&lt;span&gt; transform.scaledBy(x: &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, y: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;47&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .up, .down, .&lt;span style="color:#66d9ef"&gt;left&lt;/span&gt;, .&lt;span style="color:#66d9ef"&gt;right&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;48&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;49&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;50&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;51&lt;/span&gt;&lt;span&gt; ctx.concatenate(transform)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;52&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;53&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; imageOrientation {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;54&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .&lt;span style="color:#66d9ef"&gt;left&lt;/span&gt;, .leftMirrored, .&lt;span style="color:#66d9ef"&gt;right&lt;/span&gt;, .rightMirrored:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;55&lt;/span&gt;&lt;span&gt; ctx.draw(&lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.cgImage!, &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;: CGRect(x: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, y: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, width: size.height, height: size.width))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;56&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;57&lt;/span&gt;&lt;span&gt; ctx.draw(&lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.cgImage!, &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;: CGRect(x: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, y: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, width: size.width, height: size.height))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;58&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;59&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;60&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;61&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;guard&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; newCGImage = ctx.makeImage() &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; { &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;62&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; UIImage.&lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(cgImage: newCGImage, scale: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, orientation: .up)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;63&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;64&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>自作SegueでViewControllerをdismissする</title><link>https://blog.piyo.tech/posts/2018-07-08-custom-segue/</link><pubDate>Sun, 08 Jul 2018 06:39:31 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-08-custom-segue/</guid><description>&lt;p&gt;いやー、7年iOSやってても全然しらなかったんですが、Segueを自作するとちょっと便利ですね。&lt;/p&gt;
&lt;p&gt;モーダルで開いたViewControllerを閉じるときにボタンを置いてコードを書くのは面倒だなーと思ってたんですが、閉じるボタンの操作をSegueで定義できます。&lt;/p&gt;
&lt;p&gt;準備として&lt;code&gt;UIStoryboardSegue&lt;/code&gt;を継承したサブクラスをプロジェクト内に作っておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DismissControllerSegue&lt;/span&gt;: UIStoryboardSegue {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;perform&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.source.dismiss(animated: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;, completion: &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コードはシンプルで&lt;code&gt;perform()&lt;/code&gt;の中にやりたいことを書く形。今回は自分自身を&lt;code&gt;dismiss&lt;/code&gt;するだけです。&lt;/p&gt;
&lt;p&gt;ここまででstoryboardが参照してくれるようになっていますので、あとはボタンと紐付けるだけです。controlキーを押したままボタンからViewController自身にドラッグすると↓のようなpopoverみたいなのが出ます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/82IEh1zVBu5CSvelkVGNLHjquoE7pOEz3oSdj_RHYmg1COO9zIIYBGQ7UrEA5Ve1G5C9NqsZc6mTl2HWJNfMG-4KUuUyhwtRi4bOftuABwFli2Jm1QYySf4EtItGmr_KnkYO3BfrxdwdkeZkKzeq7TWGdLH1E7gh1ABQohk_jUAcy1AY5Zpcs3HJBLQtFnZ_brMWoDHHLJHe7g2nDkd_VKNcEMyNM8iSXn3NcLlU4qrZScXdKItWsfEkjKxTpwGR9CfZsERNkKTmo4Rd0o77YguKGBe-Qt8nrAt5X8HWZOXzOvT9v5-LQO2Nk5C4je2XA_S_lSIbGeyRzC9HYsgl-LNvUv-ga45Vt7WnMjAT64njs1e2FuuB1dpGenj0N5kL0I7_BP9k7j7PoEFI1GOAnbRSRGFl9S3CEitUFUvgXljcHv5ULm8J7UbRq7dSz6MlU0c9mErUDwsOJ96Dpn5spd4Kf0ZmGU8yVg3qQmFPF3qI7J4d7G6cSBE6VqjGiY3JxBc3rLyc_JMhJUQswoc89PwbqCg7rTozgMYMIx50FHulL3fW4XylpYHOMtpPhP3CIUTSoLOaxd3-WcRs51UxwBQTXJ3dCPwwa9p0VGVv0G_qgEja29o9JkJ2tH66uJw7MFfnQ-FS9Z3kj4WCi3MSdrA-yUEPwye_uw=w1546-h1228-no"&gt;&lt;img src="https://lh3.googleusercontent.com/82IEh1zVBu5CSvelkVGNLHjquoE7pOEz3oSdj_RHYmg1COO9zIIYBGQ7UrEA5Ve1G5C9NqsZc6mTl2HWJNfMG-4KUuUyhwtRi4bOftuABwFli2Jm1QYySf4EtItGmr_KnkYO3BfrxdwdkeZkKzeq7TWGdLH1E7gh1ABQohk_jUAcy1AY5Zpcs3HJBLQtFnZ_brMWoDHHLJHe7g2nDkd_VKNcEMyNM8iSXn3NcLlU4qrZScXdKItWsfEkjKxTpwGR9CfZsERNkKTmo4Rd0o77YguKGBe-Qt8nrAt5X8HWZOXzOvT9v5-LQO2Nk5C4je2XA_S_lSIbGeyRzC9HYsgl-LNvUv-ga45Vt7WnMjAT64njs1e2FuuB1dpGenj0N5kL0I7_BP9k7j7PoEFI1GOAnbRSRGFl9S3CEitUFUvgXljcHv5ULm8J7UbRq7dSz6MlU0c9mErUDwsOJ96Dpn5spd4Kf0ZmGU8yVg3qQmFPF3qI7J4d7G6cSBE6VqjGiY3JxBc3rLyc_JMhJUQswoc89PwbqCg7rTozgMYMIx50FHulL3fW4XylpYHOMtpPhP3CIUTSoLOaxd3-WcRs51UxwBQTXJ3dCPwwa9p0VGVv0G_qgEja29o9JkJ2tH66uJw7MFfnQ-FS9Z3kj4WCi3MSdrA-yUEPwye_uw=w1546-h1228-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここで、先程追加したSegueを表す&lt;code&gt;dismiss controller&lt;/code&gt;を選べばOK。ボタンタップ時に自身が閉じてくれます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/uVCObSvUaf5kozOY3zxwPryi2-QVKqJxCE0VaPIrl0628MIC-iZvpxCQAriHCn5Aa82cHq_CaphzJxTDvYbKl6kyvAkRL1mmJ18eYQ6avq4_MUjRB0HQk7X5UstHVRUBZF1jV1FkLchT0FVe79rryuq2N_fWuFseOXeaL6vXtmwggLtVRLyV842DckRDSUnryUk_4pPFrIvopXaEQ2KGkaTFBqesAO1OKF0hY7N8gSDb6h9TRLVF9uq5P2zk0DP84aRzth9t0Ka2u-QWXCzqnuw22FOnomOSkVua6IVdduzczPauHRsXwZ27hnSvkgkpMNP8l8t5mCjM9pfm54OQop2C7MJgFIxr4KxS-87tNmKRffR5QQ0ff-im3H-IDJLqM9XCbACBcaZ4HAibnaxoV6TKDU0ZWwOMcEdKFdB8Hpzgi4GGSBsnkXBssUKU07iTRVnAaFRvt7RukTpycAl0dmCXEVEyi-Cv6qU2pUV3uVmt2aIeS44e_0dIzPa9hmiH36UVETgLnlaWBBCapmJpwFKSCkVhAVd00MJqWOKu9tXSxYkkFsHcfvUEHmaRg7rY8VWNuRzTBgNZNAukx8PIlLLiPlBBYet6FigxTCETIumWRy8YiQUX99z1N818womC8aDjBNLWgcYACUlHn11lkbamBGdRBhJOdA=w387-h811-no"&gt;&lt;img src="https://lh3.googleusercontent.com/uVCObSvUaf5kozOY3zxwPryi2-QVKqJxCE0VaPIrl0628MIC-iZvpxCQAriHCn5Aa82cHq_CaphzJxTDvYbKl6kyvAkRL1mmJ18eYQ6avq4_MUjRB0HQk7X5UstHVRUBZF1jV1FkLchT0FVe79rryuq2N_fWuFseOXeaL6vXtmwggLtVRLyV842DckRDSUnryUk_4pPFrIvopXaEQ2KGkaTFBqesAO1OKF0hY7N8gSDb6h9TRLVF9uq5P2zk0DP84aRzth9t0Ka2u-QWXCzqnuw22FOnomOSkVua6IVdduzczPauHRsXwZ27hnSvkgkpMNP8l8t5mCjM9pfm54OQop2C7MJgFIxr4KxS-87tNmKRffR5QQ0ff-im3H-IDJLqM9XCbACBcaZ4HAibnaxoV6TKDU0ZWwOMcEdKFdB8Hpzgi4GGSBsnkXBssUKU07iTRVnAaFRvt7RukTpycAl0dmCXEVEyi-Cv6qU2pUV3uVmt2aIeS44e_0dIzPa9hmiH36UVETgLnlaWBBCapmJpwFKSCkVhAVd00MJqWOKu9tXSxYkkFsHcfvUEHmaRg7rY8VWNuRzTBgNZNAukx8PIlLLiPlBBYet6FigxTCETIumWRy8YiQUX99z1N818womC8aDjBNLWgcYACUlHn11lkbamBGdRBhJOdA=w387-h811-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>ローカル環境に公開URLを紐付けられるngrokの有料登録しました</title><link>https://blog.piyo.tech/posts/2018-07-06-ngrok-paid-plan/</link><pubDate>Fri, 06 Jul 2018 06:41:19 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-06-ngrok-paid-plan/</guid><description>&lt;p&gt;先日紹介したngrokにお金を払って使うことにしました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-06-07-ngrok-usecase/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://blog.piyo.tech/images/default.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;ローカル環境をインターネットに公開できるngrokのユースケース - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;ngrokというサービスがあります。僕は無料で簡易に使ったことしかないのでその範囲内の話しかできないですが、ユースケースを紹介したいと思います。 まず使い方はとても簡単。 1 % brew cask install ngrok 2 % ngrok http 3000 # ポート番号 これで、 xxxxxxx.ngrok.com みたいなURLが発行されます。このURLにアクセスするとローカルマシンの3000番ポートにリクエストが飛んできます。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;無料ユーザーだと毎回ランダムに生成される公開URLを使うことしかできません。この公開URLは12時間しか有効ではないため、毎日発行し直しが必要です。&lt;/p&gt;
&lt;p&gt;当然そのURLを参照している箇所は修正が必要となるため、毎日1〜2分の手間がかかります。&lt;/p&gt;
&lt;p&gt;これまではたまにしか必要ではなかったのですが、最近はWebサーバーにつなぐiPhoneアプリの実機デバッグのためによく使っていますので有料プランを使ってしまえばいいのでは？と思うようになりました。&lt;/p&gt;
&lt;p&gt;一番安い有料プランでは予めドメインを3つまで予約しておくことができ、それらを自分専用で使えます。年間60ドルでした。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/zqYhtxFf6y0q0uVBpm1dqguoYYKJQgY03cLLP15MF4qv3egzYun9rOHswcoAAVFykCwibOj9uSiqSt1j8OVN6pE9yDbq7PoLzQMci-yHJ9t-L_85oG64JsRc90Z8vWhR66UAiVZaKje81u_hcMcrvyxqC8ZkGsmrirGM9m1iderz_wjN_0fhx4AcHPdh_6JFJrsOF_h5WcGDI-vmEt-7pjUimgaLBr3XMsgaADdQgdVtWCxyyomJxK7AVgu2NBQwt-MwpzYilVm6Es58X1Uu3Ct6XtVCEA-H4aUiBqCCPdwlO-YPgbnt_b13jZ87OxuVyCx8k_ajdRyoaCFIxysGwtAWiIMb6CX3GYRD9PrfPG3kE9q8UuzRvXjBQpvrrlDvHYSWY41IUehUfIFhaMEwrBDTyg4k9zCar80ZdSiCuWGfsgR1LaYOtjitP5JvweShZnFPqOJVjwlQmhIMBrStrKZy3WJwHRlJ2Nn1M5WIl2fQD6XxY8C8f-_fvmTvseMXnVVcMjLtjVv6gowWC5ciYkyQE0GjnK6amO1G_dwxMrmzqPR5V_2u0O_wTWcnIqv79ZRAPpU9ys6gOf9veGcr-ks9PYJqtVacJnlhXehgj7NNzGWk3Q1kzoUlAMzJ-zZTD65R-mOY15qf2ePKd3uiYnqzp6cBU3Kp=w1228-h850-no"&gt;&lt;img src="https://lh3.googleusercontent.com/zqYhtxFf6y0q0uVBpm1dqguoYYKJQgY03cLLP15MF4qv3egzYun9rOHswcoAAVFykCwibOj9uSiqSt1j8OVN6pE9yDbq7PoLzQMci-yHJ9t-L_85oG64JsRc90Z8vWhR66UAiVZaKje81u_hcMcrvyxqC8ZkGsmrirGM9m1iderz_wjN_0fhx4AcHPdh_6JFJrsOF_h5WcGDI-vmEt-7pjUimgaLBr3XMsgaADdQgdVtWCxyyomJxK7AVgu2NBQwt-MwpzYilVm6Es58X1Uu3Ct6XtVCEA-H4aUiBqCCPdwlO-YPgbnt_b13jZ87OxuVyCx8k_ajdRyoaCFIxysGwtAWiIMb6CX3GYRD9PrfPG3kE9q8UuzRvXjBQpvrrlDvHYSWY41IUehUfIFhaMEwrBDTyg4k9zCar80ZdSiCuWGfsgR1LaYOtjitP5JvweShZnFPqOJVjwlQmhIMBrStrKZy3WJwHRlJ2Nn1M5WIl2fQD6XxY8C8f-_fvmTvseMXnVVcMjLtjVv6gowWC5ciYkyQE0GjnK6amO1G_dwxMrmzqPR5V_2u0O_wTWcnIqv79ZRAPpU9ys6gOf9veGcr-ks9PYJqtVacJnlhXehgj7NNzGWk3Q1kzoUlAMzJ-zZTD65R-mOY15qf2ePKd3uiYnqzp6cBU3Kp=w1228-h850-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="コマンドラインの認証"&gt;コマンドラインの認証&lt;/h2&gt;
&lt;p&gt;ユーザー登録した時点で認証用のトークンが発行されます。コマンドラインをアカウントと紐付けるのはフリーでもいけます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/zvjikyYjUeC0cj8vIxAzMkvMNEwnBBFvqR9d9gQhv4hdyAuzXIeUk9zL8UBlvE-dWpL2SIIUKgBGnGii82_Dn_EnHmjRAd0YRExyI-TC4wWjMBCetiU8fNEqgU04TbuaJbZsZebvmzmnwWgjNPt0LG7poZuDz2ujIySgfQjPbPvMCM3-MdPFA8ZWyhRdfWGnLTfWVmkoyRmvfioOeH6V8Dtkv2aS2oPgccZ8fVek_sietxT90GCUNZoIIOOAfx8RTW34C7sOJXlZ1hyvfHrvzaDFHlAMiGJyu1eBwmY-x9-oUX3xQCxvlwEjDhHSgcUXSYwdtofVOnHxEf_AuTZ23pj8ayqr3IGo5qWmY2nqRMM_-va0PF1jeTIbaecbD1sFr19c-8uy2VMgw7_JBjQ0QCQLO2lmv4jdPjeRuxPZsy0poXgSQHwH2VwWKa1AJTQzKEXd0REdPjc1LcFq7fe8TCO4A_cp23oK8YFYQE1zD6NjUC_pjCvUOdNYvwESwv-HIv0m39buC2frL7d2mcmyWYJI1pUVczQCi8Iw8Mso-h9USYt1O9RPBvYGN08uL5lJ-48ROIgLIQc9A1A_X892TLu_DTeOlsbF7WCVp0hdc9nba_6FXpK8cODpCBW91p7Yp40IOwZvRylp10A6CPbYtt1hQufKR3tO=w1019-h279-no"&gt;&lt;img src="https://lh3.googleusercontent.com/zvjikyYjUeC0cj8vIxAzMkvMNEwnBBFvqR9d9gQhv4hdyAuzXIeUk9zL8UBlvE-dWpL2SIIUKgBGnGii82_Dn_EnHmjRAd0YRExyI-TC4wWjMBCetiU8fNEqgU04TbuaJbZsZebvmzmnwWgjNPt0LG7poZuDz2ujIySgfQjPbPvMCM3-MdPFA8ZWyhRdfWGnLTfWVmkoyRmvfioOeH6V8Dtkv2aS2oPgccZ8fVek_sietxT90GCUNZoIIOOAfx8RTW34C7sOJXlZ1hyvfHrvzaDFHlAMiGJyu1eBwmY-x9-oUX3xQCxvlwEjDhHSgcUXSYwdtofVOnHxEf_AuTZ23pj8ayqr3IGo5qWmY2nqRMM_-va0PF1jeTIbaecbD1sFr19c-8uy2VMgw7_JBjQ0QCQLO2lmv4jdPjeRuxPZsy0poXgSQHwH2VwWKa1AJTQzKEXd0REdPjc1LcFq7fe8TCO4A_cp23oK8YFYQE1zD6NjUC_pjCvUOdNYvwESwv-HIv0m39buC2frL7d2mcmyWYJI1pUVczQCi8Iw8Mso-h9USYt1O9RPBvYGN08uL5lJ-48ROIgLIQc9A1A_X892TLu_DTeOlsbF7WCVp0hdc9nba_6FXpK8cODpCBW91p7Yp40IOwZvRylp10A6CPbYtt1hQufKR3tO=w1019-h279-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="ドメインの登録"&gt;ドメインの登録&lt;/h2&gt;
&lt;p&gt;Webのダッシュボードから登録が可能です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/D8wyWF3aRi2290pDfvyew_82y5WRIqFImMKV2vkpSJgl1c8s6roISnNpdvaLfxWaDrRt5xAXKgmoOA11yiJX78r44QYhCPDbletxpuLJ8brCcQxFaCy-MFsuYOF4JhNuD6t3miYAs1RgUxICptxfMISTdd39jEWI_C4qrtwib3pPLIywcgVGERjGtr0zlNBG6ciVdldS5UEtPZAxlr_U4noTHaOOyLcL9lLF8TORc-ygE64eeS4KdMNRQ8nAebpkhSMO8Au7WiOnEnXjtfKMgyumJ7kwm6Ys9A4lCpHx4RU5tbG5jSyrdjTgPdTwRQwy0WUm65PlYR-XAOapx_Gg94_XmiVzAs1k0ipxgKvQRlNFt-P0D_fTMoKE8jZjnC6KNDwxxZQVLMuMJ9NK7e7VjuPtnuJNkRTS_2CMQuG1GKs0F3S7TU3hJZzzN246h3J6uAqfX5gNUmbHZmTQcwP3W3GL9orEvF7mp1VRwf28dWVlx2W4g7kMjNm7p2hlhXVHG_zL7AV5CoQOapyNtj9hWVu7AROxJZXo2lDTtYcY0dPcEn5m2KBKdL0zxTH3q54S4bHNg3lvjoTBxnVU0-K8s_E6_NH59Mp8Uhjxw9vpiwG5glsKfXhPh3gs4JCsGhcELK896arudV5yQwI21HGiyVR7BYrzS_-2=w997-h348-no"&gt;&lt;img src="https://lh3.googleusercontent.com/D8wyWF3aRi2290pDfvyew_82y5WRIqFImMKV2vkpSJgl1c8s6roISnNpdvaLfxWaDrRt5xAXKgmoOA11yiJX78r44QYhCPDbletxpuLJ8brCcQxFaCy-MFsuYOF4JhNuD6t3miYAs1RgUxICptxfMISTdd39jEWI_C4qrtwib3pPLIywcgVGERjGtr0zlNBG6ciVdldS5UEtPZAxlr_U4noTHaOOyLcL9lLF8TORc-ygE64eeS4KdMNRQ8nAebpkhSMO8Au7WiOnEnXjtfKMgyumJ7kwm6Ys9A4lCpHx4RU5tbG5jSyrdjTgPdTwRQwy0WUm65PlYR-XAOapx_Gg94_XmiVzAs1k0ipxgKvQRlNFt-P0D_fTMoKE8jZjnC6KNDwxxZQVLMuMJ9NK7e7VjuPtnuJNkRTS_2CMQuG1GKs0F3S7TU3hJZzzN246h3J6uAqfX5gNUmbHZmTQcwP3W3GL9orEvF7mp1VRwf28dWVlx2W4g7kMjNm7p2hlhXVHG_zL7AV5CoQOapyNtj9hWVu7AROxJZXo2lDTtYcY0dPcEn5m2KBKdL0zxTH3q54S4bHNg3lvjoTBxnVU0-K8s_E6_NH59Mp8Uhjxw9vpiwG5glsKfXhPh3gs4JCsGhcELK896arudV5yQwI21HGiyVR7BYrzS_-2=w997-h348-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Regionとして↓が選べます。日本からはAsia Pacificを選んどくと速度的にちょっと速いんだと思われます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Europe&lt;/li&gt;
&lt;li&gt;Asia Pacific&lt;/li&gt;
&lt;li&gt;Australia&lt;/li&gt;
&lt;li&gt;United States&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;画像をみてもらうとわかりますが、&lt;code&gt;United States&lt;/code&gt;を選んだときはFQDNにリージョンが含まれまず、その他の場合は&lt;code&gt;ap&lt;/code&gt;や&lt;code&gt;eu&lt;/code&gt;などが挟まれるようになります。&lt;/p&gt;
&lt;h2 id="コマンド実行"&gt;コマンド実行&lt;/h2&gt;
&lt;p&gt;リージョンをUS以外にした場合には&lt;code&gt;ngrok&lt;/code&gt;コマンドを起動する際にリージョン指定が必要になります。サブドメインのしても合わせると次のようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% ngrok http &lt;span style="color:#ae81ff"&gt;3000&lt;/span&gt; -subdomain&lt;span style="color:#f92672"&gt;=&lt;/span&gt;mydomain -region&lt;span style="color:#f92672"&gt;=&lt;/span&gt;ap
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とまあこんな感じで固定のドメインをゲットしたのでソースコードを毎度変更する必要がなくなりました。めでたい。&lt;/p&gt;</description></item><item><title>MacのQuickTime Playerの再生速度を微調整する</title><link>https://blog.piyo.tech/posts/2018-07-05-quicktime-player-speed/</link><pubDate>Thu, 05 Jul 2018 06:20:54 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-05-quicktime-player-speed/</guid><description>&lt;p&gt;MacのQuickTime Playerで再生速度を微調整できます。社内のMTG動画なんかを動画で共有してもらうときに1.4倍速ぐらいで再生すると時短できけて便利です。&lt;/p&gt;
&lt;p&gt;早送りボタンをクリックすると1x、2x、5x, 10x, 30x, 60xの6段階で変更できますが、こちらは早送りするだけで音声は再生できません。&lt;/p&gt;
&lt;p&gt;微調整の場合は音声を再生できます。方法はoptionキーを押しながら早送りボタンをクリックです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/opqA-IZyGNwYNmd3r8sy_qLob8mKiUTNsNAO6-n9oEMH-yJtnuQUYJeQCvK_fkl-HNU4kHh66Jb7OQVZONQMXthCGl6Paj3T0DEU-Of0l5F-2PCWk85KiczeCrQqR8UFhHJqzf_Ccizi1gUskjDSgXHbUn4Nuli0mwjkXV457AQtNUT2zNlOdC8iaa_8n69-5Rs3bj7SOzOxJZ-Zx59Oz_ZqQGPOIihU5PK-WrIxVRlUEk1ZKmLB-S4nTWTsof-t8POmHl_3BigC2ht5atU5rDfRfoQS04xUZLbLFzzqUWmTQLnxUG13SHpobOTNXl_n54V6_gdrBWGG-xsz_X0UqZsFU3T7JF7mHudv9MTMWhrD5jJ5iyYaZgjSHvL_By0qq0uUUmcz2OZ-FYaqe5PlfwhfxgsQfrPTYM5EXMi8RsROpkHRc5aI1gifhyYlHcrgp4rokrGbNBJ4Dz9bHkqPiE3EFETdh-GLWtRMYsL7Saye_kqMA1Cr_1pQgnFC4JehVNWdCQjK2eRuUM-sXxpmLZEErKXAxKXNqcanGQFf3I3gt2d18H26qqr7Q8k-FXSd3YOX4fNL4Oelb-iVs2vV6xLGO6Aa-mP63BADxdbsuoHOKE_bfnmV-DPMczRWPzWM833M9Q7qnfITiUJIo-fL04MLsjpOR2GWeQ=w1010-h580-no"&gt;&lt;img src="https://lh3.googleusercontent.com/opqA-IZyGNwYNmd3r8sy_qLob8mKiUTNsNAO6-n9oEMH-yJtnuQUYJeQCvK_fkl-HNU4kHh66Jb7OQVZONQMXthCGl6Paj3T0DEU-Of0l5F-2PCWk85KiczeCrQqR8UFhHJqzf_Ccizi1gUskjDSgXHbUn4Nuli0mwjkXV457AQtNUT2zNlOdC8iaa_8n69-5Rs3bj7SOzOxJZ-Zx59Oz_ZqQGPOIihU5PK-WrIxVRlUEk1ZKmLB-S4nTWTsof-t8POmHl_3BigC2ht5atU5rDfRfoQS04xUZLbLFzzqUWmTQLnxUG13SHpobOTNXl_n54V6_gdrBWGG-xsz_X0UqZsFU3T7JF7mHudv9MTMWhrD5jJ5iyYaZgjSHvL_By0qq0uUUmcz2OZ-FYaqe5PlfwhfxgsQfrPTYM5EXMi8RsROpkHRc5aI1gifhyYlHcrgp4rokrGbNBJ4Dz9bHkqPiE3EFETdh-GLWtRMYsL7Saye_kqMA1Cr_1pQgnFC4JehVNWdCQjK2eRuUM-sXxpmLZEErKXAxKXNqcanGQFf3I3gt2d18H26qqr7Q8k-FXSd3YOX4fNL4Oelb-iVs2vV6xLGO6Aa-mP63BADxdbsuoHOKE_bfnmV-DPMczRWPzWM833M9Q7qnfITiUJIo-fL04MLsjpOR2GWeQ=w1010-h580-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>React Nativeでいつjsがbundleされるのか調べた</title><link>https://blog.piyo.tech/posts/2018-07-04-react-native-jsbundle/</link><pubDate>Wed, 04 Jul 2018 06:08:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-04-react-native-jsbundle/</guid><description>&lt;p&gt;React NativeのアプリにはJS層とNative層があり、ビルドは別々に行われます。基本的にネイティブでビルドするときには最新のJS bundleに変更したいはずなので、同時にjs bundleも行われます。&lt;/p&gt;
&lt;h1 id="ios"&gt;iOS&lt;/h1&gt;
&lt;p&gt;iOSではあらかじめXcodeの&lt;code&gt;Build Phase&lt;/code&gt;に組み込まれているため、リリースビルドする際には自動的に&lt;code&gt;main.jsbundle&lt;/code&gt;というファイルが事前に作られた上で、これを同梱する形でビルドが行われます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Qidfy5bnXioED__9sEbBPf3l4ZjtyWbK75G6xWhB41gup1LwXdLogI1N0P_w-0Cb5IqEyOLwGfSKLJcy-aRAPByvY7rAD__cRG56KcquQFu-G6Fem6Dhj-PUEo1niLEEDb4MzrnWd1X9mgX8oFa3bQlZG_reJJfDN06yzaKJujjvXDxsJClMF1JHh0rr-9h4L8QKpfTPEvveNPTBPAu6Tkzb5KXnQoWpLVTt1xvXIMZ3aCfpoT0yMX6cf_p8EZ3z1a5SX9HMXyt5czOzLPEFyRvagxt40YO6dFNsRON7QJ_xufIRBtLM5oVZ3Rpk3opl6-VaexQ_XcMTGbZWHfwXO9BjD1_cwi3m1K_otcq5gTJIUkjLlEBCREsahGbWUBQ3op4bFX6XwhLOk6pkmIUDmXK3yQ9TTkF5avJWOQr5kM1esJWXXe-DL8lkjw0IsQL3olZIuc3b2yvqj-tekkMVgWn3mNExt2eyZ49tffE154xAZOx75W-PgYWAfrlG4inGnmbBmy7j-CdO_5hPRdXs-6YtnwLDpI5u4emWqlHptcrDOhaOejhKreADjItBKaDmnZrVTSmn5OkfQaCshyhwwQCCeAN1ytCV2Rf-y479JNgLu3salD4IKNLXIvg5yQvo384YyapH5DtQMVmvGN4SYuqpUsDob_P2=w948-h434-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Qidfy5bnXioED__9sEbBPf3l4ZjtyWbK75G6xWhB41gup1LwXdLogI1N0P_w-0Cb5IqEyOLwGfSKLJcy-aRAPByvY7rAD__cRG56KcquQFu-G6Fem6Dhj-PUEo1niLEEDb4MzrnWd1X9mgX8oFa3bQlZG_reJJfDN06yzaKJujjvXDxsJClMF1JHh0rr-9h4L8QKpfTPEvveNPTBPAu6Tkzb5KXnQoWpLVTt1xvXIMZ3aCfpoT0yMX6cf_p8EZ3z1a5SX9HMXyt5czOzLPEFyRvagxt40YO6dFNsRON7QJ_xufIRBtLM5oVZ3Rpk3opl6-VaexQ_XcMTGbZWHfwXO9BjD1_cwi3m1K_otcq5gTJIUkjLlEBCREsahGbWUBQ3op4bFX6XwhLOk6pkmIUDmXK3yQ9TTkF5avJWOQr5kM1esJWXXe-DL8lkjw0IsQL3olZIuc3b2yvqj-tekkMVgWn3mNExt2eyZ49tffE154xAZOx75W-PgYWAfrlG4inGnmbBmy7j-CdO_5hPRdXs-6YtnwLDpI5u4emWqlHptcrDOhaOejhKreADjItBKaDmnZrVTSmn5OkfQaCshyhwwQCCeAN1ytCV2Rf-y479JNgLu3salD4IKNLXIvg5yQvo384YyapH5DtQMVmvGN4SYuqpUsDob_P2=w948-h434-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Xcodeで指定しているシェルスクリプト、&lt;code&gt;node_modules/react-native/scripts/react-native-xcode.sh&lt;/code&gt;を見ると&lt;code&gt;react-native&lt;/code&gt;のCLIコマンドでjsbundleを作っていることがわかります。&lt;/p&gt;
&lt;h1 id="android"&gt;Android&lt;/h1&gt;
&lt;p&gt;androidの場合は&lt;code&gt;node_modules/react-native/react.gradle&lt;/code&gt;にコマンド呼び出しの記載があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gradle" data-lang="gradle"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; currentBundleTask &lt;span style="color:#f92672"&gt;=&lt;/span&gt; tasks&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;create&lt;/span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; name: bundleJsAndAssetsTaskName&lt;span style="color:#f92672"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; type: Exec&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 略
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; commandLine&lt;span style="color:#f92672"&gt;(*&lt;/span&gt;nodeExecutableAndArgs&lt;span style="color:#f92672"&gt;,&lt;/span&gt; cliPath&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;bundle&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;--platform&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;android&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;--dev&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;${devEnabled}&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;--reset-cache&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;--entry-file&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;,&lt;/span&gt; entryFile&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;--bundle-output&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;,&lt;/span&gt; jsBundleFile&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;--assets-dest&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;,&lt;/span&gt; resourcesDir&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;extraPackagerArgs&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; enabled config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;bundleIn${targetName}&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;bundleIn${buildTypeName.capitalize()}&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;?:&lt;/span&gt; targetName&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;toLowerCase&lt;/span&gt;&lt;span style="color:#f92672"&gt;().&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;contains&lt;/span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;release&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;app/build.gradle&lt;/code&gt;側の設定もしくはreleaseビルドの際にbundleが作られるようです。&lt;/p&gt;
&lt;p&gt;という、ビルド周りのコードをちょっと読んだよという話でした。&lt;/p&gt;</description></item><item><title>iOSでいい感じのアラートをサクッと出す</title><link>https://blog.piyo.tech/posts/2018-07-03-swift-sclalertview/</link><pubDate>Tue, 03 Jul 2018 06:13:40 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-07-03-swift-sclalertview/</guid><description>&lt;p&gt;SCLAlertView-Swiftがサクッと使うのにいい感じです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/vikmeup/SCLAlertView-Swift" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/a84c6af1289132708ee935a3dd8fb2274154ac08f24b076b85d431c8188da0f6/vikmeup/SCLAlertView-Swift" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - vikmeup/SCLAlertView-Swift: Beautiful animated Alert View. Written in Swift&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Beautiful animated Alert View. Written in Swift. Contribute to vikmeup/SCLAlertView-Swift development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;簡単ですが、使用例です。サンプルアプリにボタン3つおいておきます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/taKOks15O42HMmbVCgqjZYx22LkkHFVh5HWU7H3-4qFtOCks1HeMdqzGfc5sFSOXqRwImglBzEc1iYi5WFPCKV2QHWfC7xqo_J6MEqGw4HMk-hiYRlcUgMTEDFBpHivZNnaYIx3hOBzqCO2OwbubSLmaD9ASYEFgPe_GnchbNm8MM-6MIyrV8fyJyCP7nBZ2ixyJiU3XtxSSxlIemD9EF-bYb4h_F1eh9OAARxQdCqX1yXUiDRGJ7d-I70kR4q1bFUOiCxOmxbbqd5_17PXhDNCoIDf8GtdvR71XGG0hGNd_n1m-dfANBx7izgTl7i56UvaP_BlRt6V781xbowqIoa1sJtrC1aUznYjgxF9VDbbNenYtRy3mxO618MwuzaK88E65FFg2DK7Q_ITuvmxlxwQGew2w_Sa17J4jvBPWGIcr1YWcX08ZOv64HPwbYwEH6zpaCrsUhr0D13gIRiog3dD3WwqsHpCvd0cR5gzVaC4-ECkoQvrYxZ_hMYsVKuMXd7XFn58vdg-W6Rmu6sBvNnDwyzSKqcaA9_EUJaXh3uLUNnPWA0GrG2BdOFi1Ya_AcJvNNXposaXFkZ4bocX9n05IUgbsfggvvgE-pfrSFSXMBOnrxxmFT3puV1203LTfpnOsOW4_2DMXyGrk-uRhXHIZTReHWsU_=w119-h257-no"&gt;&lt;img src="https://lh3.googleusercontent.com/taKOks15O42HMmbVCgqjZYx22LkkHFVh5HWU7H3-4qFtOCks1HeMdqzGfc5sFSOXqRwImglBzEc1iYi5WFPCKV2QHWfC7xqo_J6MEqGw4HMk-hiYRlcUgMTEDFBpHivZNnaYIx3hOBzqCO2OwbubSLmaD9ASYEFgPe_GnchbNm8MM-6MIyrV8fyJyCP7nBZ2ixyJiU3XtxSSxlIemD9EF-bYb4h_F1eh9OAARxQdCqX1yXUiDRGJ7d-I70kR4q1bFUOiCxOmxbbqd5_17PXhDNCoIDf8GtdvR71XGG0hGNd_n1m-dfANBx7izgTl7i56UvaP_BlRt6V781xbowqIoa1sJtrC1aUznYjgxF9VDbbNenYtRy3mxO618MwuzaK88E65FFg2DK7Q_ITuvmxlxwQGew2w_Sa17J4jvBPWGIcr1YWcX08ZOv64HPwbYwEH6zpaCrsUhr0D13gIRiog3dD3WwqsHpCvd0cR5gzVaC4-ECkoQvrYxZ_hMYsVKuMXd7XFn58vdg-W6Rmu6sBvNnDwyzSKqcaA9_EUJaXh3uLUNnPWA0GrG2BdOFi1Ya_AcJvNNXposaXFkZ4bocX9n05IUgbsfggvvgE-pfrSFSXMBOnrxxmFT3puV1203LTfpnOsOW4_2DMXyGrk-uRhXHIZTReHWsU_=w119-h257-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;showSuccess&lt;/code&gt;で成功時のアラートが、&lt;code&gt;showError&lt;/code&gt;でエラーじのアラートがそれぞれ出せます。他にも&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;showWarning&lt;/li&gt;
&lt;li&gt;showInfo&lt;/li&gt;
&lt;li&gt;showNotice&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;があります。&lt;/p&gt;
&lt;h2 id="showsuccess"&gt;showSuccess&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@IBAction&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;showSuccess&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; sender: Any) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; SCLAlertView().showSuccess(&lt;span style="color:#e6db74"&gt;&amp;#34;サクセス&amp;#34;&lt;/span&gt;, subTitle: &lt;span style="color:#e6db74"&gt;&amp;#34;保存しました&amp;#34;&lt;/span&gt;, closeButtonTitle: &lt;span style="color:#e6db74"&gt;&amp;#34;閉じる&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Vk3Kh4LeJTvUPMSZUJR9klcCuFWRt4UB_eZ--LyZgYlMM8ctHNVWmNWWUFjmvWFYyYiYNK6KoFDIknSTGW2BD4-ThF-aeb41GjseYn67voyDfbnqe846GTFUlStXG2VdN6HvRzlVZw7JgE-jQWZqXDUstEew7WlUNtOebBKndai7QfTAIhUnBTO1yYwrBm_4oe4XY5qJQvwXsXzvXCktSKkvX_I1H2qDXoCxsv1ABj7t1HlOY6iJa40KRwJx2NykPLxBegrfSIgcCpsU84jwlVN8zc0w-SZyRjqVIIZU5oaprjD4mqPemS8u6mP5CY1c8urzTdh1aL3vqAhXOLV9sIM6AkYuX94gG50qKDTDLFmvbOw517pP66ERXJ3tTwCYXmOTV5chxZzYNqeWdrh01o3cOsez3tcZbXDpQkneOvkdL9TPSA21qpPEraOdd7Hfau7Z2DgPQAL1hwDxPGZqGqlPudhcEjF2Xsp2UZK-qU_JUJSc1ajCDMo4fwVaeoPamB-vuhjtoc1P4wiLTmTFPwDUhFoi_TAbczC8dHIxa0_r5em7Cq0aNERTs608e3TCBwz2qBdBAke3faHFPNbUTArzxszXlSYKzc0qs0VKHDD5IcPrRHayS3PZjUyZFfgEdU-HMCCsCuS1A8AlR0ozF1gPJKEZIZ8j=w692-h1496-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Vk3Kh4LeJTvUPMSZUJR9klcCuFWRt4UB_eZ--LyZgYlMM8ctHNVWmNWWUFjmvWFYyYiYNK6KoFDIknSTGW2BD4-ThF-aeb41GjseYn67voyDfbnqe846GTFUlStXG2VdN6HvRzlVZw7JgE-jQWZqXDUstEew7WlUNtOebBKndai7QfTAIhUnBTO1yYwrBm_4oe4XY5qJQvwXsXzvXCktSKkvX_I1H2qDXoCxsv1ABj7t1HlOY6iJa40KRwJx2NykPLxBegrfSIgcCpsU84jwlVN8zc0w-SZyRjqVIIZU5oaprjD4mqPemS8u6mP5CY1c8urzTdh1aL3vqAhXOLV9sIM6AkYuX94gG50qKDTDLFmvbOw517pP66ERXJ3tTwCYXmOTV5chxZzYNqeWdrh01o3cOsez3tcZbXDpQkneOvkdL9TPSA21qpPEraOdd7Hfau7Z2DgPQAL1hwDxPGZqGqlPudhcEjF2Xsp2UZK-qU_JUJSc1ajCDMo4fwVaeoPamB-vuhjtoc1P4wiLTmTFPwDUhFoi_TAbczC8dHIxa0_r5em7Cq0aNERTs608e3TCBwz2qBdBAke3faHFPNbUTArzxszXlSYKzc0qs0VKHDD5IcPrRHayS3PZjUyZFfgEdU-HMCCsCuS1A8AlR0ozF1gPJKEZIZ8j=w692-h1496-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="showerror"&gt;showError&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;closeButtonTitle&lt;/code&gt;を指定しないとボタンのラベルはDoneとなります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@IBAction&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;showError&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; sender: Any) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; SCLAlertView().showError(&lt;span style="color:#e6db74"&gt;&amp;#34;エラー&amp;#34;&lt;/span&gt;, subTitle: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/rRhY8bBwTj4NqgK1p2NDKs-82fWFQ8PgRzYx94A2sYgQxAQHRdwlJ89C1lAgxtghdaiWpgRRQ9E6o1fKlwPA0Q4kD_CKHgBQKNpvfe03jTrmiOmH1PKQ43WHqjIcErN2OfCMuKVUwoK2csQEwWNuWAnPfEVULhlBiWo7hiz_qYEmHDu-HXexJSvh5hIQvvuFRWPPSGoXkiUR_-Fzk7aNobXDI05ZPrusEMj5xiCRAQPU57h-PtuEWUJQEy_vEp6yE0Xpgs2Xv25S2jjc3PSQuNf-z2BrsffuoLEAx8iCbbSFiGhZQMkTpOmv_2GOezplEQBYj9Gfo4izUtXveZJ6DfH8vsxLdoaFPmcVRs6ryTFTCk-iAup6mhCdFoW2Wm6rNMyzjbV6SxjXfUHPSgmzVyDf-TKpDZTOYNDVYxsRKxcSOFVeNO8opYb8YyJVgyeA6N7g7dM0nXAplT9nwmpmAEdxbZU9LTNBSHvgSTrl6TmtCqqFisOs3QybPKGEd0wWODugZZY9SOYt3n9kCBmnQnYl3tabB8XvgAfAuV0zrGgmOP9k4hKXTlHHMEBTHJyoY1R_z3CBOlLdxRTK8wB48Ltxdef_6NSbYe242LwFzAsEm8pOuz0Be-AuTA7DJgN2ZoHupzTp6IIVhVKXu7obkNFEKAAzUB0E=w692-h1496-no"&gt;&lt;img src="https://lh3.googleusercontent.com/rRhY8bBwTj4NqgK1p2NDKs-82fWFQ8PgRzYx94A2sYgQxAQHRdwlJ89C1lAgxtghdaiWpgRRQ9E6o1fKlwPA0Q4kD_CKHgBQKNpvfe03jTrmiOmH1PKQ43WHqjIcErN2OfCMuKVUwoK2csQEwWNuWAnPfEVULhlBiWo7hiz_qYEmHDu-HXexJSvh5hIQvvuFRWPPSGoXkiUR_-Fzk7aNobXDI05ZPrusEMj5xiCRAQPU57h-PtuEWUJQEy_vEp6yE0Xpgs2Xv25S2jjc3PSQuNf-z2BrsffuoLEAx8iCbbSFiGhZQMkTpOmv_2GOezplEQBYj9Gfo4izUtXveZJ6DfH8vsxLdoaFPmcVRs6ryTFTCk-iAup6mhCdFoW2Wm6rNMyzjbV6SxjXfUHPSgmzVyDf-TKpDZTOYNDVYxsRKxcSOFVeNO8opYb8YyJVgyeA6N7g7dM0nXAplT9nwmpmAEdxbZU9LTNBSHvgSTrl6TmtCqqFisOs3QybPKGEd0wWODugZZY9SOYt3n9kCBmnQnYl3tabB8XvgAfAuV0zrGgmOP9k4hKXTlHHMEBTHJyoY1R_z3CBOlLdxRTK8wB48Ltxdef_6NSbYe242LwFzAsEm8pOuz0Be-AuTA7DJgN2ZoHupzTp6IIVhVKXu7obkNFEKAAzUB0E=w692-h1496-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="独自ボタン"&gt;独自ボタン&lt;/h2&gt;
&lt;p&gt;独自のボタンを追加して個別の処理を割り当てることができます。closeボタンには直接処理を割り当てられないので、何もせずに閉じる用途がない場合には&lt;code&gt;showCloseButton: false&lt;/code&gt;なapperanceを使ってアラートを生成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@IBAction&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;showConfirm&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; sender: Any) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; appearance = SCLAlertView.SCLAppearance(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; showCloseButton: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; alert = SCLAlertView(appearance: appearance)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; alert.addButton(&lt;span style="color:#e6db74"&gt;&amp;#34;Cancel&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;cancel&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; alert.addButton(&lt;span style="color:#e6db74"&gt;&amp;#34;OK&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;ok&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; alert.showInfo(&lt;span style="color:#e6db74"&gt;&amp;#34;確認&amp;#34;&lt;/span&gt;, subTitle: &lt;span style="color:#e6db74"&gt;&amp;#34;よろしいですか？&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/DpGTOlIcfQRyIV-8sdTJY0jNPV6U61U-FO4BMnuksid3npHytYGwnubbw4k2P9s3xkVrQsEVb7X5qB7UrvbnuFv3le273-S8C4pnMdTaCB-oFPdO-Kq7bgICVBwb6ivE-kAx6snwf5oDLalLWQJoq3Q3d9uGuDj1n3X7RKRGwrpalF7Z1SC5YW3Yl-zVhDvNxyU58s96Ci0Mtk18PZAqrhpTBBY_nMR_3gpTFcw09dx6xB-esbwLOAfknuO4febIxRXr3ZfknamKcdMrntUru_JjfeE8nADUpViJcOCxQ3uBZ0v0nGHCMiVrzxIPhIo7nkP2HHhe3CtfGz0Byl8MS2CpHmszc6v62VGh3UQfRY0-BNiN9ZT99eiuQb_d4JAXKWZrCNww7ciHEUQtnnoVKnKoRKKld-j2BlWU3W_9IHktNrUlrvyvDcwDqz7YHGK-NVjn0qzhWi2mnDhJGpJFrMABoo7AIYel1ACrQ0Ry_4W1TgpHidQpHVyEMznOg5Bfm0ARk9pv2zpHULwbpl6vfLA_ZUsSh-aTZcZqb8PtHlX9V2lV-hqgEOk1bIncBW20jjZ1YDvSzwLAEbZS5LgpVFublTJunT02QLArUxKsJtKLd-kBpm-1tqH09ZNJrIwxuuFllQgZIQRjfTNhfkGfcVNrZsFUmLqJ=w692-h1496-no"&gt;&lt;img src="https://lh3.googleusercontent.com/DpGTOlIcfQRyIV-8sdTJY0jNPV6U61U-FO4BMnuksid3npHytYGwnubbw4k2P9s3xkVrQsEVb7X5qB7UrvbnuFv3le273-S8C4pnMdTaCB-oFPdO-Kq7bgICVBwb6ivE-kAx6snwf5oDLalLWQJoq3Q3d9uGuDj1n3X7RKRGwrpalF7Z1SC5YW3Yl-zVhDvNxyU58s96Ci0Mtk18PZAqrhpTBBY_nMR_3gpTFcw09dx6xB-esbwLOAfknuO4febIxRXr3ZfknamKcdMrntUru_JjfeE8nADUpViJcOCxQ3uBZ0v0nGHCMiVrzxIPhIo7nkP2HHhe3CtfGz0Byl8MS2CpHmszc6v62VGh3UQfRY0-BNiN9ZT99eiuQb_d4JAXKWZrCNww7ciHEUQtnnoVKnKoRKKld-j2BlWU3W_9IHktNrUlrvyvDcwDqz7YHGK-NVjn0qzhWi2mnDhJGpJFrMABoo7AIYel1ACrQ0Ry_4W1TgpHidQpHVyEMznOg5Bfm0ARk9pv2zpHULwbpl6vfLA_ZUsSh-aTZcZqb8PtHlX9V2lV-hqgEOk1bIncBW20jjZ1YDvSzwLAEbZS5LgpVFublTJunT02QLArUxKsJtKLd-kBpm-1tqH09ZNJrIwxuuFllQgZIQRjfTNhfkGfcVNrZsFUmLqJ=w692-h1496-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>「更に大体いい感じになるKeynoteテンプレート」Azusa Colorsオススメ</title><link>https://blog.piyo.tech/posts/2018-06-30-azusa-keynote-template/</link><pubDate>Sat, 30 Jun 2018 06:10:46 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-30-azusa-keynote-template/</guid><description>&lt;p&gt;今更ですが、Azusa ColorsっていうKeynoteのテンプレートがお気に入りです。元々はAzusaだったんですが、ずいぶん前に色が増えました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://memo.sanographix.net/post/113681262780" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://64.media.tumblr.com/a13b7f64573546b17466ed4e5c0d6ae7/tumblr_nl906fnlDB1rvxvuco2_r1_1280.gif" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;更に大体いい感じになるkeynoteテンプレート「Azusa Colors」作った - MEMOGRAPHIX&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;更に大体いい感じになるkeynoteテンプレート「Azusa Colors」作った いい感じのスライド、作るのむずいので、「Azusa Colors」っていうKeynoteテンプレートを作った。下記のサイトからダウンロードできる。 • Azusa Colors - 大体いい感じになるKeynoteテンプレート 解説 [[MORE]] デモも兼ねた解説スライドを作った。 • Introducing...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://64.media.tumblr.com/avatar_59f2cba64d68_128.pnj" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;memo.sanographix.net&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/hqJDGnRJA8kc2ID9MN3f22oGMs5rkBxRskc04kMV2qsHWoHXCvPhLLSA1hJbmL6QSDmPSK65AU093UyK1iFebKoFtcKzO_BJrORManyhlnlCPEkeYSUgrBwy5cO-Y9D0wqkgzvWEbfWUbGwi1_zki7hxwHQ82FY95nrB_CUZV3d-tQEuhXxlzSIwxPeYF65ecZglSHrkEbUrbMPiq9vxISIvY1y7bidZY-FYfd3aQSOcD_Pj38Go6IhZmwohKLWrl6yswEe7MLd9gBB_npe76LniqEjad-ZvYhSVp1-QCCGAf3mSzt2DLjQ0cWZhuBD2WgPvJTpOznQJpVFYqKNkCMAOF6qMALNNjpdswynm6dEFq2WwmQaVqJxl5lt1qRTjTVTiBWIPHmZLbp_oJ4YjIwrF0tepcs6Wm7bMB9Q1_DtKbgJoqArBVzRKakJwijEuUh33Qge5e7YSlzYeP7fG2Vlx0jMmlJFR_06KovG8YiTrme4g0tOhRf0Uy_MmNgdC5cBmXZ7dcUAAS8_v19Tju6zTM_cW9vxFE3ngFr_v22hNq4S_9iyavmk5jx1wLjuBEiwUglNWGRPprRmzi4p0R2XxryqUmKtL5isPx9cPu0wOOd-YYIgNUNFAb7qRBe18pqdnq7U0MoLLMPaUY6kmYHQQ-EkfKn2J=w500-h375-no"&gt;&lt;img src="https://lh3.googleusercontent.com/hqJDGnRJA8kc2ID9MN3f22oGMs5rkBxRskc04kMV2qsHWoHXCvPhLLSA1hJbmL6QSDmPSK65AU093UyK1iFebKoFtcKzO_BJrORManyhlnlCPEkeYSUgrBwy5cO-Y9D0wqkgzvWEbfWUbGwi1_zki7hxwHQ82FY95nrB_CUZV3d-tQEuhXxlzSIwxPeYF65ecZglSHrkEbUrbMPiq9vxISIvY1y7bidZY-FYfd3aQSOcD_Pj38Go6IhZmwohKLWrl6yswEe7MLd9gBB_npe76LniqEjad-ZvYhSVp1-QCCGAf3mSzt2DLjQ0cWZhuBD2WgPvJTpOznQJpVFYqKNkCMAOF6qMALNNjpdswynm6dEFq2WwmQaVqJxl5lt1qRTjTVTiBWIPHmZLbp_oJ4YjIwrF0tepcs6Wm7bMB9Q1_DtKbgJoqArBVzRKakJwijEuUh33Qge5e7YSlzYeP7fG2Vlx0jMmlJFR_06KovG8YiTrme4g0tOhRf0Uy_MmNgdC5cBmXZ7dcUAAS8_v19Tju6zTM_cW9vxFE3ngFr_v22hNq4S_9iyavmk5jx1wLjuBEiwUglNWGRPprRmzi4p0R2XxryqUmKtL5isPx9cPu0wOOd-YYIgNUNFAb7qRBe18pqdnq7U0MoLLMPaUY6kmYHQQ-EkfKn2J=w500-h375-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;（↑のリンクからお借りしています）&lt;/p&gt;
&lt;p&gt;どうしても青系統が好きなので右上のBlueや左下のCyanを使うことが多いです（そもそもあまり作ることないけど）&lt;/p&gt;
&lt;p&gt;という、自分の好きなものを紹介するだけの記事でした。&lt;/p&gt;</description></item><item><title>json-serverでjsonに書いたデータを返すモックサーバーを立てる</title><link>https://blog.piyo.tech/posts/2018-06-29-json-server/</link><pubDate>Fri, 29 Jun 2018 06:09:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-29-json-server/</guid><description>&lt;p&gt;サーバーサイドの実装がまだないときとか環境設定が面倒なとき、クライアントサイドでWebリクエストを投げるコードをそれっぽく書いて試したいみたいなケースで、json-serverというJSのツールが便利でした。&lt;/p&gt;
&lt;p&gt;僕の場合はwebページ上でXHRを投げる部分を試したくてjson-serverを使いました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/typicode/json-server" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/71b39fedbc8f3269470beb73770fb6f6a4a475d0f2e4ecf05ac9e8d284d5d112/typicode/json-server" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - typicode/json-server: Get a full fake REST API with zero coding in less than 30 seconds (seriously)&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Get a full fake REST API with zero coding in less than 30 seconds (seriously) - typicode/json-server&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;そのときはあまり気づかなかったですが、Star数えぐいですね。3万超えです。&lt;/p&gt;
&lt;p&gt;コマンドベースのツールで、npmで入れます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% npm install -g json-server
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;jsonファイルを指定して起動します。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% json-server --watch db.json
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;中身はリクエスト時に返すための情報が書かれてします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;posts&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; { &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;json-server&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;author&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;typicode&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;comments&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; { &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;body&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;some comment&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;postId&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;profile&amp;#34;&lt;/span&gt;: { &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;typicode&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こんへんはドキュメントをみればすぐにわかります。&lt;/p&gt;
&lt;p&gt;で、いいなーと思ったのは、サーバーを起動したときです。標準出力に↓のような情報がでています。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Resources&lt;/code&gt;というところにURLがリストされていますね。ここで有効なURLをパッと確認できるので例えばブラウザで叩くなり、curlコマンドで試すなり、クライアントサイドのアプリから試すなりと色々な使い方ができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;% json-server --watch db.json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; \{^_^}/ hi!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; Loading db2.json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; Done
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; Resources
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; http://localhost:3000/posts
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; http://localhost:3000/comments
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; http://localhost:3000/profile
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; Home
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; http://localhost:3000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; Type s + enter at any time to create a snapshot of the database
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; Watching...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;GET /posts/ 200 8.440 ms - 77
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;GET /posts/1 200 4.913 ms - 63
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;GET /posts/2 404 3.118 ms - 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;GET /profile 200 2.962 ms - 24
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、GET以外のリクエストにも対応しています。まずはPOSTを試してみます。（リクエストを組み立てるのにPostmanを使いました）&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-06-08-postman/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;blog.piyo.tech →&lt;/span&gt;&lt;span&gt;https://blog.piyo.tech/posts/2018-06-08-postman/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;http://localhost:3000/posts&lt;/code&gt;に次のようなjsonをPOSTしました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;added by post request&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;author&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;hiro&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/I-C2fKPesgw92H54ipDEyPEQjQ3AJx3pD3kwcTRQkeCr_gOELW97MCUmBfg5wbLZVboLWAbBNO94LB9sM21yzjfWTQG0Ei9wNKnJmd1LUPkngyovGrvw5HuGbsjGSpSw-g1edHg1-2JqvGGsj715ry5PQLoXAE4qSDb0lgbzAKcjg47XFSpSZj-pS9HYnIa0k1iY7in3bwctK_7MTc04_2CcIuiyNggDqnqImVFo6-nIHv7CWcCHNPTVOz3H9Har6iZiXpSq7lH81bdBMBeb-25kek8wSr6cM2-HuefcZyxlZv-tz6slYCPj91iQVEdQBy_EwTK0RgqrbnjyaAfPhl8n8KiKLEhPmc4p0gQJxxxG87LWp_pcHOqJNco5fYF4iPUJVOnf5brTjrpDAffg0gNjuyCU06U57sxaKIjrorXdFO1XYWP3wsQa2ZCmxnhnf0p_MXA_qNa9FhWu4DBVArHA_comfbPt4lts5YcsUdt3oqbmj_IkU6h3ivtegDBt0jUNo1CgtoIV4bKflMgTB8adCm-rRnJlm5o0_agtZHiaKllST0dN6OhbtHzO3Oew7IVX0FZkx1CilnErPO_8YD4jP7KXCaICczGeyFI8uEfCbHTjrmWi4WVBoW3CiNFbDakDK3sUQTqhEoRe5aFchmT34OXvsQVM=w636-h287-no"&gt;&lt;img src="https://lh3.googleusercontent.com/I-C2fKPesgw92H54ipDEyPEQjQ3AJx3pD3kwcTRQkeCr_gOELW97MCUmBfg5wbLZVboLWAbBNO94LB9sM21yzjfWTQG0Ei9wNKnJmd1LUPkngyovGrvw5HuGbsjGSpSw-g1edHg1-2JqvGGsj715ry5PQLoXAE4qSDb0lgbzAKcjg47XFSpSZj-pS9HYnIa0k1iY7in3bwctK_7MTc04_2CcIuiyNggDqnqImVFo6-nIHv7CWcCHNPTVOz3H9Har6iZiXpSq7lH81bdBMBeb-25kek8wSr6cM2-HuefcZyxlZv-tz6slYCPj91iQVEdQBy_EwTK0RgqrbnjyaAfPhl8n8KiKLEhPmc4p0gQJxxxG87LWp_pcHOqJNco5fYF4iPUJVOnf5brTjrpDAffg0gNjuyCU06U57sxaKIjrorXdFO1XYWP3wsQa2ZCmxnhnf0p_MXA_qNa9FhWu4DBVArHA_comfbPt4lts5YcsUdt3oqbmj_IkU6h3ivtegDBt0jUNo1CgtoIV4bKflMgTB8adCm-rRnJlm5o0_agtZHiaKllST0dN6OhbtHzO3Oew7IVX0FZkx1CilnErPO_8YD4jP7KXCaICczGeyFI8uEfCbHTjrmWi4WVBoW3CiNFbDakDK3sUQTqhEoRe5aFchmT34OXvsQVM=w636-h287-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;するとコンソールにはこのようなログが流れ→&lt;code&gt;POST /posts 201 53.069 ms - 69&lt;/code&gt;、元ファイルには&lt;code&gt;id=2&lt;/code&gt;のpostが登録されています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;posts&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;json-server&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;author&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;typicode&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;added by post request&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;author&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;hiro&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;comments&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;body&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;some comment&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;postId&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;profile&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;typicode&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;http://localhost:3000/posts/2&lt;/code&gt;にDELETEを投げたところ先程追加された&lt;code&gt;id=2&lt;/code&gt;のpostが削除されます。&lt;/p&gt;
&lt;p&gt;というような感じでサーバーサイドがなくても、リクエストを投げて返ってくるような簡易なサーバーを一瞬で立てられます。ダミーでいいから誰かにリクエストを投げて動きを確認したいみたいなときに重宝するのではないかと思います。&lt;/p&gt;</description></item><item><title>7月14日に「SonicGarden Tech 2＠浜松」開催します</title><link>https://blog.piyo.tech/posts/2018-06-28-sgtech-hamamatsu/</link><pubDate>Thu, 28 Jun 2018 06:11:58 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-28-sgtech-hamamatsu/</guid><description>&lt;p&gt;僕の住む浜松にてSonicGarden Techというイベントの第2回を開催します。今回はReact Nativeをテーマとしています。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;↓↓詳細や参加登録はこちらから↓↓&lt;/strong&gt;&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://sonicgarden.connpass.com/event/87520/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://media.connpass.com/thumbs/3c/c5/3cc50f13b060a69d163fd5d305b90db3.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;React Nativeを学ぶ！ 〜 SonicGarden Tech #2 浜松 (2018/07/14 14:00〜)&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;## What&amp;#39;s SonicGarden Tech SonicGarden Techは、ソニックガーデンが全国で働くメンバーと交流する目的も兼ねた技術勉強会です。 今回のテーマは、React Native。 React NativeとはFacebookが中心となって開発しているネイティブアプリのためのフレームワークです。 Reactには「Learn once, Write anywhere(一度学べば、どこでも書ける)」という思想があり、React NativeはReactで学んだ知識を活かして、iOS, Androidなど異なるプラットフォームで...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://connpass.com/static/20260423.e62af57/img/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;sonicgarden.connpass.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;テーマはReact Nativeですが、ソニックガーデンのメンバーとの交流も兼ねたイベントでもあります。社長はじめエンジニアが数人来て話す予定です。&lt;/p&gt;
&lt;p&gt;ソニックガーデンのことを聞いたことあるよという人や、RubyとかWebとかスマホアプリやってるよーみたいな人はReact Nativeのことをあまり知らなくても大丈夫なのでぜひ参加してください〜！懇親会もあります。&lt;/p&gt;
&lt;p&gt;ちなみに、前回は岡山県にてPWAをテーマに開催しました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sonicgarden.connpass.com/event/81107/"&gt;SonicGarden Tech #1 岡山 - connpass&lt;/a&gt;&lt;/p&gt;</description></item><item><title>MacのChromeでAmazonの領収書印刷がおかしい</title><link>https://blog.piyo.tech/posts/2018-06-27-amazon-order-pdf/</link><pubDate>Wed, 27 Jun 2018 06:24:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-27-amazon-order-pdf/</guid><description>&lt;p&gt;記憶がちょっと曖昧ですが、少なくともここ1ヶ月ぐらいAmazonの領収書の印刷（PDF出力）がMacのChromeでおかしいようです。Windowsは未確認です。&lt;/p&gt;
&lt;h1 id="chrome"&gt;Chrome&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/ZnmDOD6d-qa60czgxLNZVyNP6VpMzHK0VqjtcU_0D5h9a9icYKiEoKptBxu_sLwcyYlR1KyraB0iZ4mqAOHmRW_vvCs98MPTY4V44UiGdwUX3sN8nQlovEfZ-QBYlWgDmJ5okRKX7qlrRUHmgGJzzX3ULCY924-G55ZkQqWhWtTxnRZPF1KkonZ9_nd2cp3rGwqzsQaHxTWoQUpQz0kvyrbP-0RqsP2yEQB6OpnOb3sJNt8eCV9pUcCoQ8syPQZpjA_hMu2gwS1ds8mIuQ6rg-z9jcUVeyJ3gPjMoSisq4gyG4lpm4zooAh6104RkoiXbCy6hKE4ZH0hqauv4jADQe7estlcWPbiGVHTRTciYPNzM3SVqQQOvQyWyvkBULQwkPya_PmqrbNhXMMrf3TT5OxfPK1V1z3NO1j8aSl8qbIhWEjTzPZWlQ5xcQqteK8mheszcSAStY4rmYYRjvBLy2VLg0h-o99htcfsKHbNpSZqNWwv9k4_OSUYDoUQsZHQDmULEAGcFqT_P42hDTkob7PzoopBw1Et9Q0fHWywyZT2Dd2a2hzN34v4w5FyGNPRCnHwQy-J0O_G67FBQ9l91DF36yy6N09TCnXkKwxDb0IhXsedUC8CSOyd8SK50RB2mOJcZoFUcTCWTMHgYEqRztDk_mxGwjbY=w1080-h765-no"&gt;&lt;img src="https://lh3.googleusercontent.com/ZnmDOD6d-qa60czgxLNZVyNP6VpMzHK0VqjtcU_0D5h9a9icYKiEoKptBxu_sLwcyYlR1KyraB0iZ4mqAOHmRW_vvCs98MPTY4V44UiGdwUX3sN8nQlovEfZ-QBYlWgDmJ5okRKX7qlrRUHmgGJzzX3ULCY924-G55ZkQqWhWtTxnRZPF1KkonZ9_nd2cp3rGwqzsQaHxTWoQUpQz0kvyrbP-0RqsP2yEQB6OpnOb3sJNt8eCV9pUcCoQ8syPQZpjA_hMu2gwS1ds8mIuQ6rg-z9jcUVeyJ3gPjMoSisq4gyG4lpm4zooAh6104RkoiXbCy6hKE4ZH0hqauv4jADQe7estlcWPbiGVHTRTciYPNzM3SVqQQOvQyWyvkBULQwkPya_PmqrbNhXMMrf3TT5OxfPK1V1z3NO1j8aSl8qbIhWEjTzPZWlQ5xcQqteK8mheszcSAStY4rmYYRjvBLy2VLg0h-o99htcfsKHbNpSZqNWwv9k4_OSUYDoUQsZHQDmULEAGcFqT_P42hDTkob7PzoopBw1Et9Q0fHWywyZT2Dd2a2hzN34v4w5FyGNPRCnHwQy-J0O_G67FBQ9l91DF36yy6N09TCnXkKwxDb0IhXsedUC8CSOyd8SK50RB2mOJcZoFUcTCWTMHgYEqRztDk_mxGwjbY=w1080-h765-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="safari"&gt;Safari&lt;/h1&gt;
&lt;p&gt;ブラウザを変えたらうまくいきました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/OzLGUIsCkZo54KWyGG8iExhTFMxDwfbHZfWtnnP3PgovglDJp6Y1lvT3XpyX6D6obWWHE8NLfTJ7uJP9n3tYOPXXgtOpflpeH3YXkJfKvBu_7xN9KGkRomtDok-_eAjfXU7CaSFLVINCpGRAafRAFL1IWKubBM1xyXrq7yVblP_qaXMCxJYIJikQieKNLEGHIr-mnm34jVDB2Ae64SEJZyBCypz_vgDvKAax9QfAS0Mfd7TegrQGcXYV1vEzHn8J9cmbCcJ3aD7iZKol-G295n3I_dof9UfuikSzO3gzkjL8EpinJqx7Xw8tfaJ3DUXfdq8ZwkKhUo4xHBOMre130xoZDR1t_zJHS83HzOJVUaQgyO2nxSMLs07daWVPiH8euhvK6tFZLbbsMDm9vUhzRx9xWrXsMe7WA_64yMaf-HK3N3MxTbUnuH45DRoFzfArdcp5ZFt3_PQO0xbAp3qEMHEivh_hEB5b_28kK87QUe61ttmSgKi1ogXWWDAPChd7tV__3Kd9ODz1FnK3rKoCD1wVk63iN1N0AhA0E2iKhnqSum2c_KuzLit8UELtG85CCHCv6edvEhu2B_t0sQaIxEkx1iRXunT1lWbX2n_IdkCzd-XnfBi_HpKwij7UTmzkMkaqt20jP3FN2uxDGRDBpwByEHrlyc_4=w581-h814-no"&gt;&lt;img src="https://lh3.googleusercontent.com/OzLGUIsCkZo54KWyGG8iExhTFMxDwfbHZfWtnnP3PgovglDJp6Y1lvT3XpyX6D6obWWHE8NLfTJ7uJP9n3tYOPXXgtOpflpeH3YXkJfKvBu_7xN9KGkRomtDok-_eAjfXU7CaSFLVINCpGRAafRAFL1IWKubBM1xyXrq7yVblP_qaXMCxJYIJikQieKNLEGHIr-mnm34jVDB2Ae64SEJZyBCypz_vgDvKAax9QfAS0Mfd7TegrQGcXYV1vEzHn8J9cmbCcJ3aD7iZKol-G295n3I_dof9UfuikSzO3gzkjL8EpinJqx7Xw8tfaJ3DUXfdq8ZwkKhUo4xHBOMre130xoZDR1t_zJHS83HzOJVUaQgyO2nxSMLs07daWVPiH8euhvK6tFZLbbsMDm9vUhzRx9xWrXsMe7WA_64yMaf-HK3N3MxTbUnuH45DRoFzfArdcp5ZFt3_PQO0xbAp3qEMHEivh_hEB5b_28kK87QUe61ttmSgKi1ogXWWDAPChd7tV__3Kd9ODz1FnK3rKoCD1wVk63iN1N0AhA0E2iKhnqSum2c_KuzLit8UELtG85CCHCv6edvEhu2B_t0sQaIxEkx1iRXunT1lWbX2n_IdkCzd-XnfBi_HpKwij7UTmzkMkaqt20jP3FN2uxDGRDBpwByEHrlyc_4=w581-h814-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>rails-ujsのdata-confirmを自前のダイアログに置き換える</title><link>https://blog.piyo.tech/posts/2018-06-26-override-rails-js-confirm/</link><pubDate>Tue, 26 Jun 2018 06:44:16 +0000</pubDate><guid>https://blog.piyo.tech/posts/2018-06-26-override-rails-js-confirm/</guid><description>&lt;p&gt;Railsではリンクやフォームに簡単に確認ダイアログを出すための記法があります。aタグやinputタグなどに&lt;code&gt;data-confirm=&amp;quot;よろしいですか？&amp;quot;&lt;/code&gt;みたいにするやつですね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;%=&lt;/span&gt; link_to &lt;span style="color:#e6db74"&gt;&amp;#39;delete&amp;#39;&lt;/span&gt;, item_path(item), &lt;span style="color:#e6db74"&gt;data&lt;/span&gt;: { &lt;span style="color:#e6db74"&gt;confirm&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;are you sure?&amp;#39;&lt;/span&gt; } &lt;span style="color:#f92672"&gt;%&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これをするとブラウザの確認ダイアログが出ます。ここでキャンセルした場合はリクエストは投げられません。&lt;/p&gt;
&lt;p&gt;というものなのですが、これをかっこよくしたいとか「以後表示しない」みたいなことをさせたくないみたいな理由で、ブラウザのダイアログを使いたくないみたいなことが場合によっては発生します。&lt;/p&gt;
&lt;p&gt;↑のような機能は&lt;code&gt;rails-ujs&lt;/code&gt;というjavascriptによって提供されています（他の処理もいろいろやっています）。元々は&lt;code&gt;jquery-ujs&lt;/code&gt;という名前でしたが、jQueryへの依存をなくすような形で書き換えられ、確かRails 5.1から標準に取り込まれました。&lt;/p&gt;
&lt;p&gt;jquery-ujsの頃は↓のような方法で自前ダイアログに変更できたのですが、rails-ujsになってからはこの方法は使えません。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://qiita.com/haazime/items/ddee6af64b98bb3799a0" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFtYXpvbmF3cy5jb20lMkYwJTJGMzg0NzIlMkZwcm9maWxlLWltYWdlcyUyRjE1MjM2ODAwMjg_aXhsaWI9cmItNC4wLjAmYXI9MSUzQTEmZml0PWNyb3AmbWFzaz1lbGxpcHNlJmJnPUZGRkZGRiZmbT1wbmczMiZzPTIyMzhhMzIxMTkwNmZmMTJiYWZhN2M2MmIyMjM2Zjll%26blend-x%3D120%26blend-y%3D467%26blend-w%3D82%26blend-h%3D82%26blend-mode%3Dnormal%26s%3D63c3f3ee81037cfc3d34df7632072e8e?ixlib=rb-4.0.0&amp;amp;w=1200&amp;amp;fm=jpg&amp;amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9bGlua190byUyMGRhdGElM0ElMjAlN0IlMjBjb25maXJtJTNBJTIwJTI3QXJlJTIweW91JTIwc3VyZSUzRiUyNyUyMCU3RCVFMyU4MiU5MiVFMyU4MiVCOSVFMyU4MiVBNCVFMyU4MyVCQyVFMyU4MyU4OCVFMyU4MSVBQiZ0eHQtYWxpZ249bGVmdCUyQ3RvcCZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTU2JnR4dC1wYWQ9MCZzPWNlYmU0MWFlMDc3OTNkZmQyOGFjYmEzNDY5ZDU4YmZj&amp;amp;mark-x=120&amp;amp;mark-y=112&amp;amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDBoYWF6aW1lJnR4dC1jb2xvcj0lMjMxRTIxMjEmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9MzYmdHh0LXBhZD0wJnM9YjgxNWRlNDk2OTM2MjM3NDA0MTlmNTM5N2MwZDRkODc&amp;amp;blend-x=242&amp;amp;blend-y=480&amp;amp;blend-w=838&amp;amp;blend-h=46&amp;amp;blend-fit=crop&amp;amp;blend-crop=left%2Cbottom&amp;amp;blend-mode=normal&amp;amp;s=f675832480c15d09c68c4d7857985d7d" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;link_to data: { confirm: &amp;#39;Are you sure?&amp;#39; }をスイートに - Qiita&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;スイート？ ブラウザ標準の確認ダイアログの代わりに、Sweet Alert2を使います。 事前準備 Sweet Alert2をインストールします。 rails-assets distをapp/assets/javascriptsに直接置く CDNをHTMLから読み込...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;qiita.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;rails-ujs&lt;/code&gt;を使用している場合はaタグのクリックイベントを単純に乗っ取るだけでは自前実装のダイアログに置き換えることはできません。また、&lt;code&gt;data-confirm&lt;/code&gt;以外にも&lt;code&gt;rails-ujs&lt;/code&gt;が色々やっている（たとえば&lt;code&gt;remote: true&lt;/code&gt;なリンクの処理など）ため、単純に乗っ取ってしまうと想定した機能が動かなくなることもあります。&lt;/p&gt;
&lt;p&gt;そういうわけで必要な箇所だけを正しく乗っ取ってあげる必要があります。幸いコード例を見つけたのでそちらを参考に書いてみましょう。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://medium.com/store2be-tech/how-to-use-sweetalert2-for-your-rails-5-1-rails-ujs-confirms-without-jquery-8a5b516b2a1" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://miro.medium.com/v2/resize:fit:1200/1*a9xwUKIuiNTGGNopAJiFKg.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;How to use SweetAlert2 for your Rails &amp;#43;5.1 (rails-ujs) confirms without jQuery&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;TL;DR see this demo project for the final solution.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://miro.medium.com/v2/5d8de952517e8160e40ef9841c781cdc14a5db313057fa3c3de41c6f5b494b19" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;medium.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;こちらの場合はsweet-alertというJSライブラリを使ってダイアログを表示しています。またujsの&lt;code&gt;data-confirm&lt;/code&gt;を上書きしないよう独自の&lt;code&gt;data-confirm-swal&lt;/code&gt;という属性を使うふうにかいていますが、&lt;code&gt;data-confirm&lt;/code&gt;自体を乗っ取ってしまっても問題なく動きます。&lt;/p&gt;
&lt;p&gt;まず、自前のイベントハンドラとクリックイベントへの紐づけの部分がこんな感じになります（元のコードの一部（&lt;code&gt;data-confirm-swal&lt;/code&gt;の変更、対象とする要素のセレクタ&lt;code&gt;input\[data-confirm\]&lt;/code&gt;のあたり）を修正）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;handleConfirm&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;element&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;allowAction&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Rails&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;stopEverything&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;element&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;allowAction&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;element&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;element&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getAttribute&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;data-confirm&amp;#39;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;showConfirmationDialog&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;element&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; document.&lt;span style="color:#a6e22e"&gt;addEventListener&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;rails:attachBindings&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Rails&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;delegate&lt;/span&gt;(document, &lt;span style="color:#e6db74"&gt;&amp;#39;a[data-confirm], input[data-confirm], button[data-confirm]&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;click&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;handleConfirm&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;}).&lt;span style="color:#a6e22e"&gt;call&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;:delete&lt;/code&gt;メソッドなリンクが正しく動くようにとか、&lt;code&gt;Rails.start&lt;/code&gt;後にこちらのやりたい処理を差し込めるように、といった工夫のため&lt;code&gt;rails:attachbindings&lt;/code&gt;のリスナーでイベントハンドラの登録を行います。&lt;/p&gt;
&lt;p&gt;クリック後、&lt;code&gt;allowAction&lt;/code&gt;でconfirmを出すべき属性があるかないかを判断し、出すべきであれば&lt;code&gt;showConfirmationDialog&lt;/code&gt;を呼び出すという流れです。&lt;/p&gt;
&lt;p&gt;その後は自分で出したいダイアログを表示するわけですが、1つポイントがあります。元記事（一部&lt;code&gt;data-confirm-swal&lt;/code&gt;を修正）の例を見てみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Display the confirmation dialog
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;showConfirmationDialog&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;element&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;message&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;element&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getAttribute&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;data-confirm&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;text&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;element&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getAttribute&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;data-text&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;swal&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;message&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Are you sure?&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;text&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;text&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;warning&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;showCancelButton&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;confirmButtonText&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Yes&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cancelButtonText&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Cancel&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }).&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;) { &lt;span style="color:#75715e"&gt;// &amp;lt;= OKを押した際のコールバック
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;confirmed&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;element&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;confirmed&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;element&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// User clicked confirm button
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;element&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;removeAttribute&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;data-confirm&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;element&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;JSライブラリによってダイアログを表示し、OKが押された場合には&lt;code&gt;data-confirm&lt;/code&gt;を消した上でJSからクリックします。すると今度は確認ダイアログなしでクリックされたことになり、元々想定していた通りのリクエストが送られる、というわけです。&lt;/p&gt;
&lt;p&gt;ダイアログの実装自体はなんでもよくて、例えば&lt;a href="https://github.com/craftpip/jquery-confirm"&gt;jquery-confirm&lt;/a&gt;のようなものでもOKです。&lt;/p&gt;
&lt;p&gt;元記事への補足として、&lt;code&gt;remote: true&lt;/code&gt;なリクエストの場合、画面全体が更新されないことが多いかと思います。場合によっては&lt;code&gt;data-confirm&lt;/code&gt;を削除した状態のリンクがそのまま残っている場合もあり得ます。&lt;/p&gt;
&lt;p&gt;この場合、該当のリンクをクリックすると今度は確認なしでリクエストを投げてしまいますのであまりよくありません。ということで元のダイアログの部分のコードを修正し、たとえばダイアログが閉じたら&lt;code&gt;data-confirm&lt;/code&gt;を戻しておくなどの工夫が必要です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;element&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setAttribute&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;data-confirm&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;message&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Xcodeでのページ上下にカーソルを追従させる</title><link>https://blog.piyo.tech/posts/2018-06-25-xcode-page-up-down/</link><pubDate>Mon, 25 Jun 2018 06:31:31 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-25-xcode-page-up-down/</guid><description>&lt;p&gt;Xcodeのエディタ部分でページアップ、ページダウンするとスクロールはしてくれるのですが、カーソルがついてきません。&lt;/p&gt;
&lt;p&gt;page-upやpage-downは別のツールでキーボードショートカットを割り当てることで実現していますので、ポジションを大きく動かさずにエディタを大きくスクロールして、そのあとは&lt;code&gt;ctrl+n&lt;/code&gt;や&lt;code&gt;ctrl+p&lt;/code&gt;で上下にカーソルを移動をすれば目標の場所にすばやく移動できます。&lt;/p&gt;
&lt;p&gt;しかしXcodeではカーソルは動かないままスクロールしてしまうので、page-downしてさらに下に数行動くぐらいのつもりでキー操作をすると、元々の箇所から数行下にスクロールが合う、つまり下にスクロールしたあと上にスクロールすることになります。&lt;/p&gt;
&lt;p&gt;これが不便で仕方がなかったんですが、キー設定で変更できるようでした。&lt;/p&gt;
&lt;p&gt;まずXcodeでPreferenceを開きます。&lt;code&gt;コマンド&lt;/code&gt; + &lt;code&gt;,&lt;/code&gt;が楽です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/gjZkpufAnaY2IaJ7uTWdSwHNClzcG2kSw25Hc7XLO-0qopD2DL2McPdKhSk8YIvOvVFxvxpgly0L02NVtLiwKZcumVrcBvzYUaKAktS-cluSrKp9H5avdDiOFgZVYfGbt8U1ZGrdHxXe6bCAvRJ0zqInvTp04TSVI0fA0j4-giSNiGKKT5R672icomYTrY_Ix-09k8QOS5myTEBiDeSgNSi7bVPDDcWiJTR9BtNTLV57Az_kmlhTMIvI5O65KlVMwjhEiIR3_KYVuC0CrC2qK8jvsFWkoOOsGIcgQLdDC2by3IAjpYO_z2XZCpiYv1qShXzXxsrE5DwMY2XpQw6-iXtsHL3FAdSvPgHmMT9fGiqiEv65mPVOAXx3fg1OzeZ-LkNJPKqTtYfmB8IsLgM2eVMcuNshr6HAaBM9IgWxJN-3P3nGhgeSOjDoAJjp4Z2nOkyTxEtm23bNkNdw1_kidcHKGeUH3lbwTgYZ0BhU2qvreHT7AQfHfDbRy6MWVMtMAQqHxXxzWmOra8ipzgwWMilTmvdNd82_V7OM026w7eeRhGG4KloSzlFKTfmGX-tqqPDFE65DrvySZcat2EWT1M408hskgL8YINso-sdDDYvF5VqqQhJpdLvVyUCnbxUWMTmIB7NCsyq2yR-jWtx-CLZN2ZS9BIlq=w1266-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/gjZkpufAnaY2IaJ7uTWdSwHNClzcG2kSw25Hc7XLO-0qopD2DL2McPdKhSk8YIvOvVFxvxpgly0L02NVtLiwKZcumVrcBvzYUaKAktS-cluSrKp9H5avdDiOFgZVYfGbt8U1ZGrdHxXe6bCAvRJ0zqInvTp04TSVI0fA0j4-giSNiGKKT5R672icomYTrY_Ix-09k8QOS5myTEBiDeSgNSi7bVPDDcWiJTR9BtNTLV57Az_kmlhTMIvI5O65KlVMwjhEiIR3_KYVuC0CrC2qK8jvsFWkoOOsGIcgQLdDC2by3IAjpYO_z2XZCpiYv1qShXzXxsrE5DwMY2XpQw6-iXtsHL3FAdSvPgHmMT9fGiqiEv65mPVOAXx3fg1OzeZ-LkNJPKqTtYfmB8IsLgM2eVMcuNshr6HAaBM9IgWxJN-3P3nGhgeSOjDoAJjp4Z2nOkyTxEtm23bNkNdw1_kidcHKGeUH3lbwTgYZ0BhU2qvreHT7AQfHfDbRy6MWVMtMAQqHxXxzWmOra8ipzgwWMilTmvdNd82_V7OM026w7eeRhGG4KloSzlFKTfmGX-tqqPDFE65DrvySZcat2EWT1M408hskgL8YINso-sdDDYvF5VqqQhJpdLvVyUCnbxUWMTmIB7NCsyq2yR-jWtx-CLZN2ZS9BIlq=w1266-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そして、画面上部から「Key Bindings」を選び、検索ボックスに「page 」と入れます。最後にスペースを入れると「pages」というが除外されるのでより見つけやすくなります。&lt;/p&gt;
&lt;p&gt;さて絞り込まれた結果を見ると、下から2つが「Scroll Page Up/Down」、その上の2つが「Move Page Up/Down」となっています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/4cTBVSGf3a4lguWclM8kqKhw0mhWHDDEdXReTP7Br6bF-ZGnYNP5xgYv-r10_QtZcqMMCOTUbDdDwDjhZZWm9FRQwVPBqK5181aSPJgShv_eKe3fSzA9eHLuNsgypSN_HhZniwGgUpBZSCsyfX1mUwup2RksovmZXL_SjZqdaBXWA4Z8Cg7t210sZyZZCNNGObjNDF0G5tLOY5bqBGwlVXTxjy9cs3DymklKHNDZgSFvZlh-RLJVJqR6D1ONfLaYu5_Wk4baHcfqna__L-6eT43NbUKlpOl6MjHwgE54L7A_qwp0Lsy12KdOmugbm4ZPzPUwkksDKKndpM1evl0nCb86CWraW6XN3MeV7mJJ1lC2lNIMmj0o6_a71Aq_qisNU1ePzNG5E3qmh39IkJ20Hsc36NU5rQ9P8ViF1oeMxG-_ITy6v33zSuTuLLWx-Z028SiCjCgXtmyoIf3AkmUapyTaJ6OfDckNbxO5Cehfhka5zwTHH4Srm8L9swsjKzEz3pN07qY6U_DvjjjIG_fC30xLNOa9B7JSDsejxDmqrY6xNhbd3RRuGAexgZ4BeFKJN1Y4Do5DSRytEGjagD_GY8wTyYOa_CJQc3gVsBhEkbigDOWejH_AGlEKHM8V6CORU8QNj2YwxMXxZzalKzsaklnOfZ4e5Z8Z=w1266-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/4cTBVSGf3a4lguWclM8kqKhw0mhWHDDEdXReTP7Br6bF-ZGnYNP5xgYv-r10_QtZcqMMCOTUbDdDwDjhZZWm9FRQwVPBqK5181aSPJgShv_eKe3fSzA9eHLuNsgypSN_HhZniwGgUpBZSCsyfX1mUwup2RksovmZXL_SjZqdaBXWA4Z8Cg7t210sZyZZCNNGObjNDF0G5tLOY5bqBGwlVXTxjy9cs3DymklKHNDZgSFvZlh-RLJVJqR6D1ONfLaYu5_Wk4baHcfqna__L-6eT43NbUKlpOl6MjHwgE54L7A_qwp0Lsy12KdOmugbm4ZPzPUwkksDKKndpM1evl0nCb86CWraW6XN3MeV7mJJ1lC2lNIMmj0o6_a71Aq_qisNU1ePzNG5E3qmh39IkJ20Hsc36NU5rQ9P8ViF1oeMxG-_ITy6v33zSuTuLLWx-Z028SiCjCgXtmyoIf3AkmUapyTaJ6OfDckNbxO5Cehfhka5zwTHH4Srm8L9swsjKzEz3pN07qY6U_DvjjjIG_fC30xLNOa9B7JSDsejxDmqrY6xNhbd3RRuGAexgZ4BeFKJN1Y4Do5DSRytEGjagD_GY8wTyYOa_CJQc3gVsBhEkbigDOWejH_AGlEKHM8V6CORU8QNj2YwxMXxZzalKzsaklnOfZ4e5Z8Z=w1266-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;最終的には「Scroll」に割り当てられているpage-upやpage-downを「Move」に割り当てればOKです。&lt;/p&gt;
&lt;p&gt;まず「Scroll Page Up」（とDown）にカーソルを合わせてDeleteキーでキーの割り当てを削除します。続いて「Move Page Up」側を選択してキー割り当てが書かれている列のあたりをダブルクリックして「+」ボタンを押し、page-upキーをおして割り当てます。Doenも同様ですね。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/7f5d1UPkD9n5abk6Eh8TSScoYxecjTdd03X09AgBkhMyqyxbExG1dmtW__q8xHB1vuxCYFSpIt6y8XTF7IRDtes5flrLKzOuBNJygerjLFxhxmHhQURl-tGXs9H6ZCk6DH0HauDCojBMY1PVNhkjvyKRHDv46HsgrsnQg4IcWp1CtgDmEd4rSdYSZrhA7YHARiTrRma8rnZT2kcOTLefIevj26Wna8v7if0B0vjOn2UZYyV9_BLq-zLhgZ_-9D7sWjH-ly8L2Hjy5-h7SzeE0wZTCPmfjOUsYYzKnnTqZhXf2CNRC20XRaLUFHXsX5WTIbPkSwgPIgl_o7lCDvrdXLQAxl6aKtlNSdVwqkUlhRxU2WtaFwovuqwa7qkFi6ohWk3mHOStzVDvpXSTUqIKgQwDN_HsBt-PJmLP0uAdfqdq-m8N8btQ0gJ0l89mTmZWJfXdc7QSJdaWEvnJ_V7mih1U9lwjBgBOp4ZMCaAM-X4Zo4C_MKVSfomubEfl3uHX8pQ7dOWHeirpPwKS7gIbqHtmx7je4ZCgyXFFFyftpI00ZJR0xyCnxqekDHjR8OgR5vcVE1diKGlhgU7Pvf1ov0O4jPo8FtGOdYKEOm-9tuVYsRshf96b-jX0mA-ObKmGHBR4yOkqc3vTMLwLCjyYNV1oTp-GyK7z=w1266-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/7f5d1UPkD9n5abk6Eh8TSScoYxecjTdd03X09AgBkhMyqyxbExG1dmtW__q8xHB1vuxCYFSpIt6y8XTF7IRDtes5flrLKzOuBNJygerjLFxhxmHhQURl-tGXs9H6ZCk6DH0HauDCojBMY1PVNhkjvyKRHDv46HsgrsnQg4IcWp1CtgDmEd4rSdYSZrhA7YHARiTrRma8rnZT2kcOTLefIevj26Wna8v7if0B0vjOn2UZYyV9_BLq-zLhgZ_-9D7sWjH-ly8L2Hjy5-h7SzeE0wZTCPmfjOUsYYzKnnTqZhXf2CNRC20XRaLUFHXsX5WTIbPkSwgPIgl_o7lCDvrdXLQAxl6aKtlNSdVwqkUlhRxU2WtaFwovuqwa7qkFi6ohWk3mHOStzVDvpXSTUqIKgQwDN_HsBt-PJmLP0uAdfqdq-m8N8btQ0gJ0l89mTmZWJfXdc7QSJdaWEvnJ_V7mih1U9lwjBgBOp4ZMCaAM-X4Zo4C_MKVSfomubEfl3uHX8pQ7dOWHeirpPwKS7gIbqHtmx7je4ZCgyXFFFyftpI00ZJR0xyCnxqekDHjR8OgR5vcVE1diKGlhgU7Pvf1ov0O4jPo8FtGOdYKEOm-9tuVYsRshf96b-jX0mA-ObKmGHBR4yOkqc3vTMLwLCjyYNV1oTp-GyK7z=w1266-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これでページ移動時にカーソルが追従してくれるようになりました。&lt;/p&gt;</description></item><item><title>Macでマウスのポインター位置を目立たせるSimple Mouse Locator</title><link>https://blog.piyo.tech/posts/2018-06-24-mouse-locator/</link><pubDate>Sun, 24 Jun 2018 06:26:31 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-24-mouse-locator/</guid><description>&lt;p&gt;先日はマウスのポインタサイズを変更する方法を紹介しました。&lt;/p&gt;
&lt;p&gt;それとは別の理由でマウスポインタを目立たせたい場合があります。リモートのミーティングで画面共有をするとき、ビデオ会議ツールのウィンドウ内で画面を共有するため大抵は画面は小さくなります。その中で小さいマウスポインタを位置を把握する（＝どんな操作をしているかを相手が把握する）のはなかなか難しいです。&lt;/p&gt;
&lt;p&gt;同僚がこんなツールを使っていたので僕も使ってみました。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://itunes.apple.com/jp/app/simple-mouse-locator/id946676425?mt=12" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;itunes.apple.com →&lt;/span&gt;&lt;span&gt;https://itunes.apple.com/jp/app/simple-mouse-locator/id946676425?mt=12&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ほぼ全員がリモートワークをしているメンバーなので各々便利ツールを知ってるものですね。&lt;/p&gt;
&lt;p&gt;使い方といってもマウスの周りにロケーターが出るだけなので、重要なのはその設定です。&lt;/p&gt;
&lt;h2 id="ロケーターの設定"&gt;ロケーターの設定&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/FN67lbtzlyufYOSYY8C82NBF0yo5wpoAHHHC50oMSTFmR-lZl3kRh_6keLB5CElxSxJfefCS9Pb3PgRURPsjb0qiv5C1Yg947z5t3Kof343Umh2Y-8X2nNbX0xx5WlWcb_vtYc9AVgSDv2xpxd1nKsOrKttY9dHhrYnfMmTXFtm0CHsjrro3Y6e1ZNDfPGzgQnTDtA1RlHQmxLxvsAFJGEgj9KA1pLOMLghT7BqbXetlKi6wl6VxIgPC6EoUWd49gUmQP81fVzPgbNTKUp1kTf2Z6fw1gjcwX_E8HyMnjTlOpWNPK-uXHaEJ-mfZFzN_pm3h3glEJT2eUwhabujU8Bv6KGx0BoWay7ncrz192GcIoLZ8KKSJZg7XSwJinuvUQjRBSsOtcCaI5DAGFNfx69VOulydA3BWnd5hbzV9IdKWU0iCI1ZnP3nt8zbjWsmTCau0gfH63n-EQ7JStUSNCPRRXw31cc6QzPwnHHlyBfaOgmawqTxV2r5Sb37s8MiAVZedVwgZGu9jYaMjxMtemolf9ey6CiOl7f07qhtZ_qqRkPvi8jZJFcdp71YmzvP0L_3zoHuJw9kbElAGsb49tIx2dIolUhKnSCRx_qbypQNAD8howjaZMnzyjnUoeZDnB540rEFTI8SWKfvhdgewTR7POcz_zRPm=w504-h489-no"&gt;&lt;img src="https://lh3.googleusercontent.com/FN67lbtzlyufYOSYY8C82NBF0yo5wpoAHHHC50oMSTFmR-lZl3kRh_6keLB5CElxSxJfefCS9Pb3PgRURPsjb0qiv5C1Yg947z5t3Kof343Umh2Y-8X2nNbX0xx5WlWcb_vtYc9AVgSDv2xpxd1nKsOrKttY9dHhrYnfMmTXFtm0CHsjrro3Y6e1ZNDfPGzgQnTDtA1RlHQmxLxvsAFJGEgj9KA1pLOMLghT7BqbXetlKi6wl6VxIgPC6EoUWd49gUmQP81fVzPgbNTKUp1kTf2Z6fw1gjcwX_E8HyMnjTlOpWNPK-uXHaEJ-mfZFzN_pm3h3glEJT2eUwhabujU8Bv6KGx0BoWay7ncrz192GcIoLZ8KKSJZg7XSwJinuvUQjRBSsOtcCaI5DAGFNfx69VOulydA3BWnd5hbzV9IdKWU0iCI1ZnP3nt8zbjWsmTCau0gfH63n-EQ7JStUSNCPRRXw31cc6QzPwnHHlyBfaOgmawqTxV2r5Sb37s8MiAVZedVwgZGu9jYaMjxMtemolf9ey6CiOl7f07qhtZ_qqRkPvi8jZJFcdp71YmzvP0L_3zoHuJw9kbElAGsb49tIx2dIolUhKnSCRx_qbypQNAD8howjaZMnzyjnUoeZDnB540rEFTI8SWKfvhdgewTR7POcz_zRPm=w504-h489-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;一番上のスライダーで大きさやリングの線の太さを変えられます。&lt;/p&gt;
&lt;p&gt;真ん中あたり、&lt;code&gt;Animated Ring&lt;/code&gt;と&lt;code&gt;Static Ring&lt;/code&gt;は片方を選ぶ形の設定項目で、ロケーターの見え方を決定します。&lt;/p&gt;
&lt;p&gt;Animatedにするとロケータが現れたあとしぼむようなアニメーションをしながら消えます。一時的に場所を示したいという人が使えばOK。&lt;/p&gt;
&lt;p&gt;それに対してStaticの方は一定時間表示されたあとフェードアウトするというものです。Display Timeのスライダーを一番左に動かすと常に表示されるようになります。後述するホットキーなどで自分で切り替えたいような人にはこれが良いです。&lt;/p&gt;
&lt;h2 id="ロケーターの有効化"&gt;ロケーターの有効化&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/_I1s0Jy7Hg5rQRFQArtKjQWPdRvOyXyXFGfB4wjpUnEw333NOWO0DLgdF1GAAgvgsB55zVJV2n2oW_ftTkgNmzSZoKhOlJNS7YFxEZef-kuR5SRrPutkXr3Se9xyvMQpaggO6J3vLczcpR_WolKAevMvwn7ZnVN3lPgZp6WfNqa--t2rwr_H5Tga7B5yyb7LDOa-L9FmlUGYDDOk7kwAFDH0f0Ws1K8unKDfwd7Z71R3Duh-vJXA6E6qP_aV2GdqCLFsyTWl1gqAIE66e8Rb1d3AmlWWGh5Ku-dgHrbXUD0POw_OjQzGX2PaEmIdXot9FgJ0-QAk3pbwFIBvdxEgcest_gE2Yg1Q-Q3rzN1pXszgrCmRgWW77MfbfKSR6hsX4KSEIsDlH1n6FRAsTLjvlV0v1DeZpl7G5Z6QT4bvPpygwHoNtvoY1Qzd2ku3oAYPTttEbY-lZqs-RGKhu8tpptMBmYahfeD4WBt4efgtOadlpikHgnSuy7Yn3XnL0qGRgdE_j8Lb3pM-4ZjEOocuElPn6OpnFs0jNJ8EKPSfaCNMFoi9jr5As7iajqk3MwXdzdpuJFdzI7QhdMqJ4KzqUu2jqAr978P2vgi8sVr6x9KIZNmlIqJSy8FEeDe1GEGapnZsLMa7SLeCEBKBG3cMtjbAYw3ak4-W=w504-h519-no"&gt;&lt;img src="https://lh3.googleusercontent.com/_I1s0Jy7Hg5rQRFQArtKjQWPdRvOyXyXFGfB4wjpUnEw333NOWO0DLgdF1GAAgvgsB55zVJV2n2oW_ftTkgNmzSZoKhOlJNS7YFxEZef-kuR5SRrPutkXr3Se9xyvMQpaggO6J3vLczcpR_WolKAevMvwn7ZnVN3lPgZp6WfNqa--t2rwr_H5Tga7B5yyb7LDOa-L9FmlUGYDDOk7kwAFDH0f0Ws1K8unKDfwd7Z71R3Duh-vJXA6E6qP_aV2GdqCLFsyTWl1gqAIE66e8Rb1d3AmlWWGh5Ku-dgHrbXUD0POw_OjQzGX2PaEmIdXot9FgJ0-QAk3pbwFIBvdxEgcest_gE2Yg1Q-Q3rzN1pXszgrCmRgWW77MfbfKSR6hsX4KSEIsDlH1n6FRAsTLjvlV0v1DeZpl7G5Z6QT4bvPpygwHoNtvoY1Qzd2ku3oAYPTttEbY-lZqs-RGKhu8tpptMBmYahfeD4WBt4efgtOadlpikHgnSuy7Yn3XnL0qGRgdE_j8Lb3pM-4ZjEOocuElPn6OpnFs0jNJ8EKPSfaCNMFoi9jr5As7iajqk3MwXdzdpuJFdzI7QhdMqJ4KzqUu2jqAr978P2vgi8sVr6x9KIZNmlIqJSy8FEeDe1GEGapnZsLMa7SLeCEBKBG3cMtjbAYw3ak4-W=w504-h519-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;3通りの方法が提供されています。&lt;/p&gt;
&lt;p&gt;1つ目がホットキー、これは設定した組み合わせのキーを同時に押すことでロケーターが有効（表示中は無効）になるというものです。&lt;/p&gt;
&lt;p&gt;2番目のグループはModiferキーで有効化する方法に関する設定で、僕はこれを使ってます。↑のキャプチャの設定だと、ShiftキーをDouble（つまり2回）押したときに有効になってくれます。&lt;/p&gt;
&lt;p&gt;3番目はマウスを動かして有効化する方法。指定した方向に指定した回数振るように動かす（waveさせる）と起動するというものです。これは誤爆しそうなので無効化しました。&lt;/p&gt;</description></item><item><title>Macでマウスポインターを大きくする</title><link>https://blog.piyo.tech/posts/2018-06-23-mouse-pointer-size/</link><pubDate>Sat, 23 Jun 2018 06:26:08 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-23-mouse-pointer-size/</guid><description>&lt;p&gt;ついにマウスポインタが見づらくなってきたので大きくしました。Macの場合は設定から簡単に大きくできます。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://support.apple.com/kb/PH25507?viewlocale=ja_JP&amp;amp;locale=ja_JP" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;support.apple.com →&lt;/span&gt;&lt;span&gt;https://support.apple.com/kb/PH25507?viewlocale=ja_JP&amp;amp;locale=ja_JP&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;アップルメニュー＞「システム環境設定」と選択し、「アクセシビリティ」をクリックします。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;「ディスプレイ」をクリックし、「カーソルのサイズ」スライダを右にドラッグして、サイズを大きくします。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;システム環境設定を開いて、アクセシビリティを開き、&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/DV4Dl7ynPCwkMjXjvsAZ9WBSCJNv0G4CEE5GkgEtGuZKKAC45J4kxp1nXrb1GctUkqgOdicdHi9i8ZroX2ElmHmJVq4bPJS9T7Z5JF3jc-Fl1UQl6oL9i5BkTxWufI1_-hekmlYub-zfU718ptDeLDfBqdCPFFsxRtgqKAV7_PhcyccgZEgJLXx50lDGpb4BRUJ9MKpcgfcBx7-FSQnv6wtrNC9hjjfwHNP8MAonaZt4Z5ybT6rtLjgFfg2ukNOToyUHYhH15gm4l6ePy9CMUIJxksXOXjzx8qNAbBTz60n1dKRurdqpV3Ica4J4mP9tyuD5rAf0WZQRTeRUNRTaWa0FuHiJR0AG2DQXtgZkM22weDgUlxM0rjsQAYKJxJXTqXjJ0we5l08OOTjFuPzrktS73DT1qNj1ULasM5JIKs7bCc3MSBHDMIQmCUDpPIOawpeiKagNkjHZg4kgXuLZa84jqfgmY9svVcJynClI1_bvj6UKuI5ivOMphSCjeDAMGpIBlkEgysEOgKj2hx5a9ToZUS6MZ3qnm2sHiyz34teFlxPBtVV76dXIGRXWmzdkLkQuXHYg2CKWAsaw-he025_9ZPS9Cc1w8TGOh9uaERwi3eb38bRm4mGh_SkfftWfmZjt0PDJZnqpqmhvBbEFOVzM3btKaLqK=w780-h710-no"&gt;&lt;img src="https://lh3.googleusercontent.com/DV4Dl7ynPCwkMjXjvsAZ9WBSCJNv0G4CEE5GkgEtGuZKKAC45J4kxp1nXrb1GctUkqgOdicdHi9i8ZroX2ElmHmJVq4bPJS9T7Z5JF3jc-Fl1UQl6oL9i5BkTxWufI1_-hekmlYub-zfU718ptDeLDfBqdCPFFsxRtgqKAV7_PhcyccgZEgJLXx50lDGpb4BRUJ9MKpcgfcBx7-FSQnv6wtrNC9hjjfwHNP8MAonaZt4Z5ybT6rtLjgFfg2ukNOToyUHYhH15gm4l6ePy9CMUIJxksXOXjzx8qNAbBTz60n1dKRurdqpV3Ica4J4mP9tyuD5rAf0WZQRTeRUNRTaWa0FuHiJR0AG2DQXtgZkM22weDgUlxM0rjsQAYKJxJXTqXjJ0we5l08OOTjFuPzrktS73DT1qNj1ULasM5JIKs7bCc3MSBHDMIQmCUDpPIOawpeiKagNkjHZg4kgXuLZa84jqfgmY9svVcJynClI1_bvj6UKuI5ivOMphSCjeDAMGpIBlkEgysEOgKj2hx5a9ToZUS6MZ3qnm2sHiyz34teFlxPBtVV76dXIGRXWmzdkLkQuXHYg2CKWAsaw-he025_9ZPS9Cc1w8TGOh9uaERwi3eb38bRm4mGh_SkfftWfmZjt0PDJZnqpqmhvBbEFOVzM3btKaLqK=w780-h710-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;左側から「ディスプレイ」を選んで、カーソルのサイズのスライダーを好みの大きさまで変えてあげればOK。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/9q_yXEvx2maW5pl_Um4KYBXieGynkxFt38aKDCGTOpmEDSUC2En0Zm5m7dzE3wsYb7EOUVXfJf5R38IwX89RUV1kO3A9uGcIRBZqnBPXVg9igvOi-5G7Ev3OqMk3XCjvgmqdo5Uxn09AnQrh64RXHAwGupif6xHwX17eHRuAFfCQkQ_ZQu4z7TdaTP3KIH_60l2Qa67qh90ZiRfbh5p2xFSMQewi1ztJsTHHXeB9LjW6QZ5lvHOqqzY2Un9MytjLRXueeb93DLdDJa7159i79B1ZUJHISkjfva6wIguJ4736hhrPG_oCt2zbW21uabJuugFqzgkqT7FazOlEy1KJ0zWWx4Ok0BQJRRNVCnZqmDykR6LYl0quYL8sWmUgYW7HxZkQwMs05kJJkDsDdEEZmKUsW7iqJ-21yjhf8ch8xLgvVrhV-yGEsNbdl3plgtxxJ1yWLh_HgUNYn4QWRvr6AtWo2QUr7B7bTHzuVYvD3d2EmhfPA2vHShbIqtOuWKErBd8VWr3qA5f9onh_BOenHtqT_HlXfsW1ow9FlZUTZ9ipvk9qxLAli90nNm52ICQzlQbZop5dRT7Hwad7Y2uUQcJLUuoUF2Xiji3Ad20v2e34zpskaOffJtcoEyD2wSEVnoMtk8yKdWYQmc5-rnIgW80OaZSG2732=w780-h588-no"&gt;&lt;img src="https://lh3.googleusercontent.com/9q_yXEvx2maW5pl_Um4KYBXieGynkxFt38aKDCGTOpmEDSUC2En0Zm5m7dzE3wsYb7EOUVXfJf5R38IwX89RUV1kO3A9uGcIRBZqnBPXVg9igvOi-5G7Ev3OqMk3XCjvgmqdo5Uxn09AnQrh64RXHAwGupif6xHwX17eHRuAFfCQkQ_ZQu4z7TdaTP3KIH_60l2Qa67qh90ZiRfbh5p2xFSMQewi1ztJsTHHXeB9LjW6QZ5lvHOqqzY2Un9MytjLRXueeb93DLdDJa7159i79B1ZUJHISkjfva6wIguJ4736hhrPG_oCt2zbW21uabJuugFqzgkqT7FazOlEy1KJ0zWWx4Ok0BQJRRNVCnZqmDykR6LYl0quYL8sWmUgYW7HxZkQwMs05kJJkDsDdEEZmKUsW7iqJ-21yjhf8ch8xLgvVrhV-yGEsNbdl3plgtxxJ1yWLh_HgUNYn4QWRvr6AtWo2QUr7B7bTHzuVYvD3d2EmhfPA2vHShbIqtOuWKErBd8VWr3qA5f9onh_BOenHtqT_HlXfsW1ow9FlZUTZ9ipvk9qxLAli90nNm52ICQzlQbZop5dRT7Hwad7Y2uUQcJLUuoUF2Xiji3Ad20v2e34zpskaOffJtcoEyD2wSEVnoMtk8yKdWYQmc5-rnIgW80OaZSG2732=w780-h588-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;マウスの設定ではなく、ディスプレイの設定なんですねー。&lt;/p&gt;</description></item><item><title>Gitでファイルがいつ削除されたかを特定する</title><link>https://blog.piyo.tech/posts/2018-06-22-git-log-for-file/</link><pubDate>Fri, 22 Jun 2018 06:12:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-22-git-log-for-file/</guid><description>&lt;p&gt;前に触ったときにはあったはずのファイルが消えてるけどいつ消えたかわからん、という場合に使えるコマンドがありました。&lt;/p&gt;
&lt;p&gt;↓のように&lt;code&gt;git log&lt;/code&gt;にファイルパスを渡すとそのファイルが変更されたパスのログを出せます。ファイルがすでに削除されていても使えるコマンドなので、ログのうち、最後のコミットで削除されたということを特定できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% git log -- &lt;span style="color:#f92672"&gt;[&lt;/span&gt;file path&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例えば、こんな風に使えます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% git log -- lib/main.rb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最後の1コミットだけみたいのであれば、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% git log -n &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; -- &lt;span style="color:#f92672"&gt;[&lt;/span&gt;file path&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とすればOKです。細かいけど、知っとくといざというとき便利。&lt;/p&gt;</description></item><item><title>キーボード用にリストレストを買った</title><link>https://blog.piyo.tech/posts/2018-06-21-wrist-rest/</link><pubDate>Thu, 21 Jun 2018 06:22:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-21-wrist-rest/</guid><description>&lt;p&gt;リストレストがぼろぼろになって捨てて以来買うのを忘れてました。突如思い出して、ないと落ち着かなくなってしまったので色々調べて購入しました。キーボードとトラックボールの両方をカバーできるサイズのものにしました。&lt;/p&gt;
&lt;p&gt;それがこちらです。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B073F3XXXX/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/614RsVr9P7L._AC_SL1280_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;サンワダイレクト リストレスト キーボード用 フルキーボード用 ブラック 200-TOK009&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;フルキーボード用、つまりテンキー有りのキーボードのサイズに合うものです。僕のキーボードはMac用のテンキー無しタイプなので、ちょうどテンキー部分にトラックボールを置けて良い感じです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/kOLZkggqJcrzO-8d9KqxFS7EmoOObjD9Nm7qMpGwrkBTP4WNHJOPx8pSVDQohzekABHgMFZOlIkdvyNwsSvF9JHT1hWYNzbKnAIMdPu3TsN0v09rSpjLIyzHE3gAqeNiKan1FXKC7DJz89q0A5LjEJMBSHXLapgXM80bCYB59vVB_mLOosLVMvn5fyRML6ClFlMD7x7abnq-r4YD3EaiMr8ClOe7JACef1HEZ-sJKcYlqhUnG3-SjyMXPHpzjLCgdXltclCpIz2EcfkOnUgnp1IgPAx7D6WuEIhUBaBvtws07WZ_uVpsHFBnwzMPNh42uodgETRTgRazqY-mBclDvGuz5l9c8P9MiOxnlhs41nupAYGuK8LHButFW2GvTef6RTVOxt5DXtDHsiv6dcZl_RHwyjL8f3XzW5vy-yubUbmjBQs2UmyJtMiVtj0DHQcuGY55ZEOfy5Rs3FB_1xtii210lAdbg7VK9UcoU7RTaPZRIrfLPbu3k8PY9EGPa4ETPzJWm0NCo98N9cchEc3twUR7rsaBNDhi22T5hWsUIhXHAivclvilX0TqHaBWae13lUBHP9B2JvoVWCF_2luaeSxpEOkrqXnb9-kZxsWYXUYlNN0CMPXsaHUfwh6mVEJam9lRkFMmZT588crpYcKnJKtyhZXSRfaEYg=s357-no"&gt;&lt;img src="https://lh3.googleusercontent.com/kOLZkggqJcrzO-8d9KqxFS7EmoOObjD9Nm7qMpGwrkBTP4WNHJOPx8pSVDQohzekABHgMFZOlIkdvyNwsSvF9JHT1hWYNzbKnAIMdPu3TsN0v09rSpjLIyzHE3gAqeNiKan1FXKC7DJz89q0A5LjEJMBSHXLapgXM80bCYB59vVB_mLOosLVMvn5fyRML6ClFlMD7x7abnq-r4YD3EaiMr8ClOe7JACef1HEZ-sJKcYlqhUnG3-SjyMXPHpzjLCgdXltclCpIz2EcfkOnUgnp1IgPAx7D6WuEIhUBaBvtws07WZ_uVpsHFBnwzMPNh42uodgETRTgRazqY-mBclDvGuz5l9c8P9MiOxnlhs41nupAYGuK8LHButFW2GvTef6RTVOxt5DXtDHsiv6dcZl_RHwyjL8f3XzW5vy-yubUbmjBQs2UmyJtMiVtj0DHQcuGY55ZEOfy5Rs3FB_1xtii210lAdbg7VK9UcoU7RTaPZRIrfLPbu3k8PY9EGPa4ETPzJWm0NCo98N9cchEc3twUR7rsaBNDhi22T5hWsUIhXHAivclvilX0TqHaBWae13lUBHP9B2JvoVWCF_2luaeSxpEOkrqXnb9-kZxsWYXUYlNN0CMPXsaHUfwh6mVEJam9lRkFMmZT588crpYcKnJKtyhZXSRfaEYg=s357-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;しかし、思わぬ欠点が…！&lt;/p&gt;
&lt;p&gt;よく考えたら当たり前なんですが、Appleのキーボードがかなり薄型であるため、リストレストに手首を置いた状態だと手元に近い一番手前や二番めの列が非常に押しづらいというか、ほぼ押せません。&lt;/p&gt;
&lt;p&gt;横から見るとこんな感じです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/7KEjNsQHzGHVsMRj4dD-rwQbzwKwF1YXPkbNwa67KFIz5SPGmrkAI9dBRPtpfY74F-s3Xe9NGJ6LWdUTL6ecJ7M6l7Jo-1z1asIEd59UJnGSjonb7eI7FtjSL-zHvaXJlt8rKHhXeaHCNO85j_6WCj4qH3ip2WLUbczpt8VpvUOAIX8DWp6Tt58rdIUGP2uZ_gfe_gAINlyTaKD0yj0VPkUIJ-Q5VDm9LWadniAXUeMwwFDU2YH31ITwu1j_R_74-0KHe2ZVLEuXDsuAn0u9pWGR8XgtggDw5LNxzuRMsp6caAVCGre4RjsWM45bCK35f_V91BuJ2xCqMUeo0QCkgqu6o1tHtjEwXPb0IL1oKvhSd7bI6fR5UO8cU5lVAdJDmLUn2obBsj505jTfedaxHUvbg56P43n8wx_khH5BDr9tpHBBgskIjzk8J6q7B-5c5rmqHBFF9k5yf68zfTC4mF3uQsRUz4Y7IJswE15943nMKiA7L4ePBK2_aPywFwuFPdaCB05chfuMDZNNtfIJrqRJudj_-oEpaG8lrHFIRkgZQuTijqMJfNQ3F--CJZu3lJSTYFkPac2cRXKKrQ_BP3ziNcx9vPGtxzPaJvKxAYBxjjiAKz4Z72UOKny9tY6IvMpKA1KQHfL8h4Lzb9_38pUX1yxSV2voDA=w907-h650-no"&gt;&lt;img src="https://lh3.googleusercontent.com/7KEjNsQHzGHVsMRj4dD-rwQbzwKwF1YXPkbNwa67KFIz5SPGmrkAI9dBRPtpfY74F-s3Xe9NGJ6LWdUTL6ecJ7M6l7Jo-1z1asIEd59UJnGSjonb7eI7FtjSL-zHvaXJlt8rKHhXeaHCNO85j_6WCj4qH3ip2WLUbczpt8VpvUOAIX8DWp6Tt58rdIUGP2uZ_gfe_gAINlyTaKD0yj0VPkUIJ-Q5VDm9LWadniAXUeMwwFDU2YH31ITwu1j_R_74-0KHe2ZVLEuXDsuAn0u9pWGR8XgtggDw5LNxzuRMsp6caAVCGre4RjsWM45bCK35f_V91BuJ2xCqMUeo0QCkgqu6o1tHtjEwXPb0IL1oKvhSd7bI6fR5UO8cU5lVAdJDmLUn2obBsj505jTfedaxHUvbg56P43n8wx_khH5BDr9tpHBBgskIjzk8J6q7B-5c5rmqHBFF9k5yf68zfTC4mF3uQsRUz4Y7IJswE15943nMKiA7L4ePBK2_aPywFwuFPdaCB05chfuMDZNNtfIJrqRJudj_-oEpaG8lrHFIRkgZQuTijqMJfNQ3F--CJZu3lJSTYFkPac2cRXKKrQ_BP3ziNcx9vPGtxzPaJvKxAYBxjjiAKz4Z72UOKny9tY6IvMpKA1KQHfL8h4Lzb9_38pUX1yxSV2voDA=w907-h650-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;仕方ないので底に1cm程度のマットを入れることにしました。こちらの腹筋ローラーを買ったときに一緒についてきた膝を置くようのマットです。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B00XZ2MAM6/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/513gKLmjrVL._AC_SL1000_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;Soomloom アブホイール エクササイズウィル スリムトレーナー 静音 腹筋ローラー エクササイズローラー 膝を保護するマット付き&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;横からみると程よい高さになっていることがわかります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/tBETH8wxJTLpZEG1rAl_NCMBrQ3QAiH_3tK_7hc77y_AXcVYWxgzJjFS7B77nL5aGH1Kf5D_91y0RNoRBgZWLkHO70jbtO88xxg7vXy5ty4PNEDEl-ZPhSCoCImMZO6lSsL8XabHKDQeLt6iGzs1PoD-8iJhtd80vSxiU6km1qF5ua2SMutchgR4m8duRCQhU6i4ocmVQlNVy_hpGDUjKiDrOWVzuTnvhL7Y35ZnojgHUipbkSwB9uP0cPPDtEba0H1y0YbkIlpdcQyaC3LMC6BocPs3ZIrLkBLNzyJXJOovIDs82NtS5yLaUdQmAhHZLLzjjvFQNcI0rmmMXQka2-Se7-C26lJE1F2LUIw4S8idAQ_POvN9l_zrN6FGo-Puda7RQzeQcIFIB075iOHTczAT7RXKEEImQbwVMMuz7O0ox2oRp2OIDZNIWxQU2qlf7T-k_KXoQGRQz-wVGs7iQ6nCtu8KyDhPofsTwlfzezEmVPq77fN6vgBzKQOZJa7koP90yS9N0CXXStiMhGNfD0QLn-S8JMulRq3EVEyEyBHI8QKlWjqV7vu9l4LrSeCl-ngpI81lTZhBUZGPGiamj7y77j_euNudA71Lzzb3syTu1AqceM50jvNBtsdXNNH3TcDy-MWa6WXriNlROJ5ScuKgeDBz-KQ4-A=w907-h647-no"&gt;&lt;img src="https://lh3.googleusercontent.com/tBETH8wxJTLpZEG1rAl_NCMBrQ3QAiH_3tK_7hc77y_AXcVYWxgzJjFS7B77nL5aGH1Kf5D_91y0RNoRBgZWLkHO70jbtO88xxg7vXy5ty4PNEDEl-ZPhSCoCImMZO6lSsL8XabHKDQeLt6iGzs1PoD-8iJhtd80vSxiU6km1qF5ua2SMutchgR4m8duRCQhU6i4ocmVQlNVy_hpGDUjKiDrOWVzuTnvhL7Y35ZnojgHUipbkSwB9uP0cPPDtEba0H1y0YbkIlpdcQyaC3LMC6BocPs3ZIrLkBLNzyJXJOovIDs82NtS5yLaUdQmAhHZLLzjjvFQNcI0rmmMXQka2-Se7-C26lJE1F2LUIw4S8idAQ_POvN9l_zrN6FGo-Puda7RQzeQcIFIB075iOHTczAT7RXKEEImQbwVMMuz7O0ox2oRp2OIDZNIWxQU2qlf7T-k_KXoQGRQz-wVGs7iQ6nCtu8KyDhPofsTwlfzezEmVPq77fN6vgBzKQOZJa7koP90yS9N0CXXStiMhGNfD0QLn-S8JMulRq3EVEyEyBHI8QKlWjqV7vu9l4LrSeCl-ngpI81lTZhBUZGPGiamj7y77j_euNudA71Lzzb3syTu1AqceM50jvNBtsdXNNH3TcDy-MWa6WXriNlROJ5ScuKgeDBz-KQ4-A=w907-h647-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;上から見るとだいぶダサいですが仕方ない。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/EY0CLE93LaOapYfvfySyOoVveSvl8d4Bydtx6cFdVsF7TkIU7Ft_gr5UCI_SfEcDPwfK17o4HYLFPStDfEGg3p9Q7TNFGMoDqvDjgJ1JBJmeO-MYm3jwac-6i_XsWDN_KCsvvUrkAgslYxtkvG35wfAoDUzNEy-N2twi1O9rA14ZZdjV6BTtyqzl9Xvh5vpliALuUNYC8mg3nZ_VK5WkbczKkXjgUrvqgcsr16QoWANZi9SiVenMlTSJHjeQ4bpMQ2Th6CHiGcaPDARQqBEAoGLT50bplQWrrMVZOQ2ukktn1L1oHQXiVigZE1ZOxmD9UtrrGyZBBG-3FlLgw3XglKVajlfRQRxt29qecE3Tr4EprCRld6OYL98H4vxOO3sBZhonB7D8D8kDKbG1x70E0CPIjxR4WKySwNp3aguRkworjDRC_-2Q7B0p2GmxegHg7npD8Ac91N95ZxG9fUpWn20B_KYsGsOXlJ-Grf2DM6ykA_VXxK9TW-ictAiNBZJZS3rS2nRlSfjWUJv8lhzAhWpFVu1Zsnxzy02UD8Ggw9rtve_ax1xeERhspLZ6Mv8vuBKEen-_O2jEdMDS57KSJW-p0R6ow1X1HLI_tZxP7G28s_-sRMkS0QGAa7RGpaHaAXZY5dJGmFl4bKPScv6NNLeDZjDEMM5q9Q=w907-h850-no"&gt;&lt;img src="https://lh3.googleusercontent.com/EY0CLE93LaOapYfvfySyOoVveSvl8d4Bydtx6cFdVsF7TkIU7Ft_gr5UCI_SfEcDPwfK17o4HYLFPStDfEGg3p9Q7TNFGMoDqvDjgJ1JBJmeO-MYm3jwac-6i_XsWDN_KCsvvUrkAgslYxtkvG35wfAoDUzNEy-N2twi1O9rA14ZZdjV6BTtyqzl9Xvh5vpliALuUNYC8mg3nZ_VK5WkbczKkXjgUrvqgcsr16QoWANZi9SiVenMlTSJHjeQ4bpMQ2Th6CHiGcaPDARQqBEAoGLT50bplQWrrMVZOQ2ukktn1L1oHQXiVigZE1ZOxmD9UtrrGyZBBG-3FlLgw3XglKVajlfRQRxt29qecE3Tr4EprCRld6OYL98H4vxOO3sBZhonB7D8D8kDKbG1x70E0CPIjxR4WKySwNp3aguRkworjDRC_-2Q7B0p2GmxegHg7npD8Ac91N95ZxG9fUpWn20B_KYsGsOXlJ-Grf2DM6ykA_VXxK9TW-ictAiNBZJZS3rS2nRlSfjWUJv8lhzAhWpFVu1Zsnxzy02UD8Ggw9rtve_ax1xeERhspLZ6Mv8vuBKEen-_O2jEdMDS57KSJW-p0R6ow1X1HLI_tZxP7G28s_-sRMkS0QGAa7RGpaHaAXZY5dJGmFl4bKPScv6NNLeDZjDEMM5q9Q=w907-h850-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;感じのリストレストの使い心地は、概ね良好です。ある程度反発力があるため沈む込みませんし、表面の素材が多少汗ばんでも張り付きにくそうな素材になっているのが良いです。&lt;/p&gt;</description></item><item><title>hugo new で生成されるファイルの初期内容を変更する</title><link>https://blog.piyo.tech/posts/2018-06-19-hugo-archetypes/</link><pubDate>Tue, 19 Jun 2018 08:49:07 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-19-hugo-archetypes/</guid><description>&lt;p&gt;ブログに記事を追加するときには、↓なコマンドで生成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% hugo new posts/2018-06-19-hugo-archetypes.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;するとこんな中身で生成されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;title: &amp;#34;2018 06 19 Hugo Archetypes&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;date: 2018-06-19T08:41:23+09:00
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;draft: true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ルートディレクトリのarchetypesの中に、このような元ファイルがあり、これをベースに生成されていることがわかります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;title: &amp;#34;{{ replace .Name &amp;#34;-&amp;#34; &amp;#34; &amp;#34; | title }}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;date: {{ .Date }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;draft: true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;カスタマイズできそうだと思いつつも、しばらくはデフォルトのままで使っていました。が、いよいよ面倒になってきました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;draft: true&lt;/code&gt;はほとんど使わないし、タイトルはどうせ書き換えるから空でいいし、&lt;code&gt;tags: []&lt;/code&gt;とか自前で使っている&lt;code&gt;ogimage&lt;/code&gt;とかを入れておきたいです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://gohugo.io/content-management/archetypes/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://gohugo.io/opengraph/gohugoio-card-base-1_hu_b6b2cbed518793fa.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Archetypes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;An archetype is a template for new content.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://gohugo.io/favicon-32x32.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;gohugo.io&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;↑こちらのURLにarchetypes（= templates used when creating new content.）について書かれています。&lt;/p&gt;
&lt;p&gt;記事の種類（置かれるパス）によって参照するファイルの優先順位が異なるよ、ということでした。僕の場合は原則postsのページしか作りませんので、&lt;code&gt;archetypes/default.md&lt;/code&gt;を更新するので十分かなと思いました。&lt;/p&gt;
&lt;p&gt;というわけで元ファイルを次のように変更しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;title:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;date: {{ .Date }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;tags: []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;ogimage:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドで、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% hugo new posts/2018-06-19-hugo-archetypes.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↓が生成されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;title:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;date: 2018-06-19T08:49:07+09:00
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;tags: []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;ogimage:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>SQLiteのデータベースを閲覧・操作できる「」DB Browser for SQLite」</title><link>https://blog.piyo.tech/posts/2018-06-18-db-browser-sqlite/</link><pubDate>Mon, 18 Jun 2018 06:53:17 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-18-db-browser-sqlite/</guid><description>&lt;p&gt;たまにSQLite使うときにやっぱりGUIアプリがあると便利なので、このGUIアプリを使っています。各OSで動きそうな雰囲気です。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://sqlitebrowser.org/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://img.shields.io/badge/docs-Wiki-blue.svg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;DB Browser for SQLite&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="http://sqlitebrowser.org/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;sqlitebrowser.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;データを一覧したり、レコードを追加したり、テーブル定義を変更したり、一通りのことができます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/EMw9_tXl_Z6AzXr-dxemdlmdqarvt1kj6n3bF2KIIsgyRCrpz3A1skYFjR1wA7GD_aOgUeX5yV2RowE8CDfgxD0M2yp1XFxK3wI7ZmM9wSEvAXTdKj8YAgiVIr9xsVgJPq7H3he6mDVP3sO_3aNIyYHvEqHosZCJAJ6-TvUkNT4wfi6AV41j3lePy1lFf6jcHN5aS0oLQ2dl_2WwhdBYrrUYEbnSubWCdXngaOtJKa-GVhP6X7o_i8f7nubOsiPqx-0lHjutmlxJQeXByMXSvPmylZUFVcMTb6drWezV10odxTtxtCWvbrxKIjfsTbc-tFv_sLOcLmFV4-dId-QWWwdgURef5J3Klob_59BCh2unKHLPKHNxswQoEb1sfF4WauWngDIx6W5tD-3kSFdDNU9gHRFaVFoaDGjPZdl5nFEidvMF1TH9bspfCHI2NtaothiTKHm3bwJVj5YMQcwdsPtbKHOzBwppts0VxaH6-BC3FESUsl9bo9xX8swH0MCbmuZn3sV90GdRbLyhcxMMRx90IAGp_YNZ8wHvtjRzc_wx01SD7kFqOWhPeB4zjq2A8gzO9S1mpmwV_m-tY0aPXsrs415K85Ze33nzuuEh4D_7wQvR_jcpwwXCdohQm-f2BGsHWsVOg_GeCq1DxU0OKEAf4x3vVcW-=w1256-h764-no"&gt;&lt;img src="https://lh3.googleusercontent.com/EMw9_tXl_Z6AzXr-dxemdlmdqarvt1kj6n3bF2KIIsgyRCrpz3A1skYFjR1wA7GD_aOgUeX5yV2RowE8CDfgxD0M2yp1XFxK3wI7ZmM9wSEvAXTdKj8YAgiVIr9xsVgJPq7H3he6mDVP3sO_3aNIyYHvEqHosZCJAJ6-TvUkNT4wfi6AV41j3lePy1lFf6jcHN5aS0oLQ2dl_2WwhdBYrrUYEbnSubWCdXngaOtJKa-GVhP6X7o_i8f7nubOsiPqx-0lHjutmlxJQeXByMXSvPmylZUFVcMTb6drWezV10odxTtxtCWvbrxKIjfsTbc-tFv_sLOcLmFV4-dId-QWWwdgURef5J3Klob_59BCh2unKHLPKHNxswQoEb1sfF4WauWngDIx6W5tD-3kSFdDNU9gHRFaVFoaDGjPZdl5nFEidvMF1TH9bspfCHI2NtaothiTKHm3bwJVj5YMQcwdsPtbKHOzBwppts0VxaH6-BC3FESUsl9bo9xX8swH0MCbmuZn3sV90GdRbLyhcxMMRx90IAGp_YNZ8wHvtjRzc_wx01SD7kFqOWhPeB4zjq2A8gzO9S1mpmwV_m-tY0aPXsrs415K85Ze33nzuuEh4D_7wQvR_jcpwwXCdohQm-f2BGsHWsVOg_GeCq1DxU0OKEAf4x3vVcW-=w1256-h764-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ただし、1個だけ注意が。&lt;/p&gt;
&lt;p&gt;このアプリから更新系の操作を実行した場合、即時反映はされません。↓の「Write Changes」を押さないと実際のDBは更新されないため、うっかり忘れてハマるってことになりかねません（実際はまった）。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/WTLzAr2tZDhrPvycQhwqWnzQ6J8H-rNTdM8rbKHlVA7uODlO-HBJEhfQ_KWzseUh2E4BhLtVfdrunArOtb8F0QaXNuAmYQscsiNHfa0EUR9k-dtdyzPId8UWidYF6holzOySxuKSlxuk-_IFISFIAB0Lh3hz0AX9EdWgUbX0-mVuVYpMjk4B319EL9hFNe2bW-VPa-bpy5vRWPU4gBBQZt-Eak9McvqDWRAj6O2ssP3PWFHCOR3tUvPByWf9MOhbMG_deonOcbrZLb-zjTKPUg6_3x6lUTsihThqI5SY0JoULXs_AIyjTPwJqvJjqwEEkk6ucSOEfaCg4FBqgGDETjRgim-QayixXfsc5iIWVMdHrTjfvHQOf4gTnHI9Z5a2ehQMyjXMuM5eqPsvI0cQj8DdgFBQLPMSwheYmQx3R5B1pgONhhtfxZVv2EoVIMITrRcwB_wzr4hqDC0-oqzVK4j6buijRtbxUizxUkowE-0GhMg5DwfoCjvSclBlAcbY86mGkty0ibXzwnGCdPMhz7uiBnkwRKVYKpSSM9A5aA0DEjiERwkuhG5XMnXW4MZZhHlrtcnPWfi8uMfOi6jXio8LudQIO1I0GMXdGyjo9Y9gg57VarUEfgPi7XkIVnptQkC1J8OjeB7Q6vhSfU7FqQFDLSnWsYRY=w618-h112-no"&gt;&lt;img src="https://lh3.googleusercontent.com/WTLzAr2tZDhrPvycQhwqWnzQ6J8H-rNTdM8rbKHlVA7uODlO-HBJEhfQ_KWzseUh2E4BhLtVfdrunArOtb8F0QaXNuAmYQscsiNHfa0EUR9k-dtdyzPId8UWidYF6holzOySxuKSlxuk-_IFISFIAB0Lh3hz0AX9EdWgUbX0-mVuVYpMjk4B319EL9hFNe2bW-VPa-bpy5vRWPU4gBBQZt-Eak9McvqDWRAj6O2ssP3PWFHCOR3tUvPByWf9MOhbMG_deonOcbrZLb-zjTKPUg6_3x6lUTsihThqI5SY0JoULXs_AIyjTPwJqvJjqwEEkk6ucSOEfaCg4FBqgGDETjRgim-QayixXfsc5iIWVMdHrTjfvHQOf4gTnHI9Z5a2ehQMyjXMuM5eqPsvI0cQj8DdgFBQLPMSwheYmQx3R5B1pgONhhtfxZVv2EoVIMITrRcwB_wzr4hqDC0-oqzVK4j6buijRtbxUizxUkowE-0GhMg5DwfoCjvSclBlAcbY86mGkty0ibXzwnGCdPMhz7uiBnkwRKVYKpSSM9A5aA0DEjiERwkuhG5XMnXW4MZZhHlrtcnPWfi8uMfOi6jXio8LudQIO1I0GMXdGyjo9Y9gg57VarUEfgPi7XkIVnptQkC1J8OjeB7Q6vhSfU7FqQFDLSnWsYRY=w618-h112-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;即時反映されて困ることもありそうなのでこのようになってるでしょうけど。&lt;/p&gt;</description></item><item><title>Railsでカタカナのバリデーション</title><link>https://blog.piyo.tech/posts/2018-06-17-katakana-validation-rails/</link><pubDate>Sun, 17 Jun 2018 06:59:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-17-katakana-validation-rails/</guid><description>&lt;p&gt;Railsでカタカナのバリデーションについて、忘れ易いのでメモ。&lt;/p&gt;
&lt;p&gt;↓みたいにやるとできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;validates &lt;span style="color:#e6db74"&gt;:kana_name&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;presence&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;, format: { &lt;span style="color:#e6db74"&gt;with&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;/\A[\p{katakana}\p{blank}ー－]+\z/&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;message&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;はカタカナで入力して下さい。&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;p{katakana}&lt;/code&gt;についての詳しいことは↓にまとまっています。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://qiita.com/ymrl/items/b34c5493c9383633330b" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFtYXpvbmF3cy5jb20lMkYwJTJGMjIzMzMlMkZwcm9maWxlLWltYWdlcyUyRjE0NzM2ODM1NTA_aXhsaWI9cmItNC4wLjAmYXI9MSUzQTEmZml0PWNyb3AmbWFzaz1lbGxpcHNlJmJnPUZGRkZGRiZmbT1wbmczMiZzPTRjMDYyNjM0YWI2YTU2Y2JjNjY0ODI4YmUyOTQ5OWU2%26blend-x%3D120%26blend-y%3D462%26blend-w%3D90%26blend-h%3D90%26blend-mode%3Dnormal%26mark64%3DaHR0cHM6Ly9xaWl0YS1vcmdhbml6YXRpb24taW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnMzLWFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkZxaWl0YS1vcmdhbml6YXRpb24taW1hZ2UlMkY2ZTJiYzBiNWJmZjA5ZWMxZmZiZmExOGVkMWNjZGMxN2IyYTAyY2MwJTJGb3JpZ2luYWwuanBnJTNGMTYyNDM0MjUwNz9peGxpYj1yYi00LjAuMCZ3PTQ0Jmg9NDQmZml0PWNyb3AmbWFzaz1jb3JuZXJzJmNvcm5lci1yYWRpdXM9OCZiZz1GRkZGRkYmYm9yZGVyPTIlMkNGRkZGRkYmZm09cG5nMzImcz04YWIwOTViNmQ0MzEwZjM1MWZjYmE2NDc0NmNmZmI3Ng%26mark-x%3D186%26mark-y%3D515%26mark-w%3D40%26mark-h%3D40%26s%3D4814ad6c833d2934e8c5d0ac07a96606?ixlib=rb-4.0.0&amp;amp;w=1200&amp;amp;fm=jpg&amp;amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9UnVieSVFMyU4MSVBRSVFNiVBRCVBMyVFOCVBNiU4RiVFOCVBMSVBOCVFNyU4RiVCRSVFMyU4MSVBRSUyRiU1QiU1Q3AlN0JrYXRha2FuYSU3RCU1RCUyRiUyMCVFMyU4MSVBMyVFMyU4MSVBNiVFMyU4MSVBQSVFMyU4MiU5MyVFMyU4MSVBQSVFMyU4MSVBRSZ0eHQtYWxpZ249bGVmdCUyQ3RvcCZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTU2JnR4dC1wYWQ9MCZzPWQyZGQ4M2IzZjdkZTIzODJlYzhlNjk0MzM4OTlkZWUw&amp;amp;mark-x=120&amp;amp;mark-y=112&amp;amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDB5bXJsJnR4dC1jb2xvcj0lMjMxRTIxMjEmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9MzYmdHh0LXBhZD0wJnM9NGEzNjg2OGM2ZGMzNDE4NGYxYTJkYzA5ZGUwMWVmNDI&amp;amp;blend-x=242&amp;amp;blend-y=454&amp;amp;blend-w=838&amp;amp;blend-h=46&amp;amp;blend-fit=crop&amp;amp;blend-crop=left%2Cbottom&amp;amp;blend-mode=normal&amp;amp;txt64=ZnJlZWU&amp;amp;txt-x=242&amp;amp;txt-y=539&amp;amp;txt-width=838&amp;amp;txt-clip=end%2Cellipsis&amp;amp;txt-color=%231E2121&amp;amp;txt-font=Hiragino%20Sans%20W6&amp;amp;txt-size=28&amp;amp;s=cc2802ce9d6ed565f9faafc7245a92ad" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Rubyの正規表現の/[\p{katakana}]/ ってなんなの - Qiita&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;会社の人が書いたRubyのコードの正規表現で /[\p{katakana}]*/みたいなのがでてきて、なんだこれって思ったので調べた。 へー &amp;#39;アイウエオ&amp;#39; =~ /\A[\p{katakana}]&amp;#43;\z/ #=&amp;amp;gt; 0 &amp;#39;あいうえお&amp;#39; =~ /\A[\p{katakana...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;qiita.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;許容する文字が足りなければ必要に応じてフォーマットに追加することで対応できそう。&lt;/p&gt;</description></item><item><title>Railsで電話番号のバリデーション</title><link>https://blog.piyo.tech/posts/2018-06-16-phone-number-validation/</link><pubDate>Sat, 16 Jun 2018 06:38:06 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-16-phone-number-validation/</guid><description>&lt;p&gt;電話番号を単に数字とハイフンの並びと見るだけであればまだいいのですが、真面目に扱おうとすると割と面倒です。&lt;/p&gt;
&lt;p&gt;幸い、Googleの&lt;code&gt;libphonenumber&lt;/code&gt;やそれをバリデーション用にラップした&lt;code&gt;telephone_number&lt;/code&gt;というgemがあるので、それらを活用すると簡単に扱えるはずです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/mobi/telephone_number" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/d01467637ba63a7e0b5b4edceca9bd16b7b69158d7cffd28e8a2a3a74f95461b/mobi/telephone_number" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - mobi/telephone_number: Phone number validation for Ruby&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Phone number validation for Ruby. Contribute to mobi/telephone_number development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;電話番号のバリデーションをそのうち実装することになりそうなので、使い方を調べてみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mobi/telephone_number#rails-validation"&gt;Rails Validation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ざっくり書くとこんな感じ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;validates &lt;span style="color:#e6db74"&gt;:phone&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;telephone_number&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;country&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:ja&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;types&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:fixed_line&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:mobile&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コードを見る限りでは&lt;code&gt;country&lt;/code&gt;の指定は必須、&lt;code&gt;types&lt;/code&gt;は指定しない場合は全タイプで判定するようですね。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mobi/telephone_number/blob/master/lib/active_model/telephone_number_validator.rb"&gt;https://github.com/mobi/telephone_number/blob/master/lib/active_model/telephone_number_validator.rb&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;マニュアルでの呼び出しの場合、&lt;code&gt;country&lt;/code&gt;は必須ではありません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;phone &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TelephoneNumber&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Number&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(number) &lt;span style="color:#75715e"&gt;# country =&amp;gt; nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;phone&lt;span style="color:#f92672"&gt;.&lt;/span&gt;valid?
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;その場合、validation時にどこの国の番号かを推測するために、国番号が先頭になるかどうかなどのマッチングを行います。きちんと判定するには国はアプリケーション側で渡すのが良さそうです。&lt;/p&gt;
&lt;p&gt;このライブラリを使ったRailsのデモサイトもあります。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="http://numberjack.io/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;numberjack.io →&lt;/span&gt;&lt;span&gt;http://numberjack.io/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;バリデーション結果やいろんな表記に変換した結果なんかを見ることができます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/zNLWhPg8PBnekAzSSz7Z7MKdFeIITSdLDk9710dMnpT5kI99BWbc5PbyPNClDn_kkTz9nvTy68PQMLEJrko599WD5cJNR5F06Cx0QGfbLShNqJLvqAe94RUKWW7LCz2Ck3-AX7hEqBijtxf4j1_H4RgnY7GRHGNLPBA6ZCxGal2FUFgw9fmj7Ot75TJGwMwAffGjpOi3t6ImjoTqee5Jo7rc1mNOV6aRafOaNlzUqVGuboAFJCe3Bp74X2kP1den5zOY1AvRgu5fFu98HYtf5jPfzElFUrYjPbeXeTlI4rHKiBlIOH3BxyiS51ruVIJ9ToTLsrTTVTMG9uN1OsX-wZJ0F_r7fBQLXwkB_itCvD2f7MbIOYEOjXoZg2SKCXUuo7MZX9N2RZ_TS6-ydCdHiEaoiGqUwA_e53hiOs9JiaH7wkfSKGpe5B4ZKuS3-00i8gm-HV40tI6FTpCtBzjOhyh-uLiKPEN9EJNw4teZV9Gzs74T49PFtcZFZ5eLgEstw355IzdRlDd0CU9nlE7zSQawZfBPEuIWcCHdTEYkj8bLxbR_j0h99ZPLcuIJNJrzBgDh3fhjW0UXboTH4G1uO7Yuhwbni730394LVUOTsGLjRXM1qPU0noqkyTr1vMxX7N8cLasKt-4KFJRb0ygAOL2aCZMMDnAi=w550-h867-no"&gt;&lt;img src="https://lh3.googleusercontent.com/zNLWhPg8PBnekAzSSz7Z7MKdFeIITSdLDk9710dMnpT5kI99BWbc5PbyPNClDn_kkTz9nvTy68PQMLEJrko599WD5cJNR5F06Cx0QGfbLShNqJLvqAe94RUKWW7LCz2Ck3-AX7hEqBijtxf4j1_H4RgnY7GRHGNLPBA6ZCxGal2FUFgw9fmj7Ot75TJGwMwAffGjpOi3t6ImjoTqee5Jo7rc1mNOV6aRafOaNlzUqVGuboAFJCe3Bp74X2kP1den5zOY1AvRgu5fFu98HYtf5jPfzElFUrYjPbeXeTlI4rHKiBlIOH3BxyiS51ruVIJ9ToTLsrTTVTMG9uN1OsX-wZJ0F_r7fBQLXwkB_itCvD2f7MbIOYEOjXoZg2SKCXUuo7MZX9N2RZ_TS6-ydCdHiEaoiGqUwA_e53hiOs9JiaH7wkfSKGpe5B4ZKuS3-00i8gm-HV40tI6FTpCtBzjOhyh-uLiKPEN9EJNw4teZV9Gzs74T49PFtcZFZ5eLgEstw355IzdRlDd0CU9nlE7zSQawZfBPEuIWcCHdTEYkj8bLxbR_j0h99ZPLcuIJNJrzBgDh3fhjW0UXboTH4G1uO7Yuhwbni730394LVUOTsGLjRXM1qPU0noqkyTr1vMxX7N8cLasKt-4KFJRb0ygAOL2aCZMMDnAi=w550-h867-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>URLでプレースホルダー画像（ダミー画像）を返してくれるサイト</title><link>https://blog.piyo.tech/posts/2018-06-15-placeholder-image/</link><pubDate>Fri, 15 Jun 2018 06:28:28 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-15-placeholder-image/</guid><description>&lt;p&gt;モックアップ用でプレースホルダー画像を置きたいことがあると思います。わざわざ自分で用意するのは大変なので、URLベースでいろんな画像を返してくれるサービスを使うと便利です。&lt;/p&gt;
&lt;p&gt;大きく分けて写真を返してくれるサイトとサイズ表記の画像を返してくれるサイトの2種類にわかれます。サイトごとにライセンス表記があったりなかったりで要注意。画像に勝手にクレジットを入れてくれるところもあります（すごい）。&lt;/p&gt;
&lt;h1 id="lorempixel"&gt;lorempixel&lt;/h1&gt;
&lt;p&gt;一番有名っぽいサイト。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lorempixel.com/"&gt;http://lorempixel.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;http://lorempixel.com/幅/高さ/&lt;/code&gt; というURLで画像を返してくれます。URLのあとにカテゴリを追加するとそのカテゴリに合う画像になります。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lorempixel.com/400/200/"&gt;http://lorempixel.com/400/200/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lorempixel.com/400/200/"&gt;&lt;img src="http://lorempixel.com/400/200/" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;以前に比べて処理が遅くなったような気がします（個人の感想）&lt;/p&gt;
&lt;h1 id="loremflickr"&gt;LoremFlickr&lt;/h1&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://loremflickr.com" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://loremflickr.com/img/logo.large.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;LoremFlickr.com&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;LoremFlickr is a service that provides free placeholder images for web and print.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://loremflickr.com/img/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;loremflickr.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;こちらも幅と高さを入れたURLで画像を返してくれます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://loremflickr.com/320/240/dog"&gt;https://loremflickr.com/320/240/dog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://loremflickr.com/320/240/dog"&gt;&lt;img src="https://loremflickr.com/320/240/dog" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="lorem-picsum"&gt;Lorem Picsum&lt;/h1&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://picsum.photos" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://picsum.photos/id/237/250" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Lorem Picsum&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Lorem Ipsum... but for photos&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://picsum.photos/assets/images/favicon/favicon-32x32.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;picsum.photos&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;こちらもほぼ同じような使い方。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://picsum.photos/300/200"&gt;https://picsum.photos/300/200&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://picsum.photos/300/200"&gt;&lt;img src="https://picsum.photos/300/200" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="placeimg"&gt;PlaceIMG&lt;/h1&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://placeimg.com/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;placeimg.com →&lt;/span&gt;&lt;span&gt;https://placeimg.com/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://placeimg.com/320/240/any"&gt;https://placeimg.com/320/240/any&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://placeimg.com/320/240/any"&gt;&lt;img src="https://placeimg.com/320/240/any" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="placeholdercom"&gt;Placeholder.com&lt;/h1&gt;
&lt;p&gt;こちらはよりダミー感が強い画像を作ってくれます。ワイヤーフレームっぽい画面にもってこいです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://placeholder.com/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;span class="truncate"&gt;placeholder.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="http://via.placeholder.com/350x150"&gt;http://via.placeholder.com/350x150&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://via.placeholder.com/350x150"&gt;&lt;img src="http://via.placeholder.com/350x150" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="placeholdjp"&gt;Placehold.jp&lt;/h1&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://placehold.jp/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://placehold.jp/eeeeee/666666/200x200.png?text=placehold.jp" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;placehold.jp | 簡単！ダミー画像作成&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;簡単！ダミー画像生成、モックアップ用画像作成ツール。文字やサイズ、メモを入れた仮の画像を簡単に作成できます。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://placehold.jp/24/333333/ffffff/32x32.png?text=P" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;placehold.jp&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;日本語です。こちらもプレースホルダーらしい画像です。背景色や文字色も変えられます。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://placehold.jp/24/cc9999/993333/350x150.png"&gt;http://placehold.jp/24/cc9999/993333/350x150.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://placehold.jp/24/cc9999/993333/350x150.png"&gt;&lt;img src="http://placehold.jp/24/cc9999/993333/350x150.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;p&gt;他にもありそうでしたが、6個あれば十分間に合うかと思います。&lt;/p&gt;</description></item><item><title>画像を横方向 or 縦方向に結合するMacアプリ ImageJoiner</title><link>https://blog.piyo.tech/posts/2018-06-14-mac-image-joiner/</link><pubDate>Thu, 14 Jun 2018 06:23:06 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-14-mac-image-joiner/</guid><description>&lt;p&gt;画像を横とか縦にサクッと並べたいだけのときがあります。Sketchみたいなアプリでもできるし、ImageMagickのmontageコマンドなんかでもできますが、前者は面倒だし後者はやり方をよく忘れます。&lt;/p&gt;
&lt;p&gt;ということで、ImageJoinerというアプリを買って使っています。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://itunes.apple.com/jp/app/imagejoiner-2-combine-multiples-images-into-one/id1006127937" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;itunes.apple.com →&lt;/span&gt;&lt;span&gt;https://itunes.apple.com/jp/app/imagejoiner-2-combine-multiples-images-into-one/id1006127937&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;起動するとメニューバーに常駐します。アイコンをクリックすると設定画面が。ここで結合の方向とかスキマの設定を変えられます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/rHDkVRRw4WPNIcm4lZRyekTPh9XS_-DC26Y3VKwSw1K2zZrM38NlGybnbgn3r0qNj6YM2MgbXZtkOl0qoM0gL9R8aRnrIwo0zDqExiX7lkjU7_LQ8fseabyQxk793vInpoImWoE7IVSnPrCgSnjf9xoIfLsaZBfj46Sd7fA-CmAtItI8ZigxKXJ8wzAzvL0_z6c75Vd2qrAEDTNgnO-JOegS7F9I2z-sBLPKo74lzqHyfRzjOUMx-ejT9Barpa-rjd38PDde5sFWCEP7WMB0ZxtYWTdCncamAw9MDJIi3-vOVamonSL74Cnw8y-sa-MpWzwIeI4Y4zYQ1fDFSn5_oyxuUvhrK7g3jg8b-4JUejuLGLfZ5AOpQ9twDyHKAA2XywoQakltW7TieAavcZqRSXwOz5IlOxim38NoF3izNshhDS_s-7kADHLbntvlKTxyOiWIEts__9CWKTVHt1yiJ7_8A92P6-75TQqi9sS9E1W8TMbYAD-LKe-6tgEVKjJ3AWMGjWXXGTgmyTZK24yzegunwt-F1mrnm7iROLUWkKlYia12pKZCFDxBM_x8eV-uSr-21zTsJ5SMK9kFOo55ilTuEqmYHOgqhnkL4C0dgGKtw1N_MSCaYaT9MMsFWcogWV_npmStKhr-ETP_b8sgUo4eXYHJnU-9=w906-h334-no"&gt;&lt;img src="https://lh3.googleusercontent.com/rHDkVRRw4WPNIcm4lZRyekTPh9XS_-DC26Y3VKwSw1K2zZrM38NlGybnbgn3r0qNj6YM2MgbXZtkOl0qoM0gL9R8aRnrIwo0zDqExiX7lkjU7_LQ8fseabyQxk793vInpoImWoE7IVSnPrCgSnjf9xoIfLsaZBfj46Sd7fA-CmAtItI8ZigxKXJ8wzAzvL0_z6c75Vd2qrAEDTNgnO-JOegS7F9I2z-sBLPKo74lzqHyfRzjOUMx-ejT9Barpa-rjd38PDde5sFWCEP7WMB0ZxtYWTdCncamAw9MDJIi3-vOVamonSL74Cnw8y-sa-MpWzwIeI4Y4zYQ1fDFSn5_oyxuUvhrK7g3jg8b-4JUejuLGLfZ5AOpQ9twDyHKAA2XywoQakltW7TieAavcZqRSXwOz5IlOxim38NoF3izNshhDS_s-7kADHLbntvlKTxyOiWIEts__9CWKTVHt1yiJ7_8A92P6-75TQqi9sS9E1W8TMbYAD-LKe-6tgEVKjJ3AWMGjWXXGTgmyTZK24yzegunwt-F1mrnm7iROLUWkKlYia12pKZCFDxBM_x8eV-uSr-21zTsJ5SMK9kFOo55ilTuEqmYHOgqhnkL4C0dgGKtw1N_MSCaYaT9MMsFWcogWV_npmStKhr-ETP_b8sgUo4eXYHJnU-9=w906-h334-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;使い方は、結合したい画像をすべて選択した上でメニューバー上のアイコンへドラッグアンドドロップです。ちょっとわかりづらい。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Ml5f3HzadX44u4XHAfrlmD2y3oiqxdG9L-nCW7UgljjKKXSJ5GEer-J9jjp0uYulS9cp4aH9pExKvpSQWMP9MNuOCNNO7xPPULnd6jsUGmdcYTQl7NuEnhrgwhNGcfxy-XJB15045lK_YxdkYgZkixI9LyQZVKSC35ngj0IVEC-2HdLFnXqlfreUqQuEgNpeLpt-fd8_sO9LCdqAJXyv9rdr0_sNvhUcIy-oZvqDaeC9T02Zbk4kyJ0Lmb5j_wF-6u81OTba5Jj3O1NKbY1j0jmFvHFq_h2lgU9nSxEChenuiBoO7YU2u77q9FteQJ9m-9t8sKCRStU8XCGBe9obrKD4DqsqL7ETRoJQXyt4eu6KXUQFoRib68nlBCe5xTjfNaT23kqlcJTkpQEUGSeIAFj7D8yppmbyI8R-WQNvjGmlnYaEnEXIUY08nSXpOeceyz68F2BmMvuWd9eysf8HSaHI-_BnDu72KprGTDcwOCwPWcbRGYV1J6OLGjCEqoWUk2CW3hM08xmxpnZ1ryMOdnEZ9tlmYV7hWzTLPn0KOCAECsLY53wXz4G7ae7JRxsIL7YPfu9fMpyCZopMFe17TkaqG0vIkFVzaWJCg7OCnt28MlS9zwfz_8B7_Xa3unti2zyzZuqFAsPUmG-lv0kfdOBjwa0SQV6L=w738-h422-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Ml5f3HzadX44u4XHAfrlmD2y3oiqxdG9L-nCW7UgljjKKXSJ5GEer-J9jjp0uYulS9cp4aH9pExKvpSQWMP9MNuOCNNO7xPPULnd6jsUGmdcYTQl7NuEnhrgwhNGcfxy-XJB15045lK_YxdkYgZkixI9LyQZVKSC35ngj0IVEC-2HdLFnXqlfreUqQuEgNpeLpt-fd8_sO9LCdqAJXyv9rdr0_sNvhUcIy-oZvqDaeC9T02Zbk4kyJ0Lmb5j_wF-6u81OTba5Jj3O1NKbY1j0jmFvHFq_h2lgU9nSxEChenuiBoO7YU2u77q9FteQJ9m-9t8sKCRStU8XCGBe9obrKD4DqsqL7ETRoJQXyt4eu6KXUQFoRib68nlBCe5xTjfNaT23kqlcJTkpQEUGSeIAFj7D8yppmbyI8R-WQNvjGmlnYaEnEXIUY08nSXpOeceyz68F2BmMvuWd9eysf8HSaHI-_BnDu72KprGTDcwOCwPWcbRGYV1J6OLGjCEqoWUk2CW3hM08xmxpnZ1ryMOdnEZ9tlmYV7hWzTLPn0KOCAECsLY53wXz4G7ae7JRxsIL7YPfu9fMpyCZopMFe17TkaqG0vIkFVzaWJCg7OCnt28MlS9zwfz_8B7_Xa3unti2zyzZuqFAsPUmG-lv0kfdOBjwa0SQV6L=w738-h422-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;試しに&lt;a href="http://lorempixel.com/"&gt;lorempixel&lt;/a&gt;から画像を3つ借りてきて、縦方向と横方向にそれぞれつなげてみました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;縦方向&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/b-Dp_UN16t_ck_qdWxkZyoWEEdxayu9gZratK9tQ2ouugZtaoayqBnIxVf_BCCBijGSN_yXLgUYQuAygtV-F80Ahu_SgeGhL1oWJfN5ctlAqgxkG6HrrvyOuQpoVEEn6L9Drw1jBGq0tARrDm-v8VaiOcWd49nQF7rQaH37JDS2qLDDlc9uXsSihfPv8zeKg7KvhRnhqK88H8Z-WW4UVgIGb36ylXwrZjxDohxZNYSSCjnJIbIHhdi3PAHzykhPQNl56byZjPIGC22p3U7qR2tEjgGwykVaZM6O7JKAEJaWl3XHCEU-rzpJkhFhivhGCas0b6FN7gEdLquQ1agXxaj6Ta3yKeIk5EJxMV9XGVjDPxhqGrYajpD_zttIDTY7KmUU5aak5UyEO11bGx-j_hMa1j7H9Tpck625wxv3CM703cBztzbuIEPGR9h6GZlAEBljUIWVGHvYNa1wcvLA_-fJXX5C9kSg1J8SL6tuYa3eh_TAQ1J2CMuiJu9FF5rPScDKflK9xU_yTxWj8dlNui8cBp4o5qkNtq2jW1ygGpKHFt4xBopRonXAxk353c00LcGXUOKaoPF641mWgfKyCw3-rtQ6vEdX9OKe3W4S7bamZ9grQBp9cfv4cl3u_NnPp0Kd8zABwUeOrmTRm_6mtlQSUhg2ol0Fl=w150-h460-no"&gt;&lt;img src="https://lh3.googleusercontent.com/b-Dp_UN16t_ck_qdWxkZyoWEEdxayu9gZratK9tQ2ouugZtaoayqBnIxVf_BCCBijGSN_yXLgUYQuAygtV-F80Ahu_SgeGhL1oWJfN5ctlAqgxkG6HrrvyOuQpoVEEn6L9Drw1jBGq0tARrDm-v8VaiOcWd49nQF7rQaH37JDS2qLDDlc9uXsSihfPv8zeKg7KvhRnhqK88H8Z-WW4UVgIGb36ylXwrZjxDohxZNYSSCjnJIbIHhdi3PAHzykhPQNl56byZjPIGC22p3U7qR2tEjgGwykVaZM6O7JKAEJaWl3XHCEU-rzpJkhFhivhGCas0b6FN7gEdLquQ1agXxaj6Ta3yKeIk5EJxMV9XGVjDPxhqGrYajpD_zttIDTY7KmUU5aak5UyEO11bGx-j_hMa1j7H9Tpck625wxv3CM703cBztzbuIEPGR9h6GZlAEBljUIWVGHvYNa1wcvLA_-fJXX5C9kSg1J8SL6tuYa3eh_TAQ1J2CMuiJu9FF5rPScDKflK9xU_yTxWj8dlNui8cBp4o5qkNtq2jW1ygGpKHFt4xBopRonXAxk353c00LcGXUOKaoPF641mWgfKyCw3-rtQ6vEdX9OKe3W4S7bamZ9grQBp9cfv4cl3u_NnPp0Kd8zABwUeOrmTRm_6mtlQSUhg2ol0Fl=w150-h460-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;横方向&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/2kTSy4JtSfGHi1C4MMUOen9VKeFxNoVf_YE7ShEtOx0s9LGXOXaUs7Y7gQy5b_FiFVpCcQ0n49AiMB3iEwVkDXBDJaYwYHiwjHUq9WnHgEYVUm2RlbccNA2bwCXdE4-voLXiERuzr3r5GjjVPZSrXBpTpG03WIpTVBDaYSFjm0R7slZyuALE0qSOtg4DhRi9_DI-tn8rSGHhItvSrXVx5ZIBN7slY5_w0_1ud22ey5rMmhNoxJoERf0_cgAJrY-0on-45Smyuyp45f0lVBIR2rMgP8Y0gWSREPdP_NXeoUkLJuJHc4d-zncy1Kb7LxoiNGwKeKe_WHvmcXRFHhhNgRiuUaJeUrTBqXq_Fx7Rah38jDrtSfTmQFVpcV5lH4jb-F9__v12pM1aDrDdcUQf09QOXQT4gVpNMijaWG2dysz-2RWAnTVAhLiBKz9lF7VLMpZ91CzntEVj4skA1uutbmcEugFhj4iTWHMz_0nE9SDT6L4a0KcEihkX7TMpn0iEEBy2LauBR0PqJEo4DY32vWBxywAgU7OO4BrNSFOZTSg-JTVUFQ52KQ9CHjUfmyeBLjXi9_YF4LWwMvnQsmBJ1Ca9Z95hO0S3Z7AvGB3DeX_tYbLU0J8JA-SYSpK7V8joUbQx4GG1uHzHTvu9p3TFDrL9ZSbEVDSk=w460-h150-no"&gt;&lt;img src="https://lh3.googleusercontent.com/2kTSy4JtSfGHi1C4MMUOen9VKeFxNoVf_YE7ShEtOx0s9LGXOXaUs7Y7gQy5b_FiFVpCcQ0n49AiMB3iEwVkDXBDJaYwYHiwjHUq9WnHgEYVUm2RlbccNA2bwCXdE4-voLXiERuzr3r5GjjVPZSrXBpTpG03WIpTVBDaYSFjm0R7slZyuALE0qSOtg4DhRi9_DI-tn8rSGHhItvSrXVx5ZIBN7slY5_w0_1ud22ey5rMmhNoxJoERf0_cgAJrY-0on-45Smyuyp45f0lVBIR2rMgP8Y0gWSREPdP_NXeoUkLJuJHc4d-zncy1Kb7LxoiNGwKeKe_WHvmcXRFHhhNgRiuUaJeUrTBqXq_Fx7Rah38jDrtSfTmQFVpcV5lH4jb-F9__v12pM1aDrDdcUQf09QOXQT4gVpNMijaWG2dysz-2RWAnTVAhLiBKz9lF7VLMpZ91CzntEVj4skA1uutbmcEugFhj4iTWHMz_0nE9SDT6L4a0KcEihkX7TMpn0iEEBy2LauBR0PqJEo4DY32vWBxywAgU7OO4BrNSFOZTSg-JTVUFQ52KQ9CHjUfmyeBLjXi9_YF4LWwMvnQsmBJ1Ca9Z95hO0S3Z7AvGB3DeX_tYbLU0J8JA-SYSpK7V8joUbQx4GG1uHzHTvu9p3TFDrL9ZSbEVDSk=w460-h150-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;並び順は勝手に決まる（ように見える）ので、順番が大事なときは使いにくいかも。&lt;/p&gt;</description></item><item><title>React Nativeアプリをリリースするまでに最低限必要なiOS/AndroidのTodo</title><link>https://blog.piyo.tech/posts/2018-06-13-react-native-app-release/</link><pubDate>Wed, 13 Jun 2018 06:14:11 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-13-react-native-app-release/</guid><description>&lt;p&gt;React Nativeでアプリを書くことができたとしても、アプリをリリースする先はiOSのApp Storeであったり、Google Playだったりします。リリースするためには各プラットフォームでの作法や、コード上でやっておかないと行けないことが色々とあります。&lt;/p&gt;
&lt;p&gt;React Nativeで両プラットフォームに対応しようとすると、この辺の手続きに関しても両プラットフォームのことを知っておかないといけないため、なかなかハードです。僕の場合はiOSネイティブから入っているのでiOS側は勝手知ったる作業なのですが、Androidのほうは手探りでした。&lt;/p&gt;
&lt;p&gt;ということで、自分のための頭の整理も兼ねて箇条書きレベルでまとめておこうかなと思いました（まとめたところで、プラットフォーム側のアップデートとかでよく変わっちゃうんですけどね）。&lt;/p&gt;
&lt;p&gt;ネイティブアプリ未経験の人が、React Nativeでアプリを作れたとしてもリリースまでに色々あるんだよーというのがわかってもらえたら幸いです。&lt;/p&gt;
&lt;h1 id="ios"&gt;iOS&lt;/h1&gt;
&lt;h2 id="コード側"&gt;コード側&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;アプリアイコンを用意する
&lt;ul&gt;
&lt;li&gt;ホーム画面&lt;/li&gt;
&lt;li&gt;App Store&lt;/li&gt;
&lt;li&gt;Push通知 などに使われる&lt;/li&gt;
&lt;li&gt;1024pxがあるとそこから一括で生成したりできるので便利&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Info.plitでpermissionのメッセージを設定する&lt;/li&gt;
&lt;li&gt;Capabilitiesで必要なフィーチャを有効にする&lt;/li&gt;
&lt;li&gt;Distributionの証明書でcode signできるようにする
&lt;ul&gt;
&lt;li&gt;bundle id&lt;/li&gt;
&lt;li&gt;→ Dev Centerへの登録が必要&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;バージョン
&lt;ul&gt;
&lt;li&gt;バージョン番号&lt;/li&gt;
&lt;li&gt;ビルド番号
&lt;ul&gt;
&lt;li&gt;同一バージョン、同一ビルド番号はAppStoreConnectにアップロードできない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="管理サイト側"&gt;管理サイト側&lt;/h2&gt;
&lt;p&gt;App Store Connect（旧iTunes Connect）とDeveloper CenterみたいなAppleのサイトで登録やらなんやらを実施する必要があります。&lt;/p&gt;
&lt;h3 id="developer-center"&gt;Developer Center&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.apple.com/account/"&gt;https://developer.apple.com/account/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ビルド用の証明書の登録&lt;/li&gt;
&lt;li&gt;アプリの登録
&lt;ul&gt;
&lt;li&gt;bundle id（アプリ固有のID）&lt;/li&gt;
&lt;li&gt;アプリが使う機能の管理
&lt;ul&gt;
&lt;li&gt;Push通知&lt;/li&gt;
&lt;li&gt;XxxKit など&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;他にも色々
&lt;ul&gt;
&lt;li&gt;↓この辺は最近はXcodeがやってくれる気もする&lt;/li&gt;
&lt;li&gt;デバイスの管理&lt;/li&gt;
&lt;li&gt;ビルド用プロビジョニングプロファイルの管理&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="app-store-connect"&gt;App Store Connect&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://appstoreconnect.apple.com/"&gt;https://appstoreconnect.apple.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;アプリの追加
&lt;ul&gt;
&lt;li&gt;紹介文やカテゴリ、Rating、価格などの登録&lt;/li&gt;
&lt;li&gt;スクリーンショット&lt;/li&gt;
&lt;li&gt;審査への提出&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;TestFlight
&lt;ul&gt;
&lt;li&gt;リリース前に実機に入れて試すプロセス&lt;/li&gt;
&lt;li&gt;内部テスターの追加（まずは自分を登録）&lt;/li&gt;
&lt;li&gt;外部テスターの追加
&lt;ul&gt;
&lt;li&gt;ベータテストする人を追加&lt;/li&gt;
&lt;li&gt;（社内のメンバーだとしても内部テスターだと権限が強すぎるなどあるので、外部テスターにしてる）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;メンバー管理&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="android"&gt;Android&lt;/h1&gt;
&lt;p&gt;Android側はあまり経験がないのでうろ覚えみたいなところもあり。&lt;/p&gt;
&lt;h2 id="コード側-1"&gt;コード側&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;アプリアイコン
&lt;ul&gt;
&lt;li&gt;Google Play Storeやランチャー用&lt;/li&gt;
&lt;li&gt;通知用アイコン（透過に白のアイコンじゃないとだめ？）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;AndroidManifestでpermissionの設定&lt;/li&gt;
&lt;li&gt;バージョン
&lt;ul&gt;
&lt;li&gt;versionName&lt;/li&gt;
&lt;li&gt;versionCode（全バージョンで共通管理のビルド番号ぽい扱い）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;applicationId&lt;/li&gt;
&lt;li&gt;ビルド時のkeystoreの管理&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="管理サイト側-1"&gt;管理サイト側&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://play.google.com/apps/publish"&gt;Google Play Console&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;アプリの追加
&lt;ul&gt;
&lt;li&gt;紹介文やRating、価格などを登録&lt;/li&gt;
&lt;li&gt;スクリーンショットやヘッダー画像の登録&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;アルファ版、ベータ版の管理&lt;/li&gt;
&lt;li&gt;審査への提出&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="おわりに"&gt;おわりに&lt;/h1&gt;
&lt;p&gt;粒度バラバラなのはあまり気にせず、ざーと書いてしまいました。個別の説明をほとんどしていないのにけっこうな量になっちゃいましたね。やってみるとハマって先にすすめないことがあったりしてプラットフォームの初心者には辛いところです。&lt;/p&gt;</description></item><item><title>ワールドカップのトーナメント表を家庭用プリンタで大きく印刷する</title><link>https://blog.piyo.tech/posts/2018-06-12-world-cup-pdf/</link><pubDate>Tue, 12 Jun 2018 06:25:58 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-12-world-cup-pdf/</guid><description>&lt;p&gt;ついに6月になりました。ワールドカップロシア大会がもうすぐ始まります。4年前に引き続きトーナメント表を部屋に大きく貼りたいので再びこれをやろうと思います。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2014-05-23-203000/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://www.evernote.com/shard/s15/sh/fc4bf307-60cf-4abf-ac25-bbf87e453760/a1dfc6bafbbe2b6123afe29594556a09/deep/0/screenshot_340.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;大きい1枚のPDFをA4サイズ複数枚に分割して印刷する - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;大きい1枚のPDFをA4サイズ複数枚に分割して印刷する&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;まずは印刷したいトーナメント表を準備。僕はWebで検索して適当に見繕っておきました。&lt;/p&gt;
&lt;p&gt;そしてPosterDividerというソフトをこちらからダウンロード、インストールします。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://ja.osdn.net/projects/posterdivider/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;ja.osdn.net →&lt;/span&gt;&lt;span&gt;https://ja.osdn.net/projects/posterdivider/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;PosterDividerは1枚の画像やPDFを分割して印刷できるように切ってくれるツールです。こんな感じ↓で、欲しいサイズとかのりしろの幅とかを指定すると、右下のプレビューのように分割したPDFを作ってくれます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Qb39beUSyouhTVRCXZvLp3QtYapxMdX97CtdQvwvF4LU2i6FD0ojod-yhIo55SWTvf5fJ63y41HYvUAKaPy3NhZX3ljDaJfTQQHpNHXRF9djrFLkNaV1hPYP4zZD5pnYcOeywOvP_eXwqICeJW_1BhVbk4bq4rXcyiWu3V1mLERvQ5nRPyv7lbFYWL-SeZXAVi1CkOFggFR5mV_Z4tp09HReeVs4JxvfmB1aMzY6rZIwDurl36RJXbGy5zewBoRfwSpDAKTepm39189KHM0eyhg55IewriTLZXZM-dm_usfBrp_jHjRsTdMoFb6UZfIuMVXVBni1zMUszFUexQP6JFVs6Re5j-ZLAq5wkP0nC8faEYFhgsPw9Fb8perGeHKTSK2EcLCuxi0jPFQOUpH_r8GZ5mlZ1O-abKPDd1uOrW_W1197etU_WUWVxdSVCtTSjnz1mCiLyG9VnTL6jFrIrpIY2SSB2MIRdFmizBJmRuP8tB2UD0Pbmx84FelHbIoB9QpqRo8bSzDnCD4wNbN-XgaioVf68DiUDP29hJY3h-YY4vfTn1-6-kkuqOU-gVEpMcPoixgiZsU5hG6MRVYaVlLLZExU8aj0cNDzpdowwxO71F6CJhsK4doX6m7LM_lyylOIW5DI4Ua6lBowYD5WABdJSlLEC3vT=w1137-h797-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Qb39beUSyouhTVRCXZvLp3QtYapxMdX97CtdQvwvF4LU2i6FD0ojod-yhIo55SWTvf5fJ63y41HYvUAKaPy3NhZX3ljDaJfTQQHpNHXRF9djrFLkNaV1hPYP4zZD5pnYcOeywOvP_eXwqICeJW_1BhVbk4bq4rXcyiWu3V1mLERvQ5nRPyv7lbFYWL-SeZXAVi1CkOFggFR5mV_Z4tp09HReeVs4JxvfmB1aMzY6rZIwDurl36RJXbGy5zewBoRfwSpDAKTepm39189KHM0eyhg55IewriTLZXZM-dm_usfBrp_jHjRsTdMoFb6UZfIuMVXVBni1zMUszFUexQP6JFVs6Re5j-ZLAq5wkP0nC8faEYFhgsPw9Fb8perGeHKTSK2EcLCuxi0jPFQOUpH_r8GZ5mlZ1O-abKPDd1uOrW_W1197etU_WUWVxdSVCtTSjnz1mCiLyG9VnTL6jFrIrpIY2SSB2MIRdFmizBJmRuP8tB2UD0Pbmx84FelHbIoB9QpqRo8bSzDnCD4wNbN-XgaioVf68DiUDP29hJY3h-YY4vfTn1-6-kkuqOU-gVEpMcPoixgiZsU5hG6MRVYaVlLLZExU8aj0cNDzpdowwxO71F6CJhsK4doX6m7LM_lyylOIW5DI4Ua6lBowYD5WABdJSlLEC3vT=w1137-h797-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;あとはPDFを（通常は）A4用紙に印刷してのり付けをすれば大きめのポスターが完成。今回はA4を4枚使ったのでだいたいA2サイズ相当のポスターになりました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/8jQCXOZX0EElR1RWn9PYm53depkesSjzBG7pJpRmN6y_8ahFUbz1JNbDHUd4b_9X2-Tvj9nxisLfiMFdU6ANLG0FkFMhlCQ5DSw8Pm63jeWtclgSRGLyE_IhFVxRg5XbRzP43XTjT3318mQKGpNwpM76ujRBBgBgMZkIyz0oh1t6o3SHMLiapOXqEMwAAprqXAIKVj63pNdxA57w5BfMIkuaTt0FBGn35enswDRaaCdRutenX0MEJzESMeQmK4e2jrtjuaKN1EMPzGd5RjedQ8wPHVcttAsCVWB94nHG0IeZfAL2XFZ799tPnVlzckG_WJWY541972bkBoAQxFXvUylDiTcCJ9nbIIMJuUYhl-tDSkh1TdmXhVpmSsA7JiwMwTp_qkH66h8hLrHd2Rvbac2-uaMLEQUjNzzLPGaFN8YKXV1Yv4Y9EOQVvLGCens2JGZswJd7yWVjKEwHVJ5R8KvCB-MTI-2sjcmEo_Ma0eROLu20dmSwRonj1vJu4UZm0S8Bl4Q9Du_pkp1_7dXHQrGSN6DnvFdwfZ_I_KSDYaeIith__b7XrICS3ub2qIIVRvIKEwbCP_MCaAfyIJd3PVKLGZ9uGNhzyIYXa4ncUKdi5D91StPV6FEyxf93P7MTmkgVMjg0Uz-PDhXHmc2MadvdNBjLj8HD=w1238-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/8jQCXOZX0EElR1RWn9PYm53depkesSjzBG7pJpRmN6y_8ahFUbz1JNbDHUd4b_9X2-Tvj9nxisLfiMFdU6ANLG0FkFMhlCQ5DSw8Pm63jeWtclgSRGLyE_IhFVxRg5XbRzP43XTjT3318mQKGpNwpM76ujRBBgBgMZkIyz0oh1t6o3SHMLiapOXqEMwAAprqXAIKVj63pNdxA57w5BfMIkuaTt0FBGn35enswDRaaCdRutenX0MEJzESMeQmK4e2jrtjuaKN1EMPzGd5RjedQ8wPHVcttAsCVWB94nHG0IeZfAL2XFZ799tPnVlzckG_WJWY541972bkBoAQxFXvUylDiTcCJ9nbIIMJuUYhl-tDSkh1TdmXhVpmSsA7JiwMwTp_qkH66h8hLrHd2Rvbac2-uaMLEQUjNzzLPGaFN8YKXV1Yv4Y9EOQVvLGCens2JGZswJd7yWVjKEwHVJ5R8KvCB-MTI-2sjcmEo_Ma0eROLu20dmSwRonj1vJu4UZm0S8Bl4Q9Du_pkp1_7dXHQrGSN6DnvFdwfZ_I_KSDYaeIith__b7XrICS3ub2qIIVRvIKEwbCP_MCaAfyIJd3PVKLGZ9uGNhzyIYXa4ncUKdi5D91StPV6FEyxf93P7MTmkgVMjg0Uz-PDhXHmc2MadvdNBjLj8HD=w1238-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B00NSFP1FS/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/71BCLVqtE7L._AC_SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;(旧モデル) brother レーザープリンター A4 モノクロ JUSTIO HL-L2365DW&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>ブログ用のOGPサーバーが500を返すせいでHugoのビルドがこけてた</title><link>https://blog.piyo.tech/posts/2018-06-11-data-driven-content-api/</link><pubDate>Mon, 11 Jun 2018 06:23:55 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-11-data-driven-content-api/</guid><description>&lt;p&gt;この土日、定期的に動かしているブログのビルドが失敗するようになりました。調べてみるとブログのリンクカードみたいなのを作るために自前のサーバーにOGPを取りに行く際、とあるリンク先のドメインが見つからずに500エラーで返って来ていることが原因でした。ドメインの有効期限が切れたか何かだと思われます。&lt;/p&gt;
&lt;p&gt;ちなみにリンクカードやサーバーについてはこのへんとか、&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-04-02-blog-link/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/r0owED5cBmCrD0wSbGkZkndJpmBW1SzYJPnfeb4w6XtcRfmmAr7IEYeo2nsjt3cHb81HlpByTaF4-1_UIXqJrWCfj_m-EaPaoYEszOlNg5qSIgQPbKBiyLQVgylgohhqzlss39qtNC7C6PzmxN0t6i0tAlfN858y1NXR-p9zoGsNDD_ESSfy5xrMOqAyWcav-aqnKjggx4xOnbxK0zA7qw8zVdqztuAfysiwKZI1r39UZ13ina1SjA_TEeC3zdQ132HcK4UuGSyLFmB0W662oCOyZaCz4yaTVN4tcXQm8aGsNn1nyyp7S0MQiJk2Oy-zFHcwh4WAojtUMX9HJa9T_C34B6LNPrgoavxsVumFk76ZmCVguxzLstJ1GUg61u61j1f3g_Yd3f83cTz64mc5Tg3dn4EFrgrBRQ0ZudYx99jZDTC2vYPvlZBTxWzjkWNo0AFEwO2IcZtRf31y07Jqrp5LtXwAayPNEO138CoeS7Bhc88Llw3SM76R2KYu-gbVnbljhq1xYI_bgTT_zNNl561znfF96T9wX8bwfVYEziO8i5iVIK5vUl4l1d_JCi_9Ydy-bK8ooczLhq9hWaw0czTbT8X36HjU8NmfZLDrvZC7JaBhaki5JeMjvQEw0BlchpNVno0IHoZyEe2vv59ZJpu-_agRSarUKA=w1000-h667-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Hugoでブログリンクの見た目をはてなブログっぽくする - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;これまで HeartRails Capture を使ってきたブログ内リンクを自前の実装とショートコードに置き換えました。 以前使っていたはてなブログのリンクの表示形式が気に入っていたので、それをリスペクトする形でほぼ同じような見た目で表示できるようにしました。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;このへんとかに、書いてあります。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-04-04-ogp-json/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://goo.gl/NSXeuF" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;ブログのビルド用にOGPの情報をJSONで返すサーバーも作った - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;前回の続きです。 https://blog.piyo.tech/posts/2018-04-02-blog-link/ リンクの見た目をいい感じにするためにOGPのJSONのサーバーを作って、Data-Driven Contentで表示するようにしたよ、というのが前回の話です。 echoのサーバーに機能追加 https://blog.piyo.tech/posts/2018-03-27-deploy-go/ すでに動かしているGoのサーバーに機能を追加しました。 /ogp?url=http://xxxxx とリクエストすると欲しいサイトのOGPをJSONで返してくれるようにします。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;というわけでサーバー側のコードを修正しました。エラーで失敗したときに400番台、500番台を返すとビルドが止まるようだったので、OGPの取得に失敗したとしても200を返すようにしました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;対応前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;og&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;opengraph&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fetch&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;url&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusInternalServerError&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Error: %s&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Error&lt;/span&gt;()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;対応後&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;og&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;opengraph&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fetch&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;url&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Error: %s&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Error&lt;/span&gt;())}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;JSON&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusOK&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;元々は&lt;code&gt;Fetch&lt;/code&gt;でエラーが返ってきたときは500エラーで文字列を返していたのを、200でエラーのJSONを返すように変更。そして、Hugo側のHTML（というかテンプレート）で&lt;code&gt;error&lt;/code&gt;の有り無しで分岐をすることに。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{{- $json := getJSON .Site.Params.OgpJsonBaseUrl $url -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{{- $error := $json.error -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;{{ if eq $error nil }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; 元々のHTML
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;{{ else }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $url }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;_blank&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; {{$url}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;エラー有りで返ってきた場合は単にURLの文字列のリンクとするように変えました。これで無事ビルドできるようになりました。&lt;/p&gt;</description></item><item><title>Bandwidth+でMacの通信量を計測する</title><link>https://blog.piyo.tech/posts/2018-06-10-bandwidth/</link><pubDate>Sun, 10 Jun 2018 06:38:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-10-bandwidth/</guid><description>&lt;p&gt;テザリングで使い過ぎないようにBandwidth+っていうアプリを常駐させてます。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://itunes.apple.com/jp/app/bandwidth/id490461369?mt=12" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;itunes.apple.com →&lt;/span&gt;&lt;span&gt;https://itunes.apple.com/jp/app/bandwidth/id490461369?mt=12&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;このアプリは今日の上り下りの通信量をネットワーク毎に記録してくれます。メニューバーにはサマリーとして、現在のネットワークにおける今日の通信量の合計が表示されます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/2O_wHUr5Rvf_DQT3Yy7omXo2NSyGUzpAxK6hc5EL7sIDz-D-lJwW2FQl2hOan5DnK5AQ04Zi9ZoCim53QVmQ6mlKg4foe3Fk6o_MNl3MRMWOKKJEMxpMkGNus0OgVIRO-tjjQ0ML2uS8Xur-vdOrLBlO4GbJ5L3VAC28aKRIuA7cN8_WJKj_QHMgkiBFswg8eJN-BknPX8eYnHhStmgh0uITcwN9XOrdC-bLcxjF8PrCdElrTXkWt9YRmU0Yhqwf36jq-tvoFyc74kez0g_BmHOuw9ao9IUgGy-YD89FqhvsO1Flm3Xjl3FQ_Ao5sSL21KFfvNSm5V1uWRCyppQBI49ANRNp1oAXAZPdp_Xnk6OxqKWnbOONsKIsiv7ygeBvK_d4c0b66a_ioOIQB9R0AsniFjR-06gAqt2H08xZPXz6N5acs4AiccvX1ec-hXEVxUI8YRXV-IEuejFXZiwBL9n2wf1jSil2Sr6oBIMz7Dy4ey_9BI_aVP4RidWa5qUZeeQOMxXyteKf1J2iWrhmgOp5m1Q55W1skrb1Zj41YBY_Aa-22a3fm9OKGwjN3KPsnpcSBXKFyvtc9UttnI3LgDGsFqnPdoUq_UfbhTdZUr6H1t8qxDmo-2UVOZ9NH2WECCn6K4JE0ekZaaR6buKObFpPSE7PvOx3tA=w349-h138-no"&gt;&lt;img src="https://lh3.googleusercontent.com/2O_wHUr5Rvf_DQT3Yy7omXo2NSyGUzpAxK6hc5EL7sIDz-D-lJwW2FQl2hOan5DnK5AQ04Zi9ZoCim53QVmQ6mlKg4foe3Fk6o_MNl3MRMWOKKJEMxpMkGNus0OgVIRO-tjjQ0ML2uS8Xur-vdOrLBlO4GbJ5L3VAC28aKRIuA7cN8_WJKj_QHMgkiBFswg8eJN-BknPX8eYnHhStmgh0uITcwN9XOrdC-bLcxjF8PrCdElrTXkWt9YRmU0Yhqwf36jq-tvoFyc74kez0g_BmHOuw9ao9IUgGy-YD89FqhvsO1Flm3Xjl3FQ_Ao5sSL21KFfvNSm5V1uWRCyppQBI49ANRNp1oAXAZPdp_Xnk6OxqKWnbOONsKIsiv7ygeBvK_d4c0b66a_ioOIQB9R0AsniFjR-06gAqt2H08xZPXz6N5acs4AiccvX1ec-hXEVxUI8YRXV-IEuejFXZiwBL9n2wf1jSil2Sr6oBIMz7Dy4ey_9BI_aVP4RidWa5qUZeeQOMxXyteKf1J2iWrhmgOp5m1Q55W1skrb1Zj41YBY_Aa-22a3fm9OKGwjN3KPsnpcSBXKFyvtc9UttnI3LgDGsFqnPdoUq_UfbhTdZUr6H1t8qxDmo-2UVOZ9NH2WECCn6K4JE0ekZaaR6buKObFpPSE7PvOx3tA=w349-h138-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;設定によっては上りの合計とか下りの合計、通信の速度なんかも出せます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/DtccbmcfOPxhaTzwiKoIrTwJJbHRfBEvQdj5Lfd4a2-xhM-D_st4KEEnEOwTpGMrX3d1v5ZVtJH5KrLuVgxRJHqVzusbsAU9qeGBC-2u9zkjjBx2WxOAEgb7s3P52oFSp1ub37KTAecmIXUUSXLfCek-pTuCaGIzIiwyb4HHSreuUlsKH7auuHPoi3nfXZd6NNdJkvyY0n8kDhQcG1cAl60DVZAA03DjxJvS088uXObJTpZ8o4zJQzC7QetvAO5wI9nlQakOLsn5h5iSuemGhwpxmWD9TYWtgyQ-XSF1ne1lAl0rbeh5XD2B2b1dG42DnXiRI6fAoBWCn1Y8VfBX2Bxue5XqprPF8kBribAq2zsT8M9ixDmfi1OTy9hLhP6AKfOTwNluKJeNGAcdFxHNZmYZ2MZC-ly93R-WNx_bATTXpIhtqim1UcbLTJbIi_2_gSTDIqEiGy9FNTaYidl8qv9Dn3dWIBES9n64LC8chwItlok88iwl5qaMwt-zgkjAl5j5xYhrjq7NnuosmeTnviVjYjUqEom7uV5Gyhg0XHUCkxybCYQ1jjB1x1yzSvb5esK0xX3ZBLIeTyh-9Uqj1P30Ek9PJ_TFQn2ji67r94SLgZ-Cm9hWGrnpeFdokiKgpEnAlGUPEkvpWUKWIk2eCd0aoNh1y5df8A=w592-h448-no"&gt;&lt;img src="https://lh3.googleusercontent.com/DtccbmcfOPxhaTzwiKoIrTwJJbHRfBEvQdj5Lfd4a2-xhM-D_st4KEEnEOwTpGMrX3d1v5ZVtJH5KrLuVgxRJHqVzusbsAU9qeGBC-2u9zkjjBx2WxOAEgb7s3P52oFSp1ub37KTAecmIXUUSXLfCek-pTuCaGIzIiwyb4HHSreuUlsKH7auuHPoi3nfXZd6NNdJkvyY0n8kDhQcG1cAl60DVZAA03DjxJvS088uXObJTpZ8o4zJQzC7QetvAO5wI9nlQakOLsn5h5iSuemGhwpxmWD9TYWtgyQ-XSF1ne1lAl0rbeh5XD2B2b1dG42DnXiRI6fAoBWCn1Y8VfBX2Bxue5XqprPF8kBribAq2zsT8M9ixDmfi1OTy9hLhP6AKfOTwNluKJeNGAcdFxHNZmYZ2MZC-ly93R-WNx_bATTXpIhtqim1UcbLTJbIi_2_gSTDIqEiGy9FNTaYidl8qv9Dn3dWIBES9n64LC8chwItlok88iwl5qaMwt-zgkjAl5j5xYhrjq7NnuosmeTnviVjYjUqEom7uV5Gyhg0XHUCkxybCYQ1jjB1x1yzSvb5esK0xX3ZBLIeTyh-9Uqj1P30Ek9PJ_TFQn2ji67r94SLgZ-Cm9hWGrnpeFdokiKgpEnAlGUPEkvpWUKWIk2eCd0aoNh1y5df8A=w592-h448-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>ElectronなしでJSでデスクトップアプリを書けるProton NativeをQuick startした</title><link>https://blog.piyo.tech/posts/2018-06-09-proton-native/</link><pubDate>Sat, 09 Jun 2018 06:14:58 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-09-proton-native/</guid><description>&lt;p&gt;出落ちで済みませんが、Proton Nativeとか言うのを見つけて試した、というお話です。&lt;/p&gt;
&lt;p&gt;React Nativeでモバイルアプリを書くようなノリでデスクトップアプリを書けるよ、っていう&lt;code&gt;Proton Native&lt;/code&gt;というフレームワークがありました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/kusti8/proton-native" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/06d8fc88ed2ce0437f644c038ba116a6c6f68fc0276feaa60a8bc6566250054e/kusti8/proton-native" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - kusti8/proton-native: A React environment for cross platform desktop apps&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;A React environment for cross platform desktop apps - kusti8/proton-native&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;裏では&lt;code&gt;libui&lt;/code&gt;、そしてそのJSバインディングである&lt;code&gt;libui-node&lt;/code&gt;が使われているらしい。&lt;code&gt;libui&lt;/code&gt;、なに？って感じなので今度調べます。&lt;/p&gt;
&lt;p&gt;インストールからひな形アプリの生成、そして起動までざっとやってみます。これはquick startに書いてある通りです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://proton-native.js.org/#/quickstart" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Proton Native - React Native for the desktop, cross compatible&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://proton-native.js.org/images/favicon.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;proton-native.js.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% npm install -g create-proton-app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;% create-proton-app my-app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;% cd my-app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;% npm run start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;で、これをすると簡単なアプリが起動します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/y2bTEStVJgw0xI_AUJ7oTgkmgz9jyp_pBFWVAk8ekhMt1aTDbu7ZI0Q1vWeGoH7HckY5I5Fi_wQfjHX76rcv_91eivixiDaw-FxsjdVhGpVMxVjvnxuOMtlbUWt79_tgoWHMJysU8djzEqxAOPPZtghwEcMifBwmXJdXrrNZD2CDPjbIdQ6GtI-kSArlPsvPq6WCLR9yLYo2RlOQPddVvuZte_3YkPQo6DIlJJLwIIMnEJPm3QcfMXY-9ZAsA62CyPmJe-KUsZPQ_1OlKKxI_DwtYgjkbAxrEpcuGIbpJyMeABFoD8VvVLSrs40kHA-b7bNmls5KzeX4D9A-e25u37rzzNTfqUMKuNVxyTdbJCN1F1wJpdo2YMy7lPK1BdQHng10bdKFCZ-H4HQLLLn-GILY_VL3FWU5923q2DP-iZ8PKDrFmfMd-LPcQotUpUF9md2-pgCgaqqui5kiGg_16UrGNAaR3TuD63y207eGRiZXoBXYCYv8j-mWQdoEB_0wog_sOvkreoB_BXn825WgOzE-2p7D3OlhjriW6uhvO0UtdCd16FUp2Q_Gdm6i56iKqDq-iSSGGUXfdjMnCtxyReDfILgJmWoY543TK28Tafwh2hdX1iY5W66Xk4LNziGMPCoIltJxlwLbYFEOWUqlxe1TrtPyGS3vBA=w327-h343-no"&gt;&lt;img src="https://lh3.googleusercontent.com/y2bTEStVJgw0xI_AUJ7oTgkmgz9jyp_pBFWVAk8ekhMt1aTDbu7ZI0Q1vWeGoH7HckY5I5Fi_wQfjHX76rcv_91eivixiDaw-FxsjdVhGpVMxVjvnxuOMtlbUWt79_tgoWHMJysU8djzEqxAOPPZtghwEcMifBwmXJdXrrNZD2CDPjbIdQ6GtI-kSArlPsvPq6WCLR9yLYo2RlOQPddVvuZte_3YkPQo6DIlJJLwIIMnEJPm3QcfMXY-9ZAsA62CyPmJe-KUsZPQ_1OlKKxI_DwtYgjkbAxrEpcuGIbpJyMeABFoD8VvVLSrs40kHA-b7bNmls5KzeX4D9A-e25u37rzzNTfqUMKuNVxyTdbJCN1F1wJpdo2YMy7lPK1BdQHng10bdKFCZ-H4HQLLLn-GILY_VL3FWU5923q2DP-iZ8PKDrFmfMd-LPcQotUpUF9md2-pgCgaqqui5kiGg_16UrGNAaR3TuD63y207eGRiZXoBXYCYv8j-mWQdoEB_0wog_sOvkreoB_BXn825WgOzE-2p7D3OlhjriW6uhvO0UtdCd16FUp2Q_Gdm6i56iKqDq-iSSGGUXfdjMnCtxyReDfILgJmWoY543TK28Tafwh2hdX1iY5W66Xk4LNziGMPCoIltJxlwLbYFEOWUqlxe1TrtPyGS3vBA=w327-h343-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Example&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;() { &lt;span style="color:#75715e"&gt;// all Components must have a render method
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;App&lt;/span&gt;&amp;gt; &lt;span style="color:#75715e"&gt;// you must always include App around everything
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;Window&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Proton Native Rocks!&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;size&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{&lt;span style="color:#a6e22e"&gt;w&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;h&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;}} &lt;span style="color:#a6e22e"&gt;menuBar&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;}&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#75715e"&gt;/* all your other components go here*/&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;Window&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;App&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コードはほぼReactです。サンプルとしてこれじゃあまりにアレなので、ボタンを置いて動かしてみました。&lt;/p&gt;
&lt;p&gt;コードを↓のように変更して、ボタンを押したらダイアログを表示してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Example&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;() { &lt;span style="color:#75715e"&gt;// all Components must have a render method
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;App&lt;/span&gt;&amp;gt; &lt;span style="color:#75715e"&gt;// you must always include App around everything
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;Window&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Proton Native Rocks!&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;size&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{&lt;span style="color:#a6e22e"&gt;w&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;h&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;}} &lt;span style="color:#a6e22e"&gt;menuBar&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;}&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;Button&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onClick&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{() =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Dialog&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Message&amp;#39;&lt;/span&gt;, {&lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ダイアログを開きましたね？&amp;#34;&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; }}&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Open&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;the&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Dialog&lt;/span&gt;&lt;span style="color:#f92672"&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;Button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;Window&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;App&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;なんか小さくなった&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/jTb77HUVx2eW1mcFxCWT8VLvzFTGoJ1przVoUV4PzSsHFnp9nTTKgOuqi3SB2HfTnO10S_cn8Un7Y2HTmGwKRiTZKMCAQABNhG4GvqZ5nx2-tb5J1gOeaLB9NwcKTFvCe3_2FJ1TQ9RoeXF3LphIV5CudOVXySixzzA38l6Zl40Xh_sYbeYxBdQ5xVMMTvUdON8Arkb8F0uzv3KdCXBS04DHS8fQ_-naxj7u179ALXUEyfzOQS0SEe3Fpf-XVgNF2IvsQqyQmiX-fd02nd01jsj86_xUZuBVnvutUYPdVCDLtOgpUFoc9h_olTu6QKIyAte4FXYQg29AqDvEt5FzadMGoTZFgX7IaulqRqEXTkd8AP9Yo7r5MgeH3AS3INbGEjQM6TbU7EnI2mwtvsz7uV9kHi1RYFbSokKHmMRKVIJ3rMriKQJPbX8Vl4EJtgKXtyGIpQgRsajSME_mCHGZXv39_hNuYu9ktqAB9nAMzkoaoi_Nt_wiLogU4hvBAU1PegKXlJVlho36Yojxb-3Jkdb-t3BK1n5_aZiWcDUBqAYqEFnFUh7rOEVIJbDEdhJ7dNn_s7Y1dR9fzSM4Lxp_9hY4vZPq_qjhUe-PUGiQ3KJx93cErc8K01alQOQ9YPjbOf1hEJTbJ99Gt9l0oNblYimN1s5UUU2u4w=w412-h155-no"&gt;&lt;img src="https://lh3.googleusercontent.com/jTb77HUVx2eW1mcFxCWT8VLvzFTGoJ1przVoUV4PzSsHFnp9nTTKgOuqi3SB2HfTnO10S_cn8Un7Y2HTmGwKRiTZKMCAQABNhG4GvqZ5nx2-tb5J1gOeaLB9NwcKTFvCe3_2FJ1TQ9RoeXF3LphIV5CudOVXySixzzA38l6Zl40Xh_sYbeYxBdQ5xVMMTvUdON8Arkb8F0uzv3KdCXBS04DHS8fQ_-naxj7u179ALXUEyfzOQS0SEe3Fpf-XVgNF2IvsQqyQmiX-fd02nd01jsj86_xUZuBVnvutUYPdVCDLtOgpUFoc9h_olTu6QKIyAte4FXYQg29AqDvEt5FzadMGoTZFgX7IaulqRqEXTkd8AP9Yo7r5MgeH3AS3INbGEjQM6TbU7EnI2mwtvsz7uV9kHi1RYFbSokKHmMRKVIJ3rMriKQJPbX8Vl4EJtgKXtyGIpQgRsajSME_mCHGZXv39_hNuYu9ktqAB9nAMzkoaoi_Nt_wiLogU4hvBAU1PegKXlJVlho36Yojxb-3Jkdb-t3BK1n5_aZiWcDUBqAYqEFnFUh7rOEVIJbDEdhJ7dNn_s7Y1dR9fzSM4Lxp_9hY4vZPq_qjhUe-PUGiQ3KJx93cErc8K01alQOQ9YPjbOf1hEJTbJ99Gt9l0oNblYimN1s5UUU2u4w=w412-h155-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ダイアログが出た&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/60ntSq_X8_aX8PEnTpR1sIbURSnwXS0Y0yuL4Z-6rgMSLZpDBAyVO_zsBylQhobI5gpt5I9KzYL4f3ptlCYFu201WNw3kk2_Yu3T6FFGGpKHvCMxq3zHdfNIXMkAzxm0aTdc1x8RkPIMYlOieYd3fG6DygusPbJxAsMDd6-dSAsU1HA17excznGssMBHy0OT0b2WW_C-v0iFRRG33LwAOiwchzucdznOfsN-d4bvQBcGopBYhf9vYTtTjhAvK_93hhaKG321AGsU5sK-zBmJJKwXNSlN9fMSBOnvYNHVQ-ukiS7h1Gu8NP1F7LtarIjltSpwZL-vncAlGEv0ys1zC_I8KLoE6HJ1GooYv5TvzcIf593Lz1ezC4ejlaVEU75h9wIDcuLRMK1fA8eCjS4XeL2Pg2hXuop3OfZmcnsUPNu8uIqhGasx4aAmcl612hmEw2SIVQ2zNBmndyjZlxPOxvqreVjca9XHIowGnqXVd3c_MwuK6s6TJ6y-4rOJ3Ae62MEHXzkrYNbbsd1-VxQc9iufIsAWMvjso8xk2NyftY43CrOrIMRVcSqc2JkyliG90yAjBXy_YXrTOsBBHy99w3OACHo1Pw70exV1Wi1AQgVvliFgQM6H3FmbPUUzonisjc2bKZJuortmpWOV1I6LrJwOvOPxHXtEjA=w454-h204-no"&gt;&lt;img src="https://lh3.googleusercontent.com/60ntSq_X8_aX8PEnTpR1sIbURSnwXS0Y0yuL4Z-6rgMSLZpDBAyVO_zsBylQhobI5gpt5I9KzYL4f3ptlCYFu201WNw3kk2_Yu3T6FFGGpKHvCMxq3zHdfNIXMkAzxm0aTdc1x8RkPIMYlOieYd3fG6DygusPbJxAsMDd6-dSAsU1HA17excznGssMBHy0OT0b2WW_C-v0iFRRG33LwAOiwchzucdznOfsN-d4bvQBcGopBYhf9vYTtTjhAvK_93hhaKG321AGsU5sK-zBmJJKwXNSlN9fMSBOnvYNHVQ-ukiS7h1Gu8NP1F7LtarIjltSpwZL-vncAlGEv0ys1zC_I8KLoE6HJ1GooYv5TvzcIf593Lz1ezC4ejlaVEU75h9wIDcuLRMK1fA8eCjS4XeL2Pg2hXuop3OfZmcnsUPNu8uIqhGasx4aAmcl612hmEw2SIVQ2zNBmndyjZlxPOxvqreVjca9XHIowGnqXVd3c_MwuK6s6TJ6y-4rOJ3Ae62MEHXzkrYNbbsd1-VxQc9iufIsAWMvjso8xk2NyftY43CrOrIMRVcSqc2JkyliG90yAjBXy_YXrTOsBBHy99w3OACHo1Pw70exV1Wi1AQgVvliFgQM6H3FmbPUUzonisjc2bKZJuortmpWOV1I6LrJwOvOPxHXtEjA=w454-h204-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;↑の例ではWindowサイズが無視されてボタンのサイズにフィットしてしまいました。余白をいれたり中央に配置したりできないかと色々試しましたが、どうやらレイアウトを微調整するのがかなり難しいことがわかりました。そもそも&lt;code&gt;libui&lt;/code&gt;の癖なのか、ProtonNativeにAPIが足りないのか、そこまではまだわかっていません。実用にはもう少し成熟が必要そうです。&lt;/p&gt;
&lt;p&gt;とはいえ、デスクトップアプリをサクッと作りたいと常日頃思っていたので、React Nativeに慣れている僕にとっては、似たような考え方で書けるProton Nativeの存在は期待しています。&lt;/p&gt;</description></item><item><title>ローカル環境をインターネットに公開できるngrokのユースケース</title><link>https://blog.piyo.tech/posts/2018-06-07-ngrok-usecase/</link><pubDate>Thu, 07 Jun 2018 06:18:08 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-07-ngrok-usecase/</guid><description>&lt;p&gt;ngrokというサービスがあります。僕は無料で簡易に使ったことしかないのでその範囲内の話しかできないですが、ユースケースを紹介したいと思います。&lt;/p&gt;
&lt;p&gt;まず使い方はとても簡単。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% brew cask install ngrok
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;% ngrok http &lt;span style="color:#ae81ff"&gt;3000&lt;/span&gt; &lt;span style="color:#75715e"&gt;# ポート番号&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで、&lt;code&gt;xxxxxxx.ngrok.com&lt;/code&gt;みたいなURLが発行されます。このURLにアクセスするとローカルマシンの3000番ポートにリクエストが飛んできます。&lt;/p&gt;
&lt;p&gt;ではこれができると何が嬉しいか。僕は主に2つのユースケースで使ってします。&lt;/p&gt;
&lt;h2 id="アプリ開発"&gt;アプリ開発&lt;/h2&gt;
&lt;p&gt;Webサービスのスマートフォンクライアント開発をするとき、ローカルのサーバーでAPIを開発しつつアプリ側を開発することがまあよくあります。&lt;/p&gt;
&lt;p&gt;この場合アプリはサーバーありきのため、アプリからサーバーへWebのリクエストが飛びます。大抵の場合はシミュレータから(localhost:3000）とかにアクセスすれば事足りますが、写真撮影してアップロード、みたいなことをやろうとすると、(iOS)では実機を使って動作させるしかありません。&lt;/p&gt;
&lt;p&gt;そのようなとき、例えばRailsならpuma-devなどを利用してxip.ioドメインで実機から開発機にアクセスすることは可能です。ですが、ちょとした拍子に名前解決ができなくなってしまい、サーバーの再起動などを頻繁にすることになります。&lt;/p&gt;
&lt;p&gt;その点、ngrokを使えば名前解決のあたりが安定します。インターネットを経由する分少し遅くなりますが、限定的な用途だと考えれば受け入れられる程度で、メリットのほうが大きい気がしています。&lt;/p&gt;
&lt;p&gt;また、iOSの場合はATSにより&lt;code&gt;https&lt;/code&gt;を使わないといけないなど、証明書周りで面倒なことがありがちですが、ngrokでは回避できるはず。多少遅いことを受け入れられるケースであれば使うと◎です。&lt;/p&gt;
&lt;h2 id="外部サービス連携"&gt;外部サービス連携&lt;/h2&gt;
&lt;p&gt;外部のサービスから定期的にリクエストを受け付ける、みたいな機能を作ろうとすると、外部のサービスが投げるリクエストを受け取る必要があります。&lt;/p&gt;
&lt;p&gt;例えばGitHubでは、リポジトリのWebhooksにURLを登録しておくと、コミット時やプルリクエスト作成時などのイベントが起こったときに、その内容などなどを登録したURLにPOSTで投げつけてくれます。&lt;/p&gt;
&lt;p&gt;そして、そのURLは外部に公開されている必要があります。GitHubに&lt;code&gt;https://localhost:3000/github&lt;/code&gt;みたいなURLを登録したところで、自分の開発機にはリクエストは飛んできません。&lt;/p&gt;
&lt;p&gt;そこでngrokです。ngrokで発行したURLをwebhookとして登録しておけば、開発機に連携サービスからのリクエストが飛んでくるというわけです。URLには有効期限があり（8時間）、それをすぎると使えません。&lt;/p&gt;
&lt;p&gt;お金を払うとサブドメインの部分を固定にしたり任意の文字列に設定したりとできるらしいので、人によっては払う価値が出てくるのではないかと思われます。&lt;/p&gt;</description></item><item><title>Railsでファイル関連のバリデーションをする</title><link>https://blog.piyo.tech/posts/2018-06-06-rails-file-validators/</link><pubDate>Wed, 06 Jun 2018 06:35:30 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-06-rails-file-validators/</guid><description>&lt;p&gt;アップロードファイルのサイズやcontent_typeなど、制限する場合があると思います。標準のvalidatorでは足りないので、自前で書いたり、&lt;code&gt;carrierwave&lt;/code&gt;なんかであればuploaderに制限を書いたりします。&lt;/p&gt;
&lt;p&gt;モデルでファイル関連の&lt;code&gt;validator&lt;/code&gt;を使えるようになる&lt;code&gt;file_validators&lt;/code&gt;というのがあるので、簡単に紹介。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/musaffa/file_validators" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/0af94103d68eab30cc625b2fbe693cb24b659004ca91d972dbfef92393e397bb/musaffa/file_validators" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - musaffa/file_validators: Adds file validators to ActiveModel.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Adds file validators to ActiveModel. Contribute to musaffa/file_validators development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;百聞は一見にしかずだと思うので、サンプルコードを紹介。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Profile&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; validates &lt;span style="color:#e6db74"&gt;:avatar&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;file_size&lt;/span&gt;: { &lt;span style="color:#e6db74"&gt;less_than_or_equal_to&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;kilobytes },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;file_content_type&lt;/span&gt;: { &lt;span style="color:#e6db74"&gt;allow&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;image/jpeg&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;image/png&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;file_size&lt;/code&gt;や&lt;code&gt;file_content_type&lt;/code&gt;といったバリデーションができるようになっています。&lt;/p&gt;
&lt;p&gt;これによって指定のサイズ以上は受け付けないとか、変なファイルを受け付けないとかの制御ができます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;file_content_type&lt;/code&gt;については正規表現の指定も可能で、↓のように書くと画像全般を許可できそうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;validates &lt;span style="color:#e6db74"&gt;:avatar&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;file_content_type&lt;/span&gt;: { &lt;span style="color:#e6db74"&gt;allow&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;/^image\/.*/&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;エラーメッセージのi18nにも対応しているようなので実用性はありそうだし、細々とだけどメンテもされているみたいなので使ってみても良さそうという感じです。&lt;/p&gt;</description></item><item><title>rspec-parameterizedで条件だけが異なるテストコードをDRYに書く</title><link>https://blog.piyo.tech/posts/2018-06-04-rspec-parameterized/</link><pubDate>Mon, 04 Jun 2018 06:27:50 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-04-rspec-parameterized/</guid><description>&lt;p&gt;テストのロジックは同じだけど、入力値とそれに対する結果が異なるみたいなテストをシンプルにかける&lt;code&gt;rspec-parametrized&lt;/code&gt;というgemがあります。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/tomykaira/rspec-parameterized" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/a657e109d713727d8432238ccab9e00536d8d13a26639975582b6bde2e5dccab/tomykaira/rspec-parameterized" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - tomykaira/rspec-parameterized: RSpec::Parameterized supports simple parameterized test syntax in rspec.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;RSpec::Parameterized supports simple parameterized test syntax in rspec. - tomykaira/rspec-parameterized&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;存在は知ってたけどしばらく使ってなかったんですが、試しに入れてみたらすごくシンプルに使えるし、パラメータ変えてテストできるようなメソッドにしようみたいな意識がより働いてコードに良い影響もありそうな気がしています。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;where&lt;/code&gt;と&lt;code&gt;with_them&lt;/code&gt;を使ってテストを書いていきます。↓はREADMEのサンプルの一部でして、&lt;code&gt;where&lt;/code&gt;に値の組み合わせ、&lt;code&gt;with_them&lt;/code&gt;にテストコード自体を書く使い方をします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;describe &lt;span style="color:#e6db74"&gt;&amp;#34;plus&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; where(&lt;span style="color:#e6db74"&gt;:a&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:b&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:answer&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; , &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; , &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; , &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; , &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; , &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; , &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; with_them &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; it &lt;span style="color:#e6db74"&gt;&amp;#34;should do additions&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; expect(a &lt;span style="color:#f92672"&gt;+&lt;/span&gt; b)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to eq answer
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑の例だと、&lt;code&gt;a&lt;/code&gt;,&lt;code&gt;b&lt;/code&gt;,&lt;code&gt;answer&lt;/code&gt;という3つのパラメータにセットする値をArrayのArrayで渡しています。すると、&lt;code&gt;with_them&lt;/code&gt;に書いたテストが以下の3つの条件で実行されるというわけです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;a=1, b=2, answer=3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a=5, b=8, answer=13&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a=0, b=0, answer=0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;where&lt;/code&gt;の書き方には↑のようなArrayのパターンやHashを使ったパターン、さらに独自のテーブル記法を使うこともできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;using &lt;span style="color:#66d9ef"&gt;RSpec&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Parameterized&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;TableSyntax&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;where(&lt;span style="color:#e6db74"&gt;:a&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:b&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:answer&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;直感的っちゃ直感的ですが、&lt;code&gt;using RSpec::Parameterized::TableSyntax&lt;/code&gt;しないと使えなくてひと手間かかるとも言えるので、この辺は好みですね。&lt;/p&gt;
&lt;p&gt;ということで、パラメータのみが変わるテストは&lt;code&gt;rspec-parameterized&lt;/code&gt;でDRYにして、入出力の条件にフォーカスして必要なテストをかけるようにしましょー。&lt;/p&gt;</description></item><item><title>Rubyでフリーメールの判定をするfreemail gem</title><link>https://blog.piyo.tech/posts/2018-06-03-freemail-gem/</link><pubDate>Sun, 03 Jun 2018 06:39:31 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-03-freemail-gem/</guid><description>&lt;p&gt;フリーメールで登録できないようにしたい、という要望に答えるために&lt;code&gt;freemail&lt;/code&gt;というgemを使いました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/smudge/freemail" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/607f75891c6c203afe76e4b0a204d2d83aeb5388c81abc7100bf1119ac59702d/smudge/freemail" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - smudge/freemail: A ruby implementation of the npm &amp;#39;freemail&amp;#39; database of free and disposable email domains.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;A ruby implementation of the npm &amp;#39;freemail&amp;#39; database of free and disposable email domains. - smudge/freemail&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;このgemはフリーメールのリストを管理していて、該当するかメールアドレスかどうかを判定してくれます。ある程度のリストが最初からあって自分で用意する必要がないというのが良いところです。&lt;/p&gt;
&lt;p&gt;使い方は簡単で、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;freemail&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Freemail&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;free?(&lt;span style="color:#e6db74"&gt;&amp;#39;hogehogehoge@gmail.com&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;みたいな使い方をします。&lt;code&gt;free?&lt;/code&gt;のほかに&lt;code&gt;disposable?&lt;/code&gt;という使い捨てアドレスの判定もできます。が、用途としてはちゃんとしたアドレスであるかどうかを知りたいことが多いはずなので、&lt;code&gt;free_or_disposable?&lt;/code&gt;を使うのが良いかと思われます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;freemail&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Freemail&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;free_or_disposable?(&lt;span style="color:#e6db74"&gt;&amp;#39;hogehogehoge@gmail.com&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;さて、このgemのリストには日本国内のフリーメールなんかは入っていません。とはいえいちいち除外したいドメインをメインのリストに追加してもらうようにプルリクしたりフォークしたりするのはイマイチだなと思い、対象のフリーメールを追加できるようなAPIを用意してプルリクを出し、取り込んでもらいました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/smudge/freemail/pull/11" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/2251dd22f569129f717ca0bf9e9be64b3c75cbaa2f642b6339e2db22e01908bd/smudge/freemail/pull/11" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;API for adding domains by pi-chan · Pull Request #11 · smudge/freemail&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;new version of #10, keep Hash implementation.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;（ちゃんとテスト書いてて去年の俺えらい）&lt;/p&gt;
&lt;p&gt;これによって、&lt;code&gt;free_or_disposable?&lt;/code&gt;の判定の前に&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Freemail&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_free_domains &lt;span style="color:#e6db74"&gt;%w(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;yahoo.co.jp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;outlook.jp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;hotmail.co.jp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;live.jp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;excite.co.jp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;みたいなことをしておけば、国内のフリーメールも除外対象にできるというわけです。これを使っているRailsアプリケーションでは、initializerでこの追加処理を書いています。&lt;/p&gt;</description></item><item><title>Railsでメールにプレフィックスつけるgem email_prefixer</title><link>https://blog.piyo.tech/posts/2018-06-02-rails-email-prefixer/</link><pubDate>Sat, 02 Jun 2018 06:59:23 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-02-rails-email-prefixer/</guid><description>&lt;p&gt;メール送るときにプレフィックスつけたいときあるじゃないですか。サービス名だったり、ステージング用でテストするためのメールだったり。&lt;/p&gt;
&lt;p&gt;で、1個1個subjectに設定するのは面倒だし忘れてしまいがちなので、&lt;code&gt;email_prefixer&lt;/code&gt;を使っています。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/wireframe/email_prefixer" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/14ea92be9f9aac2ab371586c31880e6752ca6407cac34715891b82c163616bc3/wireframe/email_prefixer" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - wireframe/email_prefixer&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Contribute to wireframe/email_prefixer development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Railsへの導入はgemの追加とinitializersへの設定ファイルの追加です。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;config/intitializers/email_prefixer.rb&lt;/code&gt;的なファイルを作って、必要な設定を書いておきます。&lt;/p&gt;
&lt;p&gt;たとえばこんな感じで、envごとにプレフィックスを変えて送れます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;EmailPrefixer&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;configure &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;config&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;env&lt;span style="color:#f92672"&gt;.&lt;/span&gt;production? &lt;span style="color:#f92672"&gt;or&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;env&lt;span style="color:#f92672"&gt;.&lt;/span&gt;test?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;builder &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; { &lt;span style="color:#e6db74"&gt;&amp;#39;【サービス名】&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elsif&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;env&lt;span style="color:#f92672"&gt;.&lt;/span&gt;staging?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;builder &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; { &lt;span style="color:#e6db74"&gt;&amp;#39;【staging】&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elsif&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;env&lt;span style="color:#f92672"&gt;.&lt;/span&gt;development?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;builder &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; { &lt;span style="color:#e6db74"&gt;&amp;#39;【development】&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;メールを送る側は例えばこんな感じ（↓）になると思います。subjectにはプレフィックス以外の部分を指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;invited&lt;/span&gt;(user)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; @user &lt;span style="color:#f92672"&gt;=&lt;/span&gt; user
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; mail &lt;span style="color:#e6db74"&gt;to&lt;/span&gt;: @user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;email, &lt;span style="color:#e6db74"&gt;subject&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;招待されました&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際に送られるメールのタイトルは環境によって&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;【サービス名】招待されました&lt;/li&gt;
&lt;li&gt;【staging】招待されました&lt;/li&gt;
&lt;li&gt;【development】招待されました&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;みたいな感じで勝手に分かれてくれます。プレフィックスをつけたいだけの場合（環境毎に区別しない場合）でも一箇所でDRYにできるので便利です。&lt;/p&gt;
&lt;p&gt;仕組み的にはActionMailerが提供するフック、&lt;code&gt;ActionMailer::Base.register_interceptor&lt;/code&gt;を使って、プレフィックスをつける処理を差し込むだけで割とシンプルな実装です。&lt;/p&gt;
&lt;p&gt;Railsガイドにも載っています。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://railsguides.jp/action_mailer_basics.html" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://railsguides.jp/images/cover_for_facebook.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Action Mailer の基礎 - Railsガイド&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Action Mailerを使ってメールを送受信する方法について解説します。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://railsguides.jp/railsguides/images/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;railsguides.jp&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;これを使えばpostfixerも作れますね。要らないけどね。&lt;/p&gt;</description></item><item><title>Macのおやすみモードをショートカットで切り替える</title><link>https://blog.piyo.tech/posts/2018-06-01-do-not-disturb/</link><pubDate>Fri, 01 Jun 2018 06:45:08 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-06-01-do-not-disturb/</guid><description>&lt;p&gt;リモートミーティングで画面共有中にうっかり通知が見えてしまわないようにおやすみモードを使うようにしています。けど、この切り替えがマウスで面倒です。&lt;/p&gt;
&lt;p&gt;通常はメニューバー右上の通知センターを開いて、少し上にスクロールすると出現するおやすみモードをオンに切り替えることで有効になります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/nNpJdNFXz_R1gLJASL4BJO-eLNOp8gd_DasWJe7-jVT96v9LjVCJjgLG1rr4duZ9blfQ3znfqoT2rxA3jAxltqvkIrCNdPa2uTawAfxd2G69nR8SEAjJc55y_QdQpJXy7NSvgo7VVchN5V5MLT6ykc8luBEc7e39NUM2Z3WzXSNph8gEaM2s-IeQPeE08Zaxv7SHyE0Rw3BME4DSLb7wrvelIng-qZJSoQnSIUUk4_yRrkQUPZHenupPrpDgNGc1gqtYKrj3QWuYfrlzXgPnGfw2VqPY7tvmE2vCxp0yKFBdWSlE705aF9YuUPu4Zivv0t77npWbhYxYCjTK7Qw00FUXt0YufxfEw7e_zByApGX7NAL4YrbVU43lYHX7MI1WDhV3X6xocyIGoEvzJOi3oDbmrG9hfGbZH8wwQscsgze-zfpwIRL72bfsMo9quvdKjYXQwAEib49RstRQTbFJF3W9qvna_sWMrKVHjapXOUcSSfhFnbAVUm1yMWajsV4wI3YOUYI4dDrBrVK3JU9-Cfzy1nTSH4CYAf7U44ZybaUTqmouOdMFVyas3q5E85kQT-7DzsgnR1TVK4K1GSbvbxg65J9YwNxEDNcSvCbs-gT24fri4y8UdaNTObnBW00trAums_Cslf_avEjReLdi3HASPYaFVNnh=w347-h185-no"&gt;&lt;img src="https://lh3.googleusercontent.com/nNpJdNFXz_R1gLJASL4BJO-eLNOp8gd_DasWJe7-jVT96v9LjVCJjgLG1rr4duZ9blfQ3znfqoT2rxA3jAxltqvkIrCNdPa2uTawAfxd2G69nR8SEAjJc55y_QdQpJXy7NSvgo7VVchN5V5MLT6ykc8luBEc7e39NUM2Z3WzXSNph8gEaM2s-IeQPeE08Zaxv7SHyE0Rw3BME4DSLb7wrvelIng-qZJSoQnSIUUk4_yRrkQUPZHenupPrpDgNGc1gqtYKrj3QWuYfrlzXgPnGfw2VqPY7tvmE2vCxp0yKFBdWSlE705aF9YuUPu4Zivv0t77npWbhYxYCjTK7Qw00FUXt0YufxfEw7e_zByApGX7NAL4YrbVU43lYHX7MI1WDhV3X6xocyIGoEvzJOi3oDbmrG9hfGbZH8wwQscsgze-zfpwIRL72bfsMo9quvdKjYXQwAEib49RstRQTbFJF3W9qvna_sWMrKVHjapXOUcSSfhFnbAVUm1yMWajsV4wI3YOUYI4dDrBrVK3JU9-Cfzy1nTSH4CYAf7U44ZybaUTqmouOdMFVyas3q5E85kQT-7DzsgnR1TVK4K1GSbvbxg65J9YwNxEDNcSvCbs-gT24fri4y8UdaNTObnBW00trAums_Cslf_avEjReLdi3HASPYaFVNnh=w347-h185-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;さらに簡単に切り替える方法としては、Macのoptionキーを押しながら通知センターを開くアイコンをクリック、というのがあります。これするとパネルを開かなくてもオンオフできます。&lt;/p&gt;
&lt;p&gt;でも、マウスすら面倒なのでキーボードで切り替えたいじゃないですか。ちゃんと設定できるようになってました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/ZHzRqbwaSQobUFYVW1wdQLPMTA083kT3V1jOIy8PaSQwBnSL-i2QJeOO_xv3Kv5BycpzucgQ1xZWTQRIhT-5TSxwLkHLfES8DHlNh7lhyqZ2FhAIhTDF-3shLBbNC_Lrb4F7m4gqwedUEyJpAVMsbGGuZoyGnsr0gwDkpmBnBGmqfeoWeEZM3Mr5yLrcPF3MnWGgWFzTim9ItXocnUT5bdzLaUCrG6PNl0Im-BSXnWmtUbwT_eAIXULvtfDlUzLITxDakYJjtrJXIwq0VVPWnq-bUNF3EV3mNSK2pXIbQp6eY5tk_PTRd5pt1JGlBC4jLj_0Fde6bvLX70V7GU5JqFR_FS6Lqd2ZopCYrbqi8vvefvwkyd9UgDhjviz8frdFRYofg2vgg11cE_KZOcbqDvk41pjZrSp1HjpT-JNAtUwr1xM7b8GMAKUpACCbxRm0fgTvWqJ6CKFxRzZQy_fzd-e_HFAjpyV-ppvrun4y9PlEaYL0CxSZeRPUkqTesSpUTvvf33A1uVaYmRZy3NVy0eb0H3N4zgjttQEewkDwxZaZhw8JLej0S_OcEfcNYK6Mp8WWAuGohcbouKlpTTYuFc30yH5q9v1FbYnoIbKrZKzf1Ck2a0jshg2IpVJmlW0NwomTyOgAWpyAzXokq1GFdwwCq3fkIaos=w780-h727-no"&gt;&lt;img src="https://lh3.googleusercontent.com/ZHzRqbwaSQobUFYVW1wdQLPMTA083kT3V1jOIy8PaSQwBnSL-i2QJeOO_xv3Kv5BycpzucgQ1xZWTQRIhT-5TSxwLkHLfES8DHlNh7lhyqZ2FhAIhTDF-3shLBbNC_Lrb4F7m4gqwedUEyJpAVMsbGGuZoyGnsr0gwDkpmBnBGmqfeoWeEZM3Mr5yLrcPF3MnWGgWFzTim9ItXocnUT5bdzLaUCrG6PNl0Im-BSXnWmtUbwT_eAIXULvtfDlUzLITxDakYJjtrJXIwq0VVPWnq-bUNF3EV3mNSK2pXIbQp6eY5tk_PTRd5pt1JGlBC4jLj_0Fde6bvLX70V7GU5JqFR_FS6Lqd2ZopCYrbqi8vvefvwkyd9UgDhjviz8frdFRYofg2vgg11cE_KZOcbqDvk41pjZrSp1HjpT-JNAtUwr1xM7b8GMAKUpACCbxRm0fgTvWqJ6CKFxRzZQy_fzd-e_HFAjpyV-ppvrun4y9PlEaYL0CxSZeRPUkqTesSpUTvvf33A1uVaYmRZy3NVy0eb0H3N4zgjttQEewkDwxZaZhw8JLej0S_OcEfcNYK6Mp8WWAuGohcbouKlpTTYuFc30yH5q9v1FbYnoIbKrZKzf1Ck2a0jshg2IpVJmlW0NwomTyOgAWpyAzXokq1GFdwwCq3fkIaos=w780-h727-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;設定→キーボード→ショートカットからMission Controlの「おやすみモードをオン/オフ」を有効にして好きなキーを割当てればOKです。&lt;/p&gt;
&lt;p&gt;ただ、これだと今どっちの状態にいるのかわからないんですよね。メニューバーにアイコンでも出せるといいんですが。。。&lt;/p&gt;</description></item><item><title>RailsでMarkdownのテキストをHTMLに変換する</title><link>https://blog.piyo.tech/posts/2018-05-31-markdown-gem/</link><pubDate>Thu, 31 May 2018 06:14:55 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-31-markdown-gem/</guid><description>&lt;p&gt;RailsでさくっとMarkdown対応する方法を紹介します。&lt;/p&gt;
&lt;p&gt;マークダウン形式で書かれたテキストをHTMLに変換する機能を提供するgemが大きく2つあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/vmg/redcarpet"&gt;redcarpet&lt;/a&gt; ★4222&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gjtorikian/commonmarker"&gt;commonmarker&lt;/a&gt; ★137&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;（★は2018/05/31時点）&lt;/p&gt;
&lt;p&gt;redcarpetは僕も以前から使っていて、オプションが豊富でがんばればいろんなことができる、大きめのライブラリという印象です。（GitHubでも使われてるんでしたっけ？適当なこと言ったらいけないか）&lt;/p&gt;
&lt;p&gt;で、もう一個のcommonmarkerはCommonMarkというMarkdownに対応するためのライブラリです。あるプロジェクトでredcarpetで3重にネストした箇条書きを上手く処理できなくて困ってたところに、コレに出会ってうまくいったのでこっちを採用しています。&lt;/p&gt;
&lt;p&gt;CommonMarkは仕様を明確にしたMarkdownという感じの存在です。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="http://commonmark.org/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;CommonMark&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="http://commonmark.org/images/markdown-mark-apple-touch.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;commonmark.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;redcarpet gemのコードを書いている人も参加しているみたい。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Redcarpet was written by Vicent Martí.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;のところ、および、CommonMarkのサイトの Who are you?のところの&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Vicent Marti, &lt;a href="mailto:vicent@github.com"&gt;vicent@github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;が同一人物のようですね。&lt;/p&gt;
&lt;h1 id="example"&gt;example&lt;/h1&gt;
&lt;p&gt;凝ったことをやらないのであればcommonmarkerでサクッと作ってもいいのでは？と思い最小限のRailsのサンプルを紹介します。&lt;/p&gt;
&lt;p&gt;commonmarker gemのREADMEの冒頭部分を例としてHTMLにしてみます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/gjtorikian/commonmarker/blob/master/README.md"&gt;commonmarker/README.md at master · gjtorikian/commonmarker&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;# CommonMarker
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;[&lt;span style="color:#f92672"&gt;![Build Status&lt;/span&gt;](&lt;span style="color:#a6e22e"&gt;https://travis-ci.org/gjtorikian/commonmarker.svg&lt;/span&gt;)](https://travis-ci.org/gjtorikian/commonmarker) [&lt;span style="color:#f92672"&gt;![Gem Version&lt;/span&gt;](&lt;span style="color:#a6e22e"&gt;https://badge.fury.io/rb/commonmarker.svg&lt;/span&gt;)](http://badge.fury.io/rb/commonmarker)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;Ruby wrapper for [&lt;span style="color:#f92672"&gt;libcmark-gfm&lt;/span&gt;](&lt;span style="color:#a6e22e"&gt;https://github.com/github/cmark&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;GitHub&amp;#39;s fork of the reference parser for CommonMark. It passes all of the C tests, and is therefore spec-complete. It also includes extensions to the CommonMark spec as documented in the [&lt;span style="color:#f92672"&gt;GitHub Flavored Markdown spec&lt;/span&gt;](&lt;span style="color:#a6e22e"&gt;http://github.github.com/gfm/&lt;/span&gt;), such as support for tables, strikethroughs, and autolinking.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;For more information on available extensions, see [&lt;span style="color:#f92672"&gt;the documentation below&lt;/span&gt;](&lt;span style="color:#a6e22e"&gt;#extensions&lt;/span&gt;).
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## Installation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;Add this line to your application&amp;#39;s Gemfile:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; gem &amp;#39;commonmarker&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;And then execute:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; $ bundle
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;Or install it yourself as:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; $ gem install commonmarker
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## Usage
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### Converting to HTML
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;Call &lt;span style="color:#e6db74"&gt;`render_html`&lt;/span&gt; on a string to convert it to HTML:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;導入は↑に書いてあるとおり、Gemfileに書いて&lt;code&gt;bundle install&lt;/code&gt; だけでOKです。ビューで毎度commonmarkerを呼ぶのは面倒なので、僕は大体ヘルパーにしておいて使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;module&lt;/span&gt; ApplicationHelper
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;md2html&lt;/span&gt;(text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; html &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;CommonMarker&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;render_html(text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; raw(html)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとはビューでこのヘルパーのメソッドにMarkdown形式のテキストを入れるだけです。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-erb" data-lang="erb"&gt;&amp;lt;% text = &amp;#34;#{↑のマークダウン}&amp;#34; %&amp;gt;
&amp;lt;%= md2html(text) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;レンダリング結果が↓です。いい感じです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/wkP82d26m0S6OZYnihQj4hwDsHFX90oW9himMhXolJnrr3CYBVaQTSLdk-9WFmqRR0q8sN6V4zmDjPBDBBEWsFv1LSGpbB1FDa0BuXtTAhVB5TlWN8p403ks91vsP9zyMrh2h-fn9iuAa_4kn3HGc7pibIgz2T48g592zXJ62p8oRvEbUjGUu_C4ZfcsGBKl0_QVjPLsh8zA9c0v4hnHja93jUbYYsayh-18jvvYrqwwPz3IhjLHXLyJtYETJXMTlUzU8gpM9hTKzUf_gFw92B8fvozcE8zNn9uTAV5G58MhVd0ouUpTiTU56z0MfU1FMA6Jdi0tXEckUmRG3NNRXPtiNPCQiQx100X9CxpVnzSglC-zmA5V8bfUZxBc8OzNmLOBlefSwRms45nqHvy259aj_l-Znr1WrE63zq94i3H_nQ5gJzfzXjP2XbB-F0t83nECmL0jJNWdeu7jXdLlmkRFTqplIDwHPK2ZYm6tgh8SjHJRxBdiyFU3QhT1b98YJaAY4UicjvTvwxqfcCQaMzqYA8t9wPWZ1mtKY5vXxH8rQwvcWXJa64InfK86ETN8sYZcNhBYw2AZR4bMm8z9l0qnkqMWFQIHA8zcEyvMOzYGXC-eIZzk5Qc_fmh2NhIglZgYj8rWw6NP3utFpAaANIYsfeMjM5FZ"&gt;&lt;img src="https://lh3.googleusercontent.com/wkP82d26m0S6OZYnihQj4hwDsHFX90oW9himMhXolJnrr3CYBVaQTSLdk-9WFmqRR0q8sN6V4zmDjPBDBBEWsFv1LSGpbB1FDa0BuXtTAhVB5TlWN8p403ks91vsP9zyMrh2h-fn9iuAa_4kn3HGc7pibIgz2T48g592zXJ62p8oRvEbUjGUu_C4ZfcsGBKl0_QVjPLsh8zA9c0v4hnHja93jUbYYsayh-18jvvYrqwwPz3IhjLHXLyJtYETJXMTlUzU8gpM9hTKzUf_gFw92B8fvozcE8zNn9uTAV5G58MhVd0ouUpTiTU56z0MfU1FMA6Jdi0tXEckUmRG3NNRXPtiNPCQiQx100X9CxpVnzSglC-zmA5V8bfUZxBc8OzNmLOBlefSwRms45nqHvy259aj_l-Znr1WrE63zq94i3H_nQ5gJzfzXjP2XbB-F0t83nECmL0jJNWdeu7jXdLlmkRFTqplIDwHPK2ZYm6tgh8SjHJRxBdiyFU3QhT1b98YJaAY4UicjvTvwxqfcCQaMzqYA8t9wPWZ1mtKY5vXxH8rQwvcWXJa64InfK86ETN8sYZcNhBYw2AZR4bMm8z9l0qnkqMWFQIHA8zcEyvMOzYGXC-eIZzk5Qc_fmh2NhIglZgYj8rWw6NP3utFpAaANIYsfeMjM5FZ" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Capybaraのフィーチャテストで自動的にスクリーンショットを撮るgem</title><link>https://blog.piyo.tech/posts/2018-05-30-auto-screenshot-on-capybara-failure/</link><pubDate>Wed, 30 May 2018 06:26:06 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-30-auto-screenshot-on-capybara-failure/</guid><description>&lt;p&gt;テスト失敗時のスクショ撮りをRSpec + Capybaraで設定ほぼ不要でおまかせできたので紹介します。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/mattheworiordan/capybara-screenshot" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/158345156ee67b43cad14418dedfe491dba8bc538d57bae4f550afecb6afbc71/mattheworiordan/capybara-screenshot" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - mattheworiordan/capybara-screenshot: Automatically save screen shots when a Capybara scenario fails&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Automatically save screen shots when a Capybara scenario fails - mattheworiordan/capybara-screenshot&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Gemfile&lt;/code&gt;に↓を書いて&lt;code&gt;bundle install&lt;/code&gt;し、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;group &lt;span style="color:#e6db74"&gt;:test&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;capybara-screenshot&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;rails_helper.rb&lt;/code&gt;あたりに↓の記述を入れておけばOK&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;capybara-screenshot/rspec&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際には↓の箇所でテスト後のコールバックを登録してあって、内部で失敗かどうかを判定して&lt;code&gt;tmp/capybara/&lt;/code&gt;以下にhtmlとpngを保存してくれるようになっています。自動的にタイムスタンプとかもつけてくれます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mattheworiordan/capybara-screenshot/blob/master/lib/capybara-screenshot/rspec.rb#L93"&gt;capybara-screenshot/rspec.rb#L93&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;スクリーンショットは&lt;code&gt;save_screenshot&lt;/code&gt;でも取れるので、同じようなことを自分書いても大したことないコード量で済みますが、さくっと導入する分には便利なのでこっち使っちゃうほうが好きです。&lt;/p&gt;</description></item><item><title>「小さな習慣」という本のうろ覚え感想</title><link>https://blog.piyo.tech/posts/2018-05-25-mini-habits/</link><pubDate>Fri, 25 May 2018 06:53:37 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-25-mini-habits/</guid><description>&lt;p&gt;やる気なんてものはなくて、行動すれば自然とやる気になるんだよというような話の記事を読みました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://r25.jp/article/540681193689662300" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://img.neirong.plus/o/4a/32/4a3245894b5140e8b245894b5190e8c8.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;「簡単にやる気を出す方法を教えてください！」→脳研究者「やる気なんて存在しない」｜新R25 Media - シゴトも人生も、もっと楽しもう。&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;“やる気が出ない”全ビジネスマン必見!?&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://r25.jp/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;r25.jp&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;この記事を読んだときに、「小さな習慣」という本を読んだことを思い出しました。本を読んだのは年始なのでだいぶうろ覚え感ありますが、「小さな習慣」についてざっくり思い出すと、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;モチベーションなんて不確実なものに頼ってたらやりたいこと達成できない&lt;/li&gt;
&lt;li&gt;モチベーションはやり始めれば出てくる&lt;/li&gt;
&lt;li&gt;いかに低負荷で始めるかが肝心&lt;/li&gt;
&lt;li&gt;→超簡単でがんばらなくてもできることだけを毎日続けよう&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;というものだったはず。&lt;/p&gt;
&lt;p&gt;習慣にしたいと思っている行動を最も小さくしたものを「小さな習慣」と読んでいて、例えば、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;筋トレを続けたいなら1回の腕立て伏せ&lt;/li&gt;
&lt;li&gt;本を書きたいなら1日50word書く&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;のようなことです。&lt;/p&gt;
&lt;p&gt;個人的にはポイントは2つあると思っていて、&lt;/p&gt;
&lt;p&gt;1つは先ほど紹介したリンクにもあるように「やる気」は行動すると出てくる、つまり小さな習慣の行動をすると案外続けてやりたくなってくるというものです。気が進まなかったけど、ちょっとやり始めたら案外進んだみたいなやつです。&lt;/p&gt;
&lt;p&gt;もう1つは、小さな習慣でも続けていくうちに脳が慣れていくことで自然と少しつづ行動を大きくしていけることではないかなと思います。これも紹介したリンクで歯磨きが例示されいた歯磨きと似ています。面倒でも歯磨きは毎日続くのは、脳の働きが関係しているようです。&lt;/p&gt;
&lt;p&gt;脳科学を交えてちゃんと説明してくれてるのでもう1回詳しく読んだほうがいいな。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B072B8S2YN/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/71BYOaHR&amp;#43;CL._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;小さな習慣&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>rails generate migrationにdecimalのオプションを渡す</title><link>https://blog.piyo.tech/posts/2018-05-24-migration-decimal/</link><pubDate>Thu, 24 May 2018 06:01:04 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-24-migration-decimal/</guid><description>&lt;p&gt;小ネタです。&lt;/p&gt;
&lt;p&gt;decimalのカラムを追加するときに&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rb" data-lang="rb"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;add_column &lt;span style="color:#e6db74"&gt;:items&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:new_column&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:decimal&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;precision&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;scale&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とかってやると思うんですけど、これをgeneratorのコマンドに渡せないかな？と思って調べました。&lt;/p&gt;
&lt;p&gt;コマンドに渡すっていうのはこういうのです。&lt;/p&gt;
&lt;p&gt;（以下、NewColumnとかnew_columnは適当に読み替えてください）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% rails g migration AddNewColumnToItems new_column:string
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;decimalの場合は &lt;code&gt;new_column:decimal{precision,scale}&lt;/code&gt; でいけます。&lt;/p&gt;
&lt;p&gt;たとえば、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% rails g migration AddNewColumnToItems &lt;span style="color:#e6db74"&gt;&amp;#34;new_column:decimal{3,2}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;クオートつけないと、&lt;code&gt;{3,2}&lt;/code&gt;の部分がシェルに評価されてしまうのでクオート必須です。&lt;/p&gt;</description></item><item><title>HugoにPV順の記事リストを配置する</title><link>https://blog.piyo.tech/posts/2018-05-23-popular-entries/</link><pubDate>Wed, 23 May 2018 05:53:55 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-23-popular-entries/</guid><description>&lt;p&gt;HugoのPV順の記事リストを作ってみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/BfQGAlM2yanltozxP0N8i5tCAhJAJiI6uQHPASVRDW1S9sZmHVgA6HcE4jyN8pJ76ZZdrK97eGqEioDwKzPODuyJAcW1WJvVXxrDWa29BTaWmEgDpNa7RBaodhOrXqMdd7Em71VsbJ905vyC60BKkSbmXSuuqdCn6ALnNcb15-XUwkxAn_IG61GKCYGEp6QKuJ08rNW3OteMd1Rt2JhgElvXkQQjtVIdzimDR_mHIqexJ4oQBEmDOsEPgDJ4K3SZDMxDAvO5r2KLWEyUtSy_jPrzzTZe3Nm-HLsYQ3IWiqevgBy2Lo3PlXg-qfhssEFHVye0rgJ_5NS0xc5pTG8PQNKLrYJkHa5i-BZvKZskodxMgQuUAy5LMI_d_4511sCCZ4JopRQfK2adev8XRnCjeCf4oauNlUAqMJu02U9pIJFJaKuhTwXFuhIrCPCB42htKB_8LosSb_VKdP5oaO8BbR_sdLHWLMjB8qu9FMvRac5Jrqv3Crr-IBAaGy-xPKe1D7R4DtGElwfHNbZtAEVP3Aun376RnzSST-bxXpo5alBBZ7MBQ3EnnCzJln-uknoq2RLjJvVKapRxlm9b_lUZzs1ejYINtXqHOtwO5mjVxEGnA9TQBJ6xa0IJm3746Y9Pk5dADxnT9GNJXwPj7eo_tf_oZjEPtZuI=w415-h551-no"&gt;&lt;img src="https://lh3.googleusercontent.com/BfQGAlM2yanltozxP0N8i5tCAhJAJiI6uQHPASVRDW1S9sZmHVgA6HcE4jyN8pJ76ZZdrK97eGqEioDwKzPODuyJAcW1WJvVXxrDWa29BTaWmEgDpNa7RBaodhOrXqMdd7Em71VsbJ905vyC60BKkSbmXSuuqdCn6ALnNcb15-XUwkxAn_IG61GKCYGEp6QKuJ08rNW3OteMd1Rt2JhgElvXkQQjtVIdzimDR_mHIqexJ4oQBEmDOsEPgDJ4K3SZDMxDAvO5r2KLWEyUtSy_jPrzzTZe3Nm-HLsYQ3IWiqevgBy2Lo3PlXg-qfhssEFHVye0rgJ_5NS0xc5pTG8PQNKLrYJkHa5i-BZvKZskodxMgQuUAy5LMI_d_4511sCCZ4JopRQfK2adev8XRnCjeCf4oauNlUAqMJu02U9pIJFJaKuhTwXFuhIrCPCB42htKB_8LosSb_VKdP5oaO8BbR_sdLHWLMjB8qu9FMvRac5Jrqv3Crr-IBAaGy-xPKe1D7R4DtGElwfHNbZtAEVP3Aun376RnzSST-bxXpo5alBBZ7MBQ3EnnCzJln-uknoq2RLjJvVKapRxlm9b_lUZzs1ejYINtXqHOtwO5mjVxEGnA9TQBJ6xa0IJm3746Y9Pk5dADxnT9GNJXwPj7eo_tf_oZjEPtZuI=w415-h551-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Google Analyticsのpageview情報を利用していて、サイトビルド時にデータを取得するためのAPIはGo言語を使って自前で作りました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-05-22-analytics-api-via-echo/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://goo.gl/NSXeuF" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Go lang &amp;#43; EchoでGoogle Analytics APIの結果をHugoから使えるように - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;またもやHugo用にGoのサーバーにAPIを追加しました。HugoでGoogle Analyticsで取っているPV順に並べた結果を使ってコンテンツを作るためです。 似たようなことをこの辺↓↓で書いてます。 https://blog.piyo.tech/posts/2018-04-04-ogp-json/ まず認証情報を作るところがなかなか面倒です。こちらのURLがほぼまんま参考になるので順を追って実施してみてください（丸投げ）。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;まずはサイドバーにエリアを追加しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;aside&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;l-sidebar&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;sections sidebar&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; {{ partial &amp;#34;author.html&amp;#34; . }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; {{ partial &amp;#34;popular.html&amp;#34; . }} ←これを追加
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; {{ partial &amp;#34;latests.html&amp;#34; . }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; {{ partial &amp;#34;tags.html&amp;#34; . }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;aside&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;全体としては↓のようになってて、APIでPV順に戻ってきた&lt;code&gt;$json.rows&lt;/code&gt;のうち先頭5件を取り出してループを回しています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{{- $json := getJSON .Site.Params.GAURL -}} 作っておいたAPIを呼び出す
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{{- $ogpUrl := .Site.Params.OgpJsonBaseUrl -}} ←あとで使う
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;section&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;sidebar&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;header&lt;/span&gt;&amp;gt;POPULAR&amp;lt;/&lt;span style="color:#f92672"&gt;header&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;articles sm&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; {{ range $row := (first 5 $json.rows) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; ここに内容を書く
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; {{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;section&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;記事ごとの要素はLATESTにあるものと同じような見え方にすべく、HTMLもほぼ同じようにしました。ですが、GAの結果には記事のサムネイルやタグなどがありません。&lt;/p&gt;
&lt;p&gt;タグは無くてもいいとしてサムネイルを載せないと寂しくなってしまったので、OGP画像を表示したときのようにOGPのAPIを呼び出してその結果を利用する形でサムネイルを表示しました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-04-04-ogp-json/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://goo.gl/NSXeuF" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;ブログのビルド用にOGPの情報をJSONで返すサーバーも作った - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;前回の続きです。 https://blog.piyo.tech/posts/2018-04-02-blog-link/ リンクの見た目をいい感じにするためにOGPのJSONのサーバーを作って、Data-Driven Contentで表示するようにしたよ、というのが前回の話です。 echoのサーバーに機能追加 https://blog.piyo.tech/posts/2018-03-27-deploy-go/ すでに動かしているGoのサーバーに機能を追加しました。 /ogp?url=http://xxxxx とリクエストすると欲しいサイトのOGPをJSONで返してくれるようにします。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;以下に ループの内側のHTMLを掲載します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{{- $date := substr (index $row 2) 1 10 }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{{- $path := printf &amp;#34;%s%s&amp;#34; (index $row 1) (substr (index $row 2) 1)}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;{{- $url := printf &amp;#34;https://blog.piyo.tech%s&amp;#34; $path}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;{{- $json2 := getJSON (printf &amp;#34;%s%s&amp;#34; $ogpUrl $url) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;{{- $image := index $json2.Image 0 -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;{{- $imageUrl := $image.URL -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;article&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;lism&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $path }}&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;thumb&amp;#34;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;{{&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;printf&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;background-image: url(%s)&amp;#39;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;imageUrl&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;safeHTMLAttr&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;}}&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;inner&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;title sm&amp;#34;&lt;/span&gt;&amp;gt;{{ index $row 3 }}&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;facts sm&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style="color:#f92672"&gt;i&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;fa fa-calendar&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;aria-hidden&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;i&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style="color:#f92672"&gt;time&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;datetime&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $date }}&amp;#34;&lt;/span&gt;&amp;gt;{{ $date }}&amp;lt;/&lt;span style="color:#f92672"&gt;time&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;article&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;$json2&lt;/code&gt;というのが、OGP用のAPIの結果で、その中身である&lt;code&gt;$image.URL&lt;/code&gt;をサムネイルとして利用しました。&lt;/p&gt;</description></item><item><title>Go lang + EchoでGoogle Analytics APIの結果をHugoから使えるように</title><link>https://blog.piyo.tech/posts/2018-05-22-analytics-api-via-echo/</link><pubDate>Tue, 22 May 2018 06:45:46 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-22-analytics-api-via-echo/</guid><description>&lt;p&gt;またもやHugo用にGoのサーバーにAPIを追加しました。HugoでGoogle Analyticsで取っているPV順に並べた結果を使ってコンテンツを作るためです。&lt;/p&gt;
&lt;p&gt;似たようなことをこの辺↓↓で書いてます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-04-04-ogp-json/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://goo.gl/NSXeuF" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;ブログのビルド用にOGPの情報をJSONで返すサーバーも作った - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;前回の続きです。 https://blog.piyo.tech/posts/2018-04-02-blog-link/ リンクの見た目をいい感じにするためにOGPのJSONのサーバーを作って、Data-Driven Contentで表示するようにしたよ、というのが前回の話です。 echoのサーバーに機能追加 https://blog.piyo.tech/posts/2018-03-27-deploy-go/ すでに動かしているGoのサーバーに機能を追加しました。 /ogp?url=http://xxxxx とリクエストすると欲しいサイトのOGPをJSONで返してくれるようにします。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;まず認証情報を作るところがなかなか面倒です。こちらのURLがほぼまんま参考になるので順を追って実施してみてください（丸投げ）。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://liginc.co.jp/356517" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://liginc.co.jp/wp-content/uploads/2017/07/149933867562867000_61.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;【最新版】GoogleAnalytics API 認証設定について画像多めで説明します。 | 株式会社LIG(リグ)｜DX支援・システム開発・Web制作&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;おはこんばんにちは。ハルです。 PHPで Google Analytics API&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://liginc.co.jp/wp-content/themes/ligblog2022/assets/images/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;liginc.co.jp&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;jsonを取得してGoogle Analytics側にjsonの中に書いてあるメールアドレスをユーザーとして追加するところまでやっておきます。&lt;/p&gt;
&lt;p&gt;次にコードを書きます。&lt;/p&gt;
&lt;p&gt;まずは依存するライブラリを追加します。（Echoのコードはすでにある前提とします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% dep ensure -add golang.org/x/oauth2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;% dep ensure
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そしてimportに追加&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;golang.org/x/oauth2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;golang.org/x/oauth2/google&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;analytics&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;google.golang.org/api/analytics/v3&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Echoに新しいルーティングを追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;GET&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;/ga&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;getGA&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ハンドラはこんな感じ。こちらをかなり参考にさせてもらいました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.soushi.me/entry/2016/11/07/152046/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://b.st-hatena.com/images/entry-button/button-only@2x.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;go langからGoogle Analytics APIを使う - 平日インプット週末アウトプットぶろぐ&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;こちらの記事↓ではSpring Boot &amp;#43; kotlinからの利用方法でしたがgoからの利用も調査しました。Spring Boot &amp;#43; kotlinでGoogle&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.soushi.me/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.soushi.me&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getGA&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;echo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Context&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;client&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;google&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DefaultClient&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;oauth2&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NoContext&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://www.googleapis.com/auth/analytics.readonly&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusInternalServerError&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Unable to read client : %s&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Error&lt;/span&gt;()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;service&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;analytics&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;New&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;client&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusInternalServerError&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Unable to Access Google Analytics: %s&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Error&lt;/span&gt;()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;service&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Ga&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;ga:xxxxxxxxxx&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;7daysAgo&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;today&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;ga:pageviews&amp;#34;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;Dimensions&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;ga:pagePath,ga:pagePathLevel1,ga:pagePathLevel2,ga:pageTitle&amp;#34;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;Filters&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;ga:pagePath=~^/posts/&amp;#34;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;Sort&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;-ga:pageviews&amp;#34;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;Do&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusInternalServerError&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Unable to get data: %s&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Error&lt;/span&gt;()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;JSON&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusOK&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;ga:xxxxxxxxxx&lt;/code&gt;となっている箇所はGoogle AnalyticsのViewに対応しています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/uJzldGrwCPE6z1KBTwmeqF4VpfQrw5IUnjECYq375VSThhLDw9B14ZZ5f0JZxncWDjZnehZZAGWILK4xXy2WF-iOKsj2GwjeMIFatJCpgVXyYpqgw8DA5_SjvLDnQPCwyXWIbQsrGS9YDKCCm7DbQHWIouDNbaEX79bylIFSqmsisWEH7mBAks-_xjJxbgEDCsIJSPYjq-cqkY3RIBx75U-uB4Gy6dBDlquK0xwPfDr4Ht8Th5Wgq5KmaZHPNf9k7XFHeqcTV3s-f05sBWHK4SEgyfzRAfEEE-x6VK4odEKZXWkhvWob5vvHHfmW8Vvn5tbUOs0GUND-fQxoqiW2s8dmDZ627CfPPAzv3hM3WchTvF16L4ORVnO8M3G2A2yho5NbIXAsPOc0IdbllCNyWMPnSvnlhwBam26KDiiOsyXT3pdsdN-rcjsgiM61eI_HCaOCtaFGgzIF9D_E7r5RavtTatVsqmCT2dSlNQBvHX9gVUPuyBZbcBnmlIjxra-lg41Y7v2j-6weEpaZMhTjD4thIOOL_g2WBjpFLM44ynso3HjfRiAv8_H4pYg5gYNjzp5pUlm78ODW6IxCvH2Oz0qRNFF7bL0N6ST06uzZVzyPChAAXfRyjhQOVYAU6knsHE8EFOBJoLQpK9pHWh8MhbGaDZ-5fRBL=w503-h554-no"&gt;&lt;img src="https://lh3.googleusercontent.com/uJzldGrwCPE6z1KBTwmeqF4VpfQrw5IUnjECYq375VSThhLDw9B14ZZ5f0JZxncWDjZnehZZAGWILK4xXy2WF-iOKsj2GwjeMIFatJCpgVXyYpqgw8DA5_SjvLDnQPCwyXWIbQsrGS9YDKCCm7DbQHWIouDNbaEX79bylIFSqmsisWEH7mBAks-_xjJxbgEDCsIJSPYjq-cqkY3RIBx75U-uB4Gy6dBDlquK0xwPfDr4Ht8Th5Wgq5KmaZHPNf9k7XFHeqcTV3s-f05sBWHK4SEgyfzRAfEEE-x6VK4odEKZXWkhvWob5vvHHfmW8Vvn5tbUOs0GUND-fQxoqiW2s8dmDZ627CfPPAzv3hM3WchTvF16L4ORVnO8M3G2A2yho5NbIXAsPOc0IdbllCNyWMPnSvnlhwBam26KDiiOsyXT3pdsdN-rcjsgiM61eI_HCaOCtaFGgzIF9D_E7r5RavtTatVsqmCT2dSlNQBvHX9gVUPuyBZbcBnmlIjxra-lg41Y7v2j-6weEpaZMhTjD4thIOOL_g2WBjpFLM44ynso3HjfRiAv8_H4pYg5gYNjzp5pUlm78ODW6IxCvH2Oz0qRNFF7bL0N6ST06uzZVzyPChAAXfRyjhQOVYAU6knsHE8EFOBJoLQpK9pHWh8MhbGaDZ-5fRBL=w503-h554-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;また、コードの14行目のあたりで&lt;code&gt;Dimension&lt;/code&gt;やら&lt;code&gt;Filter&lt;/code&gt;やら&lt;code&gt;Sort&lt;/code&gt;やらを指定しています。これらはQuery Explorerで確認して決めると便利です。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-05-21-google-analytics-query-explorer/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/ZQe_1isIPpoiKTVR9TQg56r2XohLYnAMFjcZf8jh_S9NhyWlrmC-LwaKUequoi00V5ESnBCpRYFNEhAovayCrx_g4iXHz4Tj0iM2ch_X8LbP__ReVTxOEruUedaMwTQxSefo8HS4S4Xr5nMMj0JitQ6d6WJwe2YgLLCmBTBWgjYPzzocprDBX9OjDysjJ6WMxcJZMzO5XzfWWGDti0BdFdCKFuG5_LbqHureBa8ReWVdMhn9c5bjgynKzN2LGVeXXna8JlWYZB9cxJcDMVkTikl7KoLkZ2p9zaODl-sn31MGLBCKNvQjwZZtXgl-8YGzndXhVD0uPzEHwdHs4deqvTYSyO2qKXhY8v5el2LO9coJbr8h4dvzYENMDXkhT6NtFh4AVvT3B_9V49w0VED4BVR6mzh7q_I_lwnQ65oAQirG4TeKqaMPnifeClPPHefiquONkozxifPEr6juFFqXPY2ExRkf6Wokzgpxck3SK3FvLHJDutpG6f7l-Jm4-TMqN5NKlsrGeQ2rWW4Keq0k0Ls9ta3xhgCzqjsMmldMwF1D9ou91url1WmpdNpZpyf7jSzT4hVaQsrc3LiQt3WwAnYf0GO9mNjNXiD430OWdTjpOXQqltxnCmQToqWqnqeAQbAMcQ2WtR62sE1XhnA1t8whigRBdL-B=w906-h586-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Google AnalyticsのQuery ExplorerでAPIリクエストをテストする - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;読まれてる記事順のリストをブログに付けてみたいという思いつきを実現したいのですが、PV的なものはGoogle Analyticsにしか情報がありません。 またサイトジェネレータの場合はページ生成時にPageViewが必要になるので工夫してあげないと実用上使えません。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;これでコードはOKです。実行時に先ほどのjsonファイルが必要となります。環境変数での指定が必要なので、&lt;code&gt;GOOGLE_APPLICATION_CREDENTIALS=path/to/json&lt;/code&gt;のような形で実行してあげると、無事Echo経由でGoogle AnalyticsのAPI呼び出しをJSONで取得できるようになりました。&lt;/p&gt;</description></item><item><title>Google AnalyticsのQuery ExplorerでAPIリクエストをテストする</title><link>https://blog.piyo.tech/posts/2018-05-21-google-analytics-query-explorer/</link><pubDate>Mon, 21 May 2018 06:41:26 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-21-google-analytics-query-explorer/</guid><description>&lt;p&gt;読まれてる記事順のリストをブログに付けてみたいという思いつきを実現したいのですが、PV的なものはGoogle Analyticsにしか情報がありません。&lt;/p&gt;
&lt;p&gt;またサイトジェネレータの場合はページ生成時にPageViewが必要になるので工夫してあげないと実用上使えません。&lt;/p&gt;
&lt;p&gt;そうなるとページ生成時にGoogle Analyticsから取ってきた結果を参考にしてページを組み立てるしかありません。&lt;/p&gt;
&lt;p&gt;必要な情報は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ある期間の&lt;/li&gt;
&lt;li&gt;PV順の&lt;/li&gt;
&lt;li&gt;記事の情報&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;となります。これらを調べるのにAPIのドキュメントを見るのもいいですが、問い合わせを試させてくれるGoogleが用意したページがあるので、それを使うと便利です。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://ga-dev-tools.appspot.com/query-explorer/?hl=ja" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://ga-dev-tools.appspot.com/favicon-32x32.png?v=5ca3b219e853f3099dafaaf6ab021795" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;ga-dev-tools.appspot.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;まずページへアクセスすると、Authorizeしてねというリンクが出ています。自分のGoogleアカウントへのアクセスを許可しないと使用できない作りになっています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/ZQe_1isIPpoiKTVR9TQg56r2XohLYnAMFjcZf8jh_S9NhyWlrmC-LwaKUequoi00V5ESnBCpRYFNEhAovayCrx_g4iXHz4Tj0iM2ch_X8LbP__ReVTxOEruUedaMwTQxSefo8HS4S4Xr5nMMj0JitQ6d6WJwe2YgLLCmBTBWgjYPzzocprDBX9OjDysjJ6WMxcJZMzO5XzfWWGDti0BdFdCKFuG5_LbqHureBa8ReWVdMhn9c5bjgynKzN2LGVeXXna8JlWYZB9cxJcDMVkTikl7KoLkZ2p9zaODl-sn31MGLBCKNvQjwZZtXgl-8YGzndXhVD0uPzEHwdHs4deqvTYSyO2qKXhY8v5el2LO9coJbr8h4dvzYENMDXkhT6NtFh4AVvT3B_9V49w0VED4BVR6mzh7q_I_lwnQ65oAQirG4TeKqaMPnifeClPPHefiquONkozxifPEr6juFFqXPY2ExRkf6Wokzgpxck3SK3FvLHJDutpG6f7l-Jm4-TMqN5NKlsrGeQ2rWW4Keq0k0Ls9ta3xhgCzqjsMmldMwF1D9ou91url1WmpdNpZpyf7jSzT4hVaQsrc3LiQt3WwAnYf0GO9mNjNXiD430OWdTjpOXQqltxnCmQToqWqnqeAQbAMcQ2WtR62sE1XhnA1t8whigRBdL-B=w906-h586-no"&gt;&lt;img src="https://lh3.googleusercontent.com/ZQe_1isIPpoiKTVR9TQg56r2XohLYnAMFjcZf8jh_S9NhyWlrmC-LwaKUequoi00V5ESnBCpRYFNEhAovayCrx_g4iXHz4Tj0iM2ch_X8LbP__ReVTxOEruUedaMwTQxSefo8HS4S4Xr5nMMj0JitQ6d6WJwe2YgLLCmBTBWgjYPzzocprDBX9OjDysjJ6WMxcJZMzO5XzfWWGDti0BdFdCKFuG5_LbqHureBa8ReWVdMhn9c5bjgynKzN2LGVeXXna8JlWYZB9cxJcDMVkTikl7KoLkZ2p9zaODl-sn31MGLBCKNvQjwZZtXgl-8YGzndXhVD0uPzEHwdHs4deqvTYSyO2qKXhY8v5el2LO9coJbr8h4dvzYENMDXkhT6NtFh4AVvT3B_9V49w0VED4BVR6mzh7q_I_lwnQ65oAQirG4TeKqaMPnifeClPPHefiquONkozxifPEr6juFFqXPY2ExRkf6Wokzgpxck3SK3FvLHJDutpG6f7l-Jm4-TMqN5NKlsrGeQ2rWW4Keq0k0Ls9ta3xhgCzqjsMmldMwF1D9ou91url1WmpdNpZpyf7jSzT4hVaQsrc3LiQt3WwAnYf0GO9mNjNXiD430OWdTjpOXQqltxnCmQToqWqnqeAQbAMcQ2WtR62sE1XhnA1t8whigRBdL-B=w906-h586-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;次にどのサイトのどのViewのデータを見たいかを指定します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Q510aYeE5p4La70FrUkZZZy-K40oXXR__j6zwnBExpcarosN8l5SttE_VZnbX1MYIyMN2L74R5pnuZZE1QAF9c5sHMXec7SqtE48b5AlJMypjg1PzgicpNUt48ckYOBjP6G2Ace-xbO9pLE2Q41m8kTZnXxuPFpwcyGX4xytAKt6p_a9i4JfQ3gvQNp6xGinx4fFuWvTJnWuefZ0L8z1RWxJrd5f9_8Ni1TvOyf-0gSmF5nmK9tN019p33HyQo69HVF1NoaHtr8ZdT7IHNHi-nDuVOJWn0EoFG-3Lbuj7vbFbhu6x8T-0G4vZhJiMQY9jSA5YgXWTA64LbRvtnJLRbxB7usit7BnTWP-XW7jN79utA0buUysOi_00oQTbV0ZQPuRRTtU63jnODN94immMjsoyJJREgPQWFrelM9Llljzzh_qO9GRHJH4srloVyaucAhBMFdWwbHr_oa-T6jByqysL5JaBvKnPVzu7N_ay8G2H_JYTK-a4qxyCmabXSTsOs1frHdbobJca8PsPyw_LPr7vFBHC2QyTCkJcIlnDYc3toHvTXIPWhHeGIKAuCkJi5_IFFz5-xBgsO2YlxuKOuWa3h9qhAF-If_sYOoTYyuGHQ8oRcEX7tx9kq7jr_4lp1xkYjIXvQS5LeDmsouOw9KwvpEQgHT7=w611-h241-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Q510aYeE5p4La70FrUkZZZy-K40oXXR__j6zwnBExpcarosN8l5SttE_VZnbX1MYIyMN2L74R5pnuZZE1QAF9c5sHMXec7SqtE48b5AlJMypjg1PzgicpNUt48ckYOBjP6G2Ace-xbO9pLE2Q41m8kTZnXxuPFpwcyGX4xytAKt6p_a9i4JfQ3gvQNp6xGinx4fFuWvTJnWuefZ0L8z1RWxJrd5f9_8Ni1TvOyf-0gSmF5nmK9tN019p33HyQo69HVF1NoaHtr8ZdT7IHNHi-nDuVOJWn0EoFG-3Lbuj7vbFbhu6x8T-0G4vZhJiMQY9jSA5YgXWTA64LbRvtnJLRbxB7usit7BnTWP-XW7jN79utA0buUysOi_00oQTbV0ZQPuRRTtU63jnODN94immMjsoyJJREgPQWFrelM9Llljzzh_qO9GRHJH4srloVyaucAhBMFdWwbHr_oa-T6jByqysL5JaBvKnPVzu7N_ay8G2H_JYTK-a4qxyCmabXSTsOs1frHdbobJca8PsPyw_LPr7vFBHC2QyTCkJcIlnDYc3toHvTXIPWhHeGIKAuCkJi5_IFFz5-xBgsO2YlxuKOuWa3h9qhAF-If_sYOoTYyuGHQ8oRcEX7tx9kq7jr_4lp1xkYjIXvQS5LeDmsouOw9KwvpEQgHT7=w611-h241-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;最後に検索条件を入力して「Run Query」をします。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/ztzRd5MLIvbOz26KyYjm7KfqbH-zcE0V3LdlbS9DgZIfxqUCRQjOqbXvOQ_R-hgNsrELQP_PEa71V3h5DmkRS7sXBizMd2JsQ8M5srjKabMYL1g2dO4tr5_DmJuvRKDwzXucy_iJojqaa7UG4iGv85i53pGW54DIFhmFED-TaDP4_sOoWp_bcXEL8PoQgFaU_JRutygvTB5KCzFlYMCKGw6lZ1dBPz5rQIMrOCu_XBeLLLBVmL0h0PoHKEl6y3gDoHz_BqY9MkJ7mVhXg_EKwMwLYkYgGtmiAskjgEWYD2nVBXHIlZvEAlhfp_TvZc-of1RUUWgvrjAb5IKm91Qs8yt7RuMPKE8Kr9bjJ3f3_lKezx51IoMm66J0AEqzK8p8cjBlK8wTARxSXjx0yEmsRCobh4IFsqGqfY9B5-KnzTBlYjujbwzpj1Y0-p2Q-unZJHYP1ym377z3gmFHk8fQJIIGroRRiV_oA1xubkWqSEwsVaDDlUa-XVjXJluH3T2-PCSd9CruUOV7Fuctu99KqGD-x3LmX5joATR9csnkIQf1b4yGDLPixBHwvsr7ne-FapTnz3Yem6qDAatMxuHMT1VDWglhWbjXwFsPc1dj8In2ORBJ2EQ2AUvxENyYowzf88qfFyU-Ks3ax-a9uij_i35EwmxGBOYH=w675-h803-no"&gt;&lt;img src="https://lh3.googleusercontent.com/ztzRd5MLIvbOz26KyYjm7KfqbH-zcE0V3LdlbS9DgZIfxqUCRQjOqbXvOQ_R-hgNsrELQP_PEa71V3h5DmkRS7sXBizMd2JsQ8M5srjKabMYL1g2dO4tr5_DmJuvRKDwzXucy_iJojqaa7UG4iGv85i53pGW54DIFhmFED-TaDP4_sOoWp_bcXEL8PoQgFaU_JRutygvTB5KCzFlYMCKGw6lZ1dBPz5rQIMrOCu_XBeLLLBVmL0h0PoHKEl6y3gDoHz_BqY9MkJ7mVhXg_EKwMwLYkYgGtmiAskjgEWYD2nVBXHIlZvEAlhfp_TvZc-of1RUUWgvrjAb5IKm91Qs8yt7RuMPKE8Kr9bjJ3f3_lKezx51IoMm66J0AEqzK8p8cjBlK8wTARxSXjx0yEmsRCobh4IFsqGqfY9B5-KnzTBlYjujbwzpj1Y0-p2Q-unZJHYP1ym377z3gmFHk8fQJIIGroRRiV_oA1xubkWqSEwsVaDDlUa-XVjXJluH3T2-PCSd9CruUOV7Fuctu99KqGD-x3LmX5joATR9csnkIQf1b4yGDLPixBHwvsr7ne-FapTnz3Yem6qDAatMxuHMT1VDWglhWbjXwFsPc1dj8In2ORBJ2EQ2AUvxENyYowzf88qfFyU-Ks3ax-a9uij_i35EwmxGBOYH=w675-h803-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PVが欲しいので&lt;code&gt;metrics&lt;/code&gt;には&lt;code&gt;ga:pageviews&lt;/code&gt;を。また、パスやタイトルなどはHugo上で使いたいので&lt;code&gt;dimentions&lt;/code&gt;に指定。&lt;/p&gt;
&lt;p&gt;PV順に並び替えた状態にしたいので&lt;code&gt;sort&lt;/code&gt;に&lt;code&gt;-ga:pageviews&lt;/code&gt;を。マイナス指定で降順になります。また、記事ページ以外は無視したいので&lt;code&gt;filter&lt;/code&gt;に正規表現でpathの条件を指定。&lt;/p&gt;
&lt;p&gt;filter以外は補完で入力してくれるのでなんとなく「pageview」とか「path」とか打ってそれっぽいものを選ぶだけでOKです。&lt;/p&gt;
&lt;p&gt;結果をこのような形で閲覧できます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/ig_HGgoy51iX6w6wP3asJrvPhpAqwLcBfhOKgFc6S-4HrTC1R2w0lxfuA5u3IOUjD_ffNVTq_z4dibK4wV7FxJegPwp55fbCuRIT9yNBm3xlhQlarEUcP4xxPJJE52FUJnYqthuoFT6Sdxn63Nvuu_6mzWixrJpybO0j3kNdlDOfzW8jX6DqAzH_fRet0fsDIzx8TmOIAjqs8KgnkmvIPrLqvSTbk8xaKNrdQfhvevwWlSa6Y7R16Fmrr-qlMWczNo-tZnIbL2X9gOcVGNuhws9pGfXOsLO7ZzKkL3ar-L8aGCG4IcN86kNYijC0gQtjnxpNlMLkiyXEwNQcL0z_VnuSKnkRB85z5nVmDtJdpHp2Xl7QRSfT4BU0ySEX_0GWbYHkxAVWTGpA6Fw84cTM9slGlqe9xEGHr3y-ZNt_i6OdKLLsEcZeFBEiIyF7ZeBXDyz-AuQvEoNfLb93kyeek5HuycYo1ktAg-nqK1xJ4s4jo8GXaStpwD0KXCWT0S1D7WjvNqNvmFNHu7C_ysRFz9-FmTOzVRI4ZdQQJHAm68CULB2kpOx_zTOAit4L_c3NSANEI91bXb7-SeLP9-u_geZp-tvf24bUcaaoim_tUoQoCnnc3k1qh5Le7gqKU9XmVoV1DC_AdaWheUrVxDTF-R7an-vKGe93=w980-h349-no"&gt;&lt;img src="https://lh3.googleusercontent.com/ig_HGgoy51iX6w6wP3asJrvPhpAqwLcBfhOKgFc6S-4HrTC1R2w0lxfuA5u3IOUjD_ffNVTq_z4dibK4wV7FxJegPwp55fbCuRIT9yNBm3xlhQlarEUcP4xxPJJE52FUJnYqthuoFT6Sdxn63Nvuu_6mzWixrJpybO0j3kNdlDOfzW8jX6DqAzH_fRet0fsDIzx8TmOIAjqs8KgnkmvIPrLqvSTbk8xaKNrdQfhvevwWlSa6Y7R16Fmrr-qlMWczNo-tZnIbL2X9gOcVGNuhws9pGfXOsLO7ZzKkL3ar-L8aGCG4IcN86kNYijC0gQtjnxpNlMLkiyXEwNQcL0z_VnuSKnkRB85z5nVmDtJdpHp2Xl7QRSfT4BU0ySEX_0GWbYHkxAVWTGpA6Fw84cTM9slGlqe9xEGHr3y-ZNt_i6OdKLLsEcZeFBEiIyF7ZeBXDyz-AuQvEoNfLb93kyeek5HuycYo1ktAg-nqK1xJ4s4jo8GXaStpwD0KXCWT0S1D7WjvNqNvmFNHu7C_ysRFz9-FmTOzVRI4ZdQQJHAm68CULB2kpOx_zTOAit4L_c3NSANEI91bXb7-SeLP9-u_geZp-tvf24bUcaaoim_tUoQoCnnc3k1qh5Le7gqKU9XmVoV1DC_AdaWheUrVxDTF-R7an-vKGe93=w980-h349-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;また、このAPIリクエストをするためのURLを生成しておいてくれるのでアクセスキーさえ設定すればすぐに使えるという感じになってて便利です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/4jThskp8Ox1v7nfG3DI-yFi4zD5YIabm8fyrv_4Ab8jfQefwKkVw_Lf9vh_py31mVJDyhNAyapfAWHmeeraYKf8AWls23BD7g5o1KbtE_up1zH_fdCireYxhEyc32HNrmp6uFxk1yjZsqkZcNYVOeyy_IXpp-DJnlimiDjhd_4SOAXyssdxHL5Kn4ph_t_-kwb9S13-U1mlgcZ5tYOAkLmQ_PahVILoD1Z7xVB_CqgioxuaoYlUaUS2s8JGELL42Tw7JodM_vHhssT8skeJGfhO_TCxO2qcb6_fccgt0SLsl82NtWXP6d7pQo5UZBvBvS4R2fsP2yGtYlq8dzjh2FQXvv_LPpyi53Ib6N-itmjGSfRwZZ3vdGj7kywJvuJf_yZQI7kdcMJqldLY-5eK5OmzOs6noLvKRRgI1lrtnc_Dox6k4ANK5m49WOnuxLpjuwsRuZlX742oDHtxp_nn9d4hsd544oZSBipMvStcLGGuYAKxE1HwnFw1k2l1wJL-aNNRdTHTiSNBkxT4fNim39eNYepkM8eBCbLgRiBD471t7GuPjn36ZgdDCr-fVLfqYoBf9VRndBVfiHSZ0FXD5yFlFCu1__zFxihQz_kbqOAKpjldvt4DO6gAODDXG3sSykWsvcxXZQsSIRY9kQtAA5-MUw8k3unzC=w1035-h138-no"&gt;&lt;img src="https://lh3.googleusercontent.com/4jThskp8Ox1v7nfG3DI-yFi4zD5YIabm8fyrv_4Ab8jfQefwKkVw_Lf9vh_py31mVJDyhNAyapfAWHmeeraYKf8AWls23BD7g5o1KbtE_up1zH_fdCireYxhEyc32HNrmp6uFxk1yjZsqkZcNYVOeyy_IXpp-DJnlimiDjhd_4SOAXyssdxHL5Kn4ph_t_-kwb9S13-U1mlgcZ5tYOAkLmQ_PahVILoD1Z7xVB_CqgioxuaoYlUaUS2s8JGELL42Tw7JodM_vHhssT8skeJGfhO_TCxO2qcb6_fccgt0SLsl82NtWXP6d7pQo5UZBvBvS4R2fsP2yGtYlq8dzjh2FQXvv_LPpyi53Ib6N-itmjGSfRwZZ3vdGj7kywJvuJf_yZQI7kdcMJqldLY-5eK5OmzOs6noLvKRRgI1lrtnc_Dox6k4ANK5m49WOnuxLpjuwsRuZlX742oDHtxp_nn9d4hsd544oZSBipMvStcLGGuYAKxE1HwnFw1k2l1wJL-aNNRdTHTiSNBkxT4fNim39eNYepkM8eBCbLgRiBD471t7GuPjn36ZgdDCr-fVLfqYoBf9VRndBVfiHSZ0FXD5yFlFCu1__zFxihQz_kbqOAKpjldvt4DO6gAODDXG3sSykWsvcxXZQsSIRY9kQtAA5-MUw8k3unzC=w1035-h138-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>React Nativeで画像のRGBA値を得る</title><link>https://blog.piyo.tech/posts/2018-05-20-image-rgba-react-native/</link><pubDate>Sun, 20 May 2018 06:08:06 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-20-image-rgba-react-native/</guid><description>&lt;p&gt;React Nativeで画像のRGBA値が欲しくて調べてたら&lt;code&gt;react-native-image-tools&lt;/code&gt;というライブラリを見つけました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/Benjamin-Lin-X/react-native-image-tools" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/8aeb2eac3e2046303b42c0f638f99b352f93d7afeb7af989478bf9cd060b7ea3/Benjamin-Lin-X/react-native-image-tools" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - Benjamin-Lin-X/react-native-image-tools&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Contribute to Benjamin-Lin-X/react-native-image-tools development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;かなり名前が近い別パッケージもあるので混同注意です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% npm -i react-native-image-tool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;% react-native link react-native-image-tool
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;で導入できます。&lt;/p&gt;
&lt;p&gt;インターフェースはざっくり&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;createBinaryImage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetImageRGBAs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;な2つしかないようです。このうち、&lt;code&gt;GetImageRGBAs&lt;/code&gt;のほうを使いました。&lt;/p&gt;
&lt;p&gt;画像のURLを渡すと結果が返ってくるという形です。結果には、&lt;code&gt;width&lt;/code&gt;、&lt;code&gt;height&lt;/code&gt;、および&lt;code&gt;rgba&lt;/code&gt;というRGBAの配列が返ってきます。&lt;/p&gt;
&lt;p&gt;以下は、この画像を読み込んでみる例です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://imgur.com/download/OSEiha9"&gt;https://imgur.com/download/OSEiha9&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://imgur.com/download/OSEiha9"&gt;&lt;img src="https://imgur.com/download/OSEiha9" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ImageTools&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react-native-image-tool&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;url&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;https://imgur.com/download/OSEiha9&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ImageTools&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;GetImageRGBAs&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;url&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;response&lt;/span&gt; =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// response.rgba
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;さてこのRGBAの配列ですが、32bitの符号付き整数として返ってきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;response&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;rgba&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// =&amp;gt; -16776961
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例えば0番目には&lt;code&gt;-16776961&lt;/code&gt;という値が入っています。これを符号無しにしてビット演算でRGBA毎の値に変換してあげないといけません。&lt;/p&gt;
&lt;p&gt;（そのまま一気に行けそうな気もするけど個人的にわかりにくいから、符号なしにしてから各成分を取り出してます）&lt;/p&gt;
&lt;p&gt;以下の関数を定義して、&lt;code&gt;-16776961&lt;/code&gt;を変換してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;unsigned&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;signedValue&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;signedValue&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;red&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;unsignedValue&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;unsignedValue&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0xff&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;green&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;unsignedValue&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;unsignedValue&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0xff&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;blue&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;unsignedValue&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;unsignedValue&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0xff&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;alpha&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;unsignedValue&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;unsignedValue&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0xff&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;val&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;response&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;rgba&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;u&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;unsigned&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;val&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// =&amp;gt; 4278190335
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;red&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;u&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// =&amp;gt; 255
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;g&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;green&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;u&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// =&amp;gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;g&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;blue&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;u&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// =&amp;gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;alpha&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;u&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// =&amp;gt; 255
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;という感じで&lt;code&gt;R&lt;/code&gt;と&lt;code&gt;A&lt;/code&gt;が&lt;code&gt;255&lt;/code&gt;、&lt;code&gt;G&lt;/code&gt;と&lt;code&gt;B&lt;/code&gt;が&lt;code&gt;0&lt;/code&gt;だということがわかりました。0番目は画像の左上で赤が正しいので、結果も合っていそうです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;response.rgba&lt;/code&gt;は配列なので、mapなどを使えば一気に赤成分だけ取り出すことも可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;redArray&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;response&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;rgba&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uint&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;unsigned&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;red&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;uint&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Quitterでつい時間使っちゃうMacアプリを隠したり終了したり</title><link>https://blog.piyo.tech/posts/2018-05-19-quitter-for-mac/</link><pubDate>Sat, 19 May 2018 06:13:35 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-19-quitter-for-mac/</guid><description>&lt;p&gt;見るつもりがないアプリなのに目に入っちゃってそこから脇道にそれていって、元々何をやろうとしていたのか忘れてしまうみたいなことがたまに起こります。&lt;/p&gt;
&lt;p&gt;特にマルチディスプレイだったりすると起こりがちかなーと思っていて、片方でコード書いてて何かの拍子に別のディスプレイで開いてたTwitterが見えちゃって、みたいなことってあるんじゃないかと。&lt;/p&gt;
&lt;p&gt;それの対策としてQuitter for Macというアプリを入れてたのに最近使うのを忘れていたことを急に思い出したのでメモしておきます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://marco.org/apps" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://marco.org/media/apps/overcast1.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Apps – Marco.org&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;I’m Marco Arment: a programmer, writer, podcaster, geek, and coffee enthusiast.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;span class="truncate"&gt;marco.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Quitterは指定したアプリが指定した時間アイドルだった場合に終了したり隠したりしてくれるだけのアプリです。開発者はInstapaperとかOvercastの開発者でもあるMarco Arment氏です。&lt;/p&gt;
&lt;p&gt;インストール方法は↑のサイトからzipをダウンロードしてきて適当にやります。起動するとメニューバーにアイコンが現れます。今後Mac起動時に常駐させておきたいなら「Start Quitter at Login」にチェックを入れおくとよいです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/F1z2XnRWyT7-9AuJGzVncrkVSzn20uiFLaKxD5VKdFclRFeK9zQknVBN073of0-67WVT3xG9piJ-wjrifxNXns_7TCACeJWbJmskSqEeE8iphLXV8Z563eDFkQJL8mFPCYBHe8MKnioAdnutGnn95dWvB9XdwKyhc3HNp81oRP1Li3a35UrGXEpJqRbYLHhJNftFyU5IM7CYIqYXQaE5yz2N5L9Om2o7rghihDWYGH7ukj-2-nULNXwXbf4isRFkjz0QaG2eFrzEExr4FtZqGb57qVXlNc5Dhw7G4e8wJTIfM6e22Rb0IULg-Tm-LnoWRoAby2TIMZSodHHQhrCAMAS3sztk_Ooje6g3i41cOz3XtoOv-JzBZEipQoyQNfly0kd9p6UEgvZ_Tz9oYGl1Jw0PygOIFTGwBYUGAGg0gqsbHRwIzgJf801SND_EtswvB5ZgUZU0zGb2rXgBM80OKJr5nxbtt7fyWPzA4abcnkJjoVkIFUizm9tgGOAHIYcI2gRfEjdquT21MRpVmt-LtM2Yi9JrCULiR0lqIWcXKOjIjTgcEqMIq5ureOZuRokr4dDULY8xqELkvCsI_BkdTRfNfVKTwwc0LJ_FioKht0jrdzL4CSpLVcOhnw_SQruq_fvMEIzIsPOM-WJ7lBY_Mvx2JrTZXX3Z=w191-h171-no"&gt;&lt;img src="https://lh3.googleusercontent.com/F1z2XnRWyT7-9AuJGzVncrkVSzn20uiFLaKxD5VKdFclRFeK9zQknVBN073of0-67WVT3xG9piJ-wjrifxNXns_7TCACeJWbJmskSqEeE8iphLXV8Z563eDFkQJL8mFPCYBHe8MKnioAdnutGnn95dWvB9XdwKyhc3HNp81oRP1Li3a35UrGXEpJqRbYLHhJNftFyU5IM7CYIqYXQaE5yz2N5L9Om2o7rghihDWYGH7ukj-2-nULNXwXbf4isRFkjz0QaG2eFrzEExr4FtZqGb57qVXlNc5Dhw7G4e8wJTIfM6e22Rb0IULg-Tm-LnoWRoAby2TIMZSodHHQhrCAMAS3sztk_Ooje6g3i41cOz3XtoOv-JzBZEipQoyQNfly0kd9p6UEgvZ_Tz9oYGl1Jw0PygOIFTGwBYUGAGg0gqsbHRwIzgJf801SND_EtswvB5ZgUZU0zGb2rXgBM80OKJr5nxbtt7fyWPzA4abcnkJjoVkIFUizm9tgGOAHIYcI2gRfEjdquT21MRpVmt-LtM2Yi9JrCULiR0lqIWcXKOjIjTgcEqMIq5ureOZuRokr4dDULY8xqELkvCsI_BkdTRfNfVKTwwc0LJ_FioKht0jrdzL4CSpLVcOhnw_SQruq_fvMEIzIsPOM-WJ7lBY_Mvx2JrTZXX3Z=w191-h171-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;「Edit Rules&amp;hellip;」から設定を追加できます。&lt;/p&gt;
&lt;p&gt;+ボタンでアプリケーションを選ぶと列が追加されるので、あとは何分後にどうしたいのかをそれぞれに設定していけばOK。&lt;/p&gt;
&lt;p&gt;僕はひとまずこんな感じにしています。ChromeとかFranzは仕事上必要なことも多いですが、常にForegroundにいる必要は全然ないのでちょっと時間が経ってくれたら隠れてくれたほうが気が散らなくて良いです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/xtHf_72V4drPwCSt5RLAHWqiF2Ol7EjJMca38BdQ8ZgQeZKqk2R2MBVrILRIdSMHzxMwuUe9osXLXY4kvn7oLZ-hjV747B22Vj3GZ76tBqSLk2CGROTCb-dryahP9G5rlkAlBRzPxbH5T5WBxqeLpt4dPUXYgUBE8SQhi__48BtvodSQjKb4ShiMz7EnHnJ7wtv1dEf9X3BvnHHtY1N16le02sj9tyjCSPvuuv3Qbzg2lgMrw80DFiO9il-sKXn406Xg-TU1AB38evlmCalvsZC1Ra8bp_kGH-NpIrkrpiVH3_1mvxYoTKn8bLMFGhxukLhDMYAEXcgiRZ9S11dPyWuOMOS7ve-DTnKXbGuOTxTXtySnoscyMp52icuNbGloXO2EJ7bMSWLt9vQaf_Q5EQCr8a1L8CXCqKvK3iwBD02zCnczC1HP30lvebGQJ9WPWFNg91Hm62iKMqgYSFq7QYP_7fg6-An6HGXVhIZ9xQmCy_lTPX-5Br_Nhy3NyFqbwT5vJHlHzy-qklbqh8JOuhvyZxwoIh6Fn-XWgQZ6t3LrKBlklj3F1iHGnGiyK0bevFWZIlGWcNp_xD7_SqLLSBYjRcSCl_r9yhoOtNakaeyIj-W3Rrbho0NCY9OX5pxGpWIwKlZJHSb9Q5Gpjrc8xOcXFOklLFiy=w563-h426-no"&gt;&lt;img src="https://lh3.googleusercontent.com/xtHf_72V4drPwCSt5RLAHWqiF2Ol7EjJMca38BdQ8ZgQeZKqk2R2MBVrILRIdSMHzxMwuUe9osXLXY4kvn7oLZ-hjV747B22Vj3GZ76tBqSLk2CGROTCb-dryahP9G5rlkAlBRzPxbH5T5WBxqeLpt4dPUXYgUBE8SQhi__48BtvodSQjKb4ShiMz7EnHnJ7wtv1dEf9X3BvnHHtY1N16le02sj9tyjCSPvuuv3Qbzg2lgMrw80DFiO9il-sKXn406Xg-TU1AB38evlmCalvsZC1Ra8bp_kGH-NpIrkrpiVH3_1mvxYoTKn8bLMFGhxukLhDMYAEXcgiRZ9S11dPyWuOMOS7ve-DTnKXbGuOTxTXtySnoscyMp52icuNbGloXO2EJ7bMSWLt9vQaf_Q5EQCr8a1L8CXCqKvK3iwBD02zCnczC1HP30lvebGQJ9WPWFNg91Hm62iKMqgYSFq7QYP_7fg6-An6HGXVhIZ9xQmCy_lTPX-5Br_Nhy3NyFqbwT5vJHlHzy-qklbqh8JOuhvyZxwoIh6Fn-XWgQZ6t3LrKBlklj3F1iHGnGiyK0bevFWZIlGWcNp_xD7_SqLLSBYjRcSCl_r9yhoOtNakaeyIj-W3Rrbho0NCY9OX5pxGpWIwKlZJHSb9Q5Gpjrc8xOcXFOklLFiy=w563-h426-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Xcodeで「An unknown error has occurred」が出て実機にインストールできないとき</title><link>https://blog.piyo.tech/posts/2018-05-17-xcode-unknown-error/</link><pubDate>Thu, 17 May 2018 06:54:40 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-17-xcode-unknown-error/</guid><description>&lt;p&gt;実機デバッグしようとしたらアプリの起動時にエラーになることが稀によくありますよね。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/VRBkYB1R_iQSUnRSW4ePn_Bt5a9oCOpPXRTE9QMZVwuHY9t_JF-r-JJGjOKiiGn7Y2KfFuvjJhMoFvyt6fWA02BLIrK4tOG1KV_qGnOhr-0ruIn1jdasfkRiIvFWHdT4wMRz19AAdot1qaHpoIwpdLEl70Wq5mReasHkXccqGhKY6tnXZn5NmpE9S3ZsHfCUxMXvBQexK_5ipGucXDWbqMSyg3x6r8aER_JbGAMpaL0gMIhZqre6Iq3dSOqLKsfanyaco7Arlz6xINdWqPhJIBlePXjhoUZsAdjuL_WauPWDrFWSXH1pccppxKyifs_kNnPdTo56j7LSwPJJT59nRIrqnVxc-gZRaW2MbLZR-NQoagAvEhMR_yxVUjIc0jhGPDE0RFCt8xCqJTHDmV5Ah7c70EB4ZKpayCxmyUeiwuYOKkin189A4YR7k7YO3rq1dBchqPLUzPLW9J149P3mJdT7gT7ERHJXBxvd1Vxr7TiKEVecqYmLKwYyOVcoHr8Z2Tgn3P2vwKRB3sv8q7jughpoa7tKugd0aO9Ie8HzGrA1AgUUc7buaGDLPBIjwXNxTZtwhZVHyefzy9dckgL3qI5uUkAIXnxdhZ_8G2AnlDcYgKggoxfRuxcm7hBk0us59mVS-nCzhjKXlt42CqSdWZlXK_Ty9Me_=w421-h131-no"&gt;&lt;img src="https://lh3.googleusercontent.com/VRBkYB1R_iQSUnRSW4ePn_Bt5a9oCOpPXRTE9QMZVwuHY9t_JF-r-JJGjOKiiGn7Y2KfFuvjJhMoFvyt6fWA02BLIrK4tOG1KV_qGnOhr-0ruIn1jdasfkRiIvFWHdT4wMRz19AAdot1qaHpoIwpdLEl70Wq5mReasHkXccqGhKY6tnXZn5NmpE9S3ZsHfCUxMXvBQexK_5ipGucXDWbqMSyg3x6r8aER_JbGAMpaL0gMIhZqre6Iq3dSOqLKsfanyaco7Arlz6xINdWqPhJIBlePXjhoUZsAdjuL_WauPWDrFWSXH1pccppxKyifs_kNnPdTo56j7LSwPJJT59nRIrqnVxc-gZRaW2MbLZR-NQoagAvEhMR_yxVUjIc0jhGPDE0RFCt8xCqJTHDmV5Ah7c70EB4ZKpayCxmyUeiwuYOKkin189A4YR7k7YO3rq1dBchqPLUzPLW9J149P3mJdT7gT7ERHJXBxvd1Vxr7TiKEVecqYmLKwYyOVcoHr8Z2Tgn3P2vwKRB3sv8q7jughpoa7tKugd0aO9Ie8HzGrA1AgUUc7buaGDLPBIjwXNxTZtwhZVHyefzy9dckgL3qI5uUkAIXnxdhZ_8G2AnlDcYgKggoxfRuxcm7hBk0us59mVS-nCzhjKXlt42CqSdWZlXK_Ty9Me_=w421-h131-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そんなときは一旦デバイスとのペアを解除して再接続すればOKです。&lt;/p&gt;
&lt;p&gt;Xcodeの「Window」メニューから「Devices and Simulators」を選びます。「Shift + Command + 2」でもOK。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/9xxxMSjAiL3MOfHVtrztMtSMH-NDnjIYtRwkVZEOBDZJT_1rMSWZP4DmSuixr1unYhAenjpUm3fyfQU5aR_3miKhZ2DtePQA21r66k3uPpSt4FwQTIZDbw0hruAGSG4j2Iis_eghJb9q1Nbvu0Zb0fBkBxE4XQovKprucrVcueYp-LyiPPSOYQqr6mfWAcEFKiGvFy3dhDgRa3eImSEsUOUYhQntzTEOsEJsuvNzqRpKLKqhIBGIAD9tD070blRc0Z8aSqgHXvgyO5D5JTQcXP2SmJdmFC2K0xb02LsCOMdnYtRt51pUGiBd0OCHs_2hTkIYTjjcpHUSC27Fn900W9MlGQ3BrBtQQYErmlZKFX-xCoU2L6auwtN4vWyLCKa5G0uoSUvfghunTCh1jPeSe7bcVtL907oO8HGmA_VBKDvkGpTyt8Gzvho7-IJR76YwOjU0dSGuh0dEEyhwxsZdpH_bCoL7CuToNdhe7Z_qz11-my7yQVaWuz-D7vL-FrUMyONQd3WeP1sIdx5HxNp5ftGPQv-raEs3su_vLE_sEBV6UECqhwVXjYCNWbFqEYkT48p2GhqrEv4ppWApAkmcYzzi7u2nxZcoiVTPa2eaR5LbRVixMqF10zofpQvQvyShRh0D0SJxJnvjV7wgpXzgTpdXIx-erzPJ=w511-h337-no"&gt;&lt;img src="https://lh3.googleusercontent.com/9xxxMSjAiL3MOfHVtrztMtSMH-NDnjIYtRwkVZEOBDZJT_1rMSWZP4DmSuixr1unYhAenjpUm3fyfQU5aR_3miKhZ2DtePQA21r66k3uPpSt4FwQTIZDbw0hruAGSG4j2Iis_eghJb9q1Nbvu0Zb0fBkBxE4XQovKprucrVcueYp-LyiPPSOYQqr6mfWAcEFKiGvFy3dhDgRa3eImSEsUOUYhQntzTEOsEJsuvNzqRpKLKqhIBGIAD9tD070blRc0Z8aSqgHXvgyO5D5JTQcXP2SmJdmFC2K0xb02LsCOMdnYtRt51pUGiBd0OCHs_2hTkIYTjjcpHUSC27Fn900W9MlGQ3BrBtQQYErmlZKFX-xCoU2L6auwtN4vWyLCKa5G0uoSUvfghunTCh1jPeSe7bcVtL907oO8HGmA_VBKDvkGpTyt8Gzvho7-IJR76YwOjU0dSGuh0dEEyhwxsZdpH_bCoL7CuToNdhe7Z_qz11-my7yQVaWuz-D7vL-FrUMyONQd3WeP1sIdx5HxNp5ftGPQv-raEs3su_vLE_sEBV6UECqhwVXjYCNWbFqEYkT48p2GhqrEv4ppWApAkmcYzzi7u2nxZcoiVTPa2eaR5LbRVixMqF10zofpQvQvyShRh0D0SJxJnvjV7wgpXzgTpdXIx-erzPJ=w511-h337-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そうすっと、こんな風にデバイス一覧があらわれます。対象のデバイスを左側の「connected」のところから選んで右クリックなどでコンテキストメニューを表示。&lt;/p&gt;
&lt;p&gt;こんなメニューがあらわれるので「Unpair Device」します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/0hWwShVna8HXjacC49aJ6BKhJ0F3LFCrc5c12e1LH_epefBupBPWrySw9mcO0TiZt4I8NQI_MoYlSUGH_WKFIwcykE2frUvi23nHT3K9UT2SIUc-kO0ME39VBwPNknbxnwpG5Qi0IXveJTZUxYKVimgcfSw9WBmBuowCEEFoZCeD325WLfFYfKWcfLUmdx5j8q3C6RgeAKGNZEuSHM_H_U7mZ3LZXRUxniDNQ5kBqWH5ck1jsvHZRfQiwYCfu00_B2T9FCrvQG2WfV_Zt7PKip46A_tHNFonnJIbfwX048jUn7zI-WR9LgO65YHi-zL_N1qDqrEBSSE0M_ePL1ycgbTbSiafaO5zEc4ybe3RgLSQ1-1wjH4ip4SfC97MPLKXooDqF9GibNs6YLyUjHOXM6rL-G-q4SJvirLcmuAEoBCSfG7aCwixB--Gkyx_LigKVlK8gj-xy5dGWnUo5Cs3W2Fc7FDrhpTA8gFxwLGJu4SgmCjndhnl4SDF2VqvxE2pyEuRLDHME9MPTdcYthM8nskWtlZXTZmEYNEN1vZ4UyAL0H09crEj8z-ArmhntxWNYdTNJRAqrmdePgRloz_gng6v9YA9nihArPK40HCUeGnLcNNhWrNlm_iNpD81_N2u6qR498F9zwprVEXKKWAnf8cjdLPiIu8f=w284-h127-no"&gt;&lt;img src="https://lh3.googleusercontent.com/0hWwShVna8HXjacC49aJ6BKhJ0F3LFCrc5c12e1LH_epefBupBPWrySw9mcO0TiZt4I8NQI_MoYlSUGH_WKFIwcykE2frUvi23nHT3K9UT2SIUc-kO0ME39VBwPNknbxnwpG5Qi0IXveJTZUxYKVimgcfSw9WBmBuowCEEFoZCeD325WLfFYfKWcfLUmdx5j8q3C6RgeAKGNZEuSHM_H_U7mZ3LZXRUxniDNQ5kBqWH5ck1jsvHZRfQiwYCfu00_B2T9FCrvQG2WfV_Zt7PKip46A_tHNFonnJIbfwX048jUn7zI-WR9LgO65YHi-zL_N1qDqrEBSSE0M_ePL1ycgbTbSiafaO5zEc4ybe3RgLSQ1-1wjH4ip4SfC97MPLKXooDqF9GibNs6YLyUjHOXM6rL-G-q4SJvirLcmuAEoBCSfG7aCwixB--Gkyx_LigKVlK8gj-xy5dGWnUo5Cs3W2Fc7FDrhpTA8gFxwLGJu4SgmCjndhnl4SDF2VqvxE2pyEuRLDHME9MPTdcYthM8nskWtlZXTZmEYNEN1vZ4UyAL0H09crEj8z-ArmhntxWNYdTNJRAqrmdePgRloz_gng6v9YA9nihArPK40HCUeGnLcNNhWrNlm_iNpD81_N2u6qR498F9zwprVEXKKWAnf8cjdLPiIu8f=w284-h127-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これで対象のデバイスを接続し直すとコンピュータを信頼しますか？といったような確認をデバイス側で求められますので、承認してあげます。&lt;/p&gt;
&lt;p&gt;冒頭のエラーはこれで大体直ります。直るのですが、いちいちUSBで接続しなければならず、せっかくの無線インストールが台無しです。&lt;/p&gt;</description></item><item><title>RSpecで失敗したテストだけを対象にできる--only-failuresオプション</title><link>https://blog.piyo.tech/posts/2018-05-16-rspec-only-failures/</link><pubDate>Wed, 16 May 2018 06:19:08 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-16-rspec-only-failures/</guid><description>&lt;p&gt;プロジェクトの根幹ぽいところをちょっと変えたばっかりにテストの半分ぐらいがが失敗してしまって、1箇所直したら全部パスするみたいなことはあるあるなんじゃないかと思います。RSpecでは失敗したテストのみを対象に再実行できるオプションがあるので、それを使うと良いです。&lt;/p&gt;
&lt;p&gt;特にコマンドラインから&lt;code&gt;rspec&lt;/code&gt;コマンドでテストを流している人（＝IDEのサポートがあまりない人）にはオススメです。社内見てると案外使われてないのか？という感じでしたが、僕は超使っているので書いておこうかと。&lt;/p&gt;
&lt;p&gt;まずRSpec3.3以降が必要です。出たのは3年ほど前なので、最近は大丈夫かと思います。&lt;/p&gt;
&lt;p&gt;それと、この機能は最後に実行したテストの実行結果をどこかにとっておく必要があり、それをファイルで実現しているので、その設定が必要です。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;spec_helper.rb&lt;/code&gt;あたりに以下の記述をしてあげると良いです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# spec_helper.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;RSpec&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;configure &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;config&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;example_status_persistence_file_path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;spec/examples.txt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、&lt;code&gt;spec/examples.txt&lt;/code&gt;はソース管理に入れる必要がないので除外しておきます。&lt;/p&gt;
&lt;p&gt;この状態でRSpecを実行してみると、例えば次のようなファイルが生成されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;./spec/models/user_spec.rb[1:1:1:1] | passed | 0.11494 seconds |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;./spec/models/user_spec.rb[1:1:2:1] | failed | 0.1067 seconds |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;./spec/models/user_spec.rb[1:2:1:1] | failed | 0.11267 seconds |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;./spec/models/user_spec.rb[1:2:2:1] | passed | 0.06915 seconds |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;./spec/models/user_spec.rb[1:2:3:1] | passed | 0.08749 seconds |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;./spec/models/user_spec.rb[1:3:1:1:1:1] | passed | 0.16688 seconds |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;./spec/models/user_spec.rb[1:3:1:1:2:1:1] | passed | 0.11628 seconds |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;./spec/models/user_spec.rb[1:3:1:1:2:2:1] | passed | 0.12612 seconds |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;./spec/models/user_spec.rb[1:3:1:1:2:2:2] | passed | 0.10565 seconds |
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;それぞれのテストが&lt;code&gt;passed&lt;/code&gt;なり&lt;code&gt;failed&lt;/code&gt;なりマークされています。&lt;/p&gt;
&lt;p&gt;次の実行時に&lt;code&gt;--only-failures&lt;/code&gt;オプションを付けて同様の&lt;code&gt;failed&lt;/code&gt;とマークされたテストのみが実施されます。例えば↑の例であれば2件しか実行されないので時間短縮になります。&lt;/p&gt;
&lt;p&gt;また、この&lt;code&gt;examples.txt&lt;/code&gt;のようなファイルは都度全て上書きされるわけではなく、rspecの対象ファイルを指定して実行したときに、関連の箇所しか書き換えません。説明がむずい。&lt;/p&gt;
&lt;p&gt;例えば、次のような順番で実行したとします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 全件テスト&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;% rspec
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; user_spec.rbとproject_spec.rbで一部のテストが失敗したとする
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# まずはuser_spec側を修正して再テスト&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;% rspec path/to/user_spec.rb --only-failures
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; user_specのうち失敗したテストを実行
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# project_spec側をテスト&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;% rspec path/to/project_spec.rb --only-failures
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;みたいなときに、最後の&lt;code&gt;project_spec.rb&lt;/code&gt;を対象に実施したときにも、最初の&lt;code&gt;failed&lt;/code&gt;が残っているのでその箇所のみテストを実行できるわけです。&lt;/p&gt;
&lt;p&gt;↑のような全体をテストをしてファイルごとに直して確認していく、というようなことはよくやります。最近ではHeadless Chromeへの移行時に似たようなことを実施しました。&lt;/p&gt;
&lt;p&gt;一応言っておくと、ファイルごとに直していくとその変更が他のテストに影響することもあり得るので最後に全体をテストするのは大事です。&lt;/p&gt;</description></item><item><title>古いMacをHigh Sierraにアップデートしようとして「macOSをインストールできませんでした」</title><link>https://blog.piyo.tech/posts/2018-05-15-macos-update-failure/</link><pubDate>Tue, 15 May 2018 06:53:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-15-macos-update-failure/</guid><description>&lt;p&gt;Yosemiteあたりが入ってるMacbook AirにHigh Sierraを入れようとしたら「macOSをインストールできませんでした」というのが出て再起動ループになってしまいました。&lt;/p&gt;
&lt;p&gt;その時の詳細なエラーのスクショを取っていなくて説明できないのが苦しいところなんですが、インストーラが見つからない、的な内容のエラーが出ていたかと思います。&lt;/p&gt;
&lt;p&gt;幸い再インストールなどせずとも復帰できたのでその手順を簡単に整理しておきます。&lt;/p&gt;
&lt;h2 id="macをリカバリーモードで起動"&gt;Macをリカバリーモードで起動&lt;/h2&gt;
&lt;p&gt;ディスクユーティリティを使用するために、リカバリーモードで起動します。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;電源ボタンを押して Mac の電源を入れた直後、または Macが再起動を始めた直後に、キーボードの「command + R」キーまたは macOS復元のほかのキーの組み合わせを押して、Appleロゴまたは回転する地球儀が表示されるまでそのまま押し続けます。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://support.apple.com/ja-jp/102518" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://cdsassets.apple.com/live/7WUAS350/images/macos/tahoe/locale/ja-jp/macos-tahoe-26-startup-options-recovery-continue.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;macOS復旧から起動する方法 - Apple サポート (日本)&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;macOS復旧は、コンピュータに内蔵されている復旧システムです。macOSの再インストール、起動ディスクの修復／消去、Time Machineバックアップからの復元などを行うためのユーティリティが備わっています。お使いのMacの種類に合わせて、以下の手順に従ってください。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://support.apple.com/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;support.apple.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="first-aid"&gt;First Aid&lt;/h2&gt;
&lt;p&gt;Macintosh HDのディスクを選んでFirst Aidで修復します。30分以上ぐらいの時間がかかった記憶があります。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;3．「ディスクユーティリティ」をクリックして、「続ける」をクリックします。
4．「表示」＞「すべてのデバイスを表示」と選択します。
5．サイドバーで、修復したいディスクを選択します。
6．「First Aid」ボタンをクリックします。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://support.apple.com/ja-jp/guide/disk-utility/dskutl1040/mac" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://help.apple.com/assets/67DB50ACE7954E47050F365E/67DB50AD43BF8DF8FC0635EF/ja_JP/63b375a929be49f56392b603161376bc.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Macのディスクユーティリティでストレージデバイスを修復する&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;ディスクで問題が起きた場合は、Macの「ディスクユーティリティ」を使って検証と修復を実行します。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://support.apple.com/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;support.apple.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="再起動アップデート"&gt;再起動・アップデート&lt;/h2&gt;
&lt;p&gt;この状態で再起動すると通常通りMacが立ち上がるようになります。起動ディスクが切り替わる用な感じなのだと思われます。これで再度ログインして、Mac App StoreからOSアップデートを実施したら動くようになりました。&lt;/p&gt;</description></item><item><title>Bluetoothで記録できる1byoneの体重計買った</title><link>https://blog.piyo.tech/posts/2018-05-14-1byone-scale/</link><pubDate>Mon, 14 May 2018 06:42:15 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-14-1byone-scale/</guid><description>&lt;p&gt;対応のスマホアプリを起動している状態で体重計に乗るとBluetoothでデータを転送してくれて、ヘルスケアアプリにもデータを入れてくれる体重計を買いました。体重増やしたいのできちんとチェックしないといけません。&lt;/p&gt;
&lt;p&gt;1byoneの体重計です。買ったときは3500円ぐらいでした。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B01GFYAZ0O/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/61-4ygU&amp;#43;j5L._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;1byone 体重計 Bluetooth 体組成計 スマホ連動 体脂肪計 smart scale 体重/体脂肪率/体水分率/推定骨量/基礎代謝量/内臓脂肪レベル/BMIなど測定 iOS/Android対応 日本語アプリで健康管理&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;アプリの使い勝手、というか閲覧性は非常に悪いですが、データはある程度の精度できちんと記録されるし、ヘルスケア側に入るので、あとでどうとでも取り出せるのが良いです。&lt;/p&gt;
&lt;p&gt;僕と妻でそれぞれ自分のiPhoneにアプリを入れて使っています。起動している端末に情報が転送されてくるのと、保存するかどうかの確認ダイアログがあるので間違って記録してしまうことはまずないです。&lt;/p&gt;</description></item><item><title>Macアプリをショートカットで起動できるようにするSnap</title><link>https://blog.piyo.tech/posts/2018-05-13-snap-app/</link><pubDate>Sun, 13 May 2018 09:03:37 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-13-snap-app/</guid><description>&lt;p&gt;よく使うアプリはAlfredみたいなランチャーから起動するのが面倒なのでSnapという常駐アプリを使ってショートカットから起動できるようにしています。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://itunes.apple.com/jp/app/snap/id418073146?mt=12" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;itunes.apple.com →&lt;/span&gt;&lt;span&gt;https://itunes.apple.com/jp/app/snap/id418073146?mt=12&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;例えばGoogle Chromeに「ctrl + shift + cmd + c」キーを割り当てていて、ブラウザを起動したいときやフォアグラウンドに持ってきたいときのこのキーを押します。また、フォアグラウンドにいるアプリのショートカットを押すとバックグラウンドに回ってくれます。&lt;/p&gt;
&lt;p&gt;つまり、割り当てたショートカットを入力すると、フォアグラウンド↔バックグラウンドを交互に行き来できます。&lt;/p&gt;
&lt;p&gt;一例を紹介すると、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ctrl+shift+cmd+Space → Emacs&lt;/li&gt;
&lt;li&gt;ctrl+shift+cmd+c → Chrome&lt;/li&gt;
&lt;li&gt;ctrl+shift+cmd+f → Finder&lt;/li&gt;
&lt;li&gt;ctrl+shift+cmd+l → LINE&lt;/li&gt;
&lt;li&gt;ctrl+shift+cmd+z → Franz&lt;/li&gt;
&lt;li&gt;ctrl+shift+cmd+s → Slack&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などなど。&lt;/p&gt;
&lt;p&gt;こんな感じでぱぱっと切り替えられます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/zmQOBZ9D_QbdvDKUD0DTZVpOG_TYG-nOoflTB89zNAaDeTzeVIu_esQC6Apy_EhPq25HnUit-nP8b7YzrwY30ibPuUVac7C0cjea29lMCy1FO_dBP7hu7UmjKUd8VWnL482SBH9qYfhOU1HQpGtrdw97YaACLKhkcvdu8-aeZFmQtbhK6Sxb-CUU_BZQrZc1EGc37RFL4N4j1-uVoy9ntHZYgbB3CM-7KliGkrew0-dhwntkFJ-qT2jsBTDB2_drltXgAdq47DXOSzUW-wZPksy6bnWYo4DMLDvZH9dtgsHLDe8wmJY276zRoLwSOQ8RXyxSfQmx_swgNO0o6i3pAejkAAlTDFdr2dG8bnoNgMnXiiZHiVik9M7thtJusKSsVDvVPj1QbvGrNcy5KrR0cIolgF7trWvNQE_CIyCcX09Ep4WHtxEuKIvs9fSef6N7OGRrkSyMID9-jdubPiYOCyumEczOXtY2flbSH7tE0BXudOxxdocF5tRDEqImqhGbw8dCDDWcASUQ1blEEXw5a9ae7bqK3YDn8vMLCSPshQdlG8MfhB4s56pFtp5OWoeA2_HK33VjwJ7UmtcxCMFxdHNDAVqct37ziK1SxqxysAA8eVK3tRMXh8FH5aAcnz-pVl1EIvfDCVar568ks79ULnLBQ2kEB7egtg=w1290-h681-no"&gt;&lt;img src="https://lh3.googleusercontent.com/zmQOBZ9D_QbdvDKUD0DTZVpOG_TYG-nOoflTB89zNAaDeTzeVIu_esQC6Apy_EhPq25HnUit-nP8b7YzrwY30ibPuUVac7C0cjea29lMCy1FO_dBP7hu7UmjKUd8VWnL482SBH9qYfhOU1HQpGtrdw97YaACLKhkcvdu8-aeZFmQtbhK6Sxb-CUU_BZQrZc1EGc37RFL4N4j1-uVoy9ntHZYgbB3CM-7KliGkrew0-dhwntkFJ-qT2jsBTDB2_drltXgAdq47DXOSzUW-wZPksy6bnWYo4DMLDvZH9dtgsHLDe8wmJY276zRoLwSOQ8RXyxSfQmx_swgNO0o6i3pAejkAAlTDFdr2dG8bnoNgMnXiiZHiVik9M7thtJusKSsVDvVPj1QbvGrNcy5KrR0cIolgF7trWvNQE_CIyCcX09Ep4WHtxEuKIvs9fSef6N7OGRrkSyMID9-jdubPiYOCyumEczOXtY2flbSH7tE0BXudOxxdocF5tRDEqImqhGbw8dCDDWcASUQ1blEEXw5a9ae7bqK3YDn8vMLCSPshQdlG8MfhB4s56pFtp5OWoeA2_HK33VjwJ7UmtcxCMFxdHNDAVqct37ziK1SxqxysAA8eVK3tRMXh8FH5aAcnz-pVl1EIvfDCVar568ks79ULnLBQ2kEB7egtg=w1290-h681-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>fastlane/boardingでTestFlightのベータ版の配布ページが一瞬で作れた</title><link>https://blog.piyo.tech/posts/2018-05-12-testflight-boarding/</link><pubDate>Sat, 12 May 2018 06:18:55 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-12-testflight-boarding/</guid><description>&lt;p&gt;社内用に作ったiPhoneアプリをメンバーに配るのにTestFlightのベータ配布を使いますが、いちいちメールアドレスを使うのが面倒です。Google Playにはオープンベータテストにしておくと参加用のURLから勝手に入ってもらうことができるのに、TestFlightはできないのかな、なんて調べていたら自分でホスティングすれば似たようなことを実現できることがわかりました。&lt;/p&gt;
&lt;p&gt;それが、このツールです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/fastlane/boarding" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/ff43e5527f686ef597c1db727153c5077a430d18ea7fa16f2cdaf05c40c4d663/fastlane/boarding" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - fastlane/boarding: Instantly create a simple signup page for TestFlight beta testers&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Instantly create a simple signup page for TestFlight beta testers - fastlane/boarding&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;boardingはiOS開発者なら名前を聞いたことぐらいはあるであろうfastlaneのツール群のうちの1つで、iTunesConnectのベータテスターへの登録の部分をWebサイト経由で実現してくれるRailsアプリケーションです。&lt;/p&gt;
&lt;p&gt;RailsアプリなのでHerokuへデプロイするのが容易なのですが、boardingではREADMEにDeploy to Herokuボタンがあるおかげで本当に一瞬でサイトを作ることができました。&lt;/p&gt;
&lt;p&gt;予め用意しておくのはこのあたりです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Heroku アカウント&lt;/li&gt;
&lt;li&gt;iTunesConnectのアカウント情報&lt;/li&gt;
&lt;li&gt;アプリのBundle ID&lt;/li&gt;
&lt;li&gt;チーム名（複数組織に所属している場合）&lt;/li&gt;
&lt;li&gt;テスターを追加するチーム名←後述&lt;/li&gt;
&lt;li&gt;登録の際に必要なパスワード&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;チーム名ですが、今回は外部テスターという名前でチームを作りそこに追加しました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Jhb92NsbOUvZEZk4AIUl2yQ7DSyWKmIEEkKC3YCxIKUn5RsajCgOZxRH2LiZSCu7Gxr2l32HoZ2rsV9BKPx1KTMIQCHDMzEyL6QyOXjkGS3I8QOmWId3FshiW6Ipx-o8lPJdYGjouJz0X0nhTFLGVbtYhZ4l3vPkY-hBS1kguh1CvW8hqd_gWTrZC3gqR_iw3O4KZygrwDA2nmQ56tAPo1vB2KsNA8GLVQHoaWsSeSdkZe94pCJcj8Ian2Tny5I_lhsbc4htL-v6B0eaMY_JwoBuk5NYVxHF5gqQZz_DPogf8DThRk5WG7EWo20BPf_zmBkJd6_iYV4cNMs1ivQbMeSmmdGG9dfvGk1JZkIBxrYk2cE8CzW1rCzGBuXqYeRgY16eOKwVbg3oby9P8W1zR4dnig21j4tCWWEK8oomO04nVWAOiChCTiunuLQsy-W1K8Cg6IQRDgijbWgFm-BK3kDz-b789QwbRu19KO2UG_RhG9TljELx4Wi0-tRq_bQzF6CVSUTe35pjWasdpDwe_FYzHy9ToycH9dfKD8f42AOqrS46z2FOIjMOwUN2xRh9kXDEchnwYxEggC-8Ydm5SWqdiL0OA_zGvzZDuZYOCqp4nGOwigmd3WwrC5bL8ObRob4iP-GWQSuhhc-vqlnkP4rNpWqfFMz2Rg=w275-h496-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Jhb92NsbOUvZEZk4AIUl2yQ7DSyWKmIEEkKC3YCxIKUn5RsajCgOZxRH2LiZSCu7Gxr2l32HoZ2rsV9BKPx1KTMIQCHDMzEyL6QyOXjkGS3I8QOmWId3FshiW6Ipx-o8lPJdYGjouJz0X0nhTFLGVbtYhZ4l3vPkY-hBS1kguh1CvW8hqd_gWTrZC3gqR_iw3O4KZygrwDA2nmQ56tAPo1vB2KsNA8GLVQHoaWsSeSdkZe94pCJcj8Ian2Tny5I_lhsbc4htL-v6B0eaMY_JwoBuk5NYVxHF5gqQZz_DPogf8DThRk5WG7EWo20BPf_zmBkJd6_iYV4cNMs1ivQbMeSmmdGG9dfvGk1JZkIBxrYk2cE8CzW1rCzGBuXqYeRgY16eOKwVbg3oby9P8W1zR4dnig21j4tCWWEK8oomO04nVWAOiChCTiunuLQsy-W1K8Cg6IQRDgijbWgFm-BK3kDz-b789QwbRu19KO2UG_RhG9TljELx4Wi0-tRq_bQzF6CVSUTe35pjWasdpDwe_FYzHy9ToycH9dfKD8f42AOqrS46z2FOIjMOwUN2xRh9kXDEchnwYxEggC-8Ydm5SWqdiL0OA_zGvzZDuZYOCqp4nGOwigmd3WwrC5bL8ObRob4iP-GWQSuhhc-vqlnkP4rNpWqfFMz2Rg=w275-h496-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Deploy to Herokuボタンを押すとHerokuのアプリ作成画面へ移動します。そこで↑で用意した値を環境変数に設定しておきます。僕は画像に文字を入れた箇所を入力しました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/YPrD29EfDWgO_eJi6slPoBdCaDrBF2cwfKJvFAXQatznIcJ5NWJMVfY9vcX2YbC4QCWsxXolXjm4DyuPUx8xUqdUfIXqIp0sJdxGVZD2ZhgcfWMOX9rD4Ah_qZ2qcMmK603K0LicqyYiD_OglIERjlUreSIy_swDW3MVTmh3apREV8tc420pKNZrXwQ_I9hN49XF3XFd9hEuFA28K2ecKe5xa4bDqT6UduPVW2oTWVghQHvUOHlmEMrDhkwhBomLBjoHJBv79AwH6xJOcrupvsyjVzW3IoZEb1EoYaBbqVRZkeEa3A7ZJK5SGjVljjfD-zfpNRlpoJ_Un7y40I9JO1JYhnG6RAHSoD4Zh87wVA0TtOqYD6EmNPgJ1F5945YJsf2Ez0pX35-Cki_IQT8FQgeBO0FS-C5pOgNAQHAjgeZ0xMf-y3EpxHW8jM8cY0rufZQ0k0GP0IROBd5sSfvdBd-AhJcW5emKfrAkzl1tYfLZOn3K6qu6dqws6mJ9l9ykCKylY9GbfTrA0y8aqtc33t_NarK6mLsw-JLMXSWdu_UMTsGOBommMqdlnFLlYB7iR_2uMWwGAIgR2nyOlgAcx08jBTpOu4sepJ3bZCpzIOBO6uksVCX3SzO-dXVeb5tmRVWcYlVjCpX6jXawGwK8_rIKtBwJxW--Lw=w429-h883-no"&gt;&lt;img src="https://lh3.googleusercontent.com/YPrD29EfDWgO_eJi6slPoBdCaDrBF2cwfKJvFAXQatznIcJ5NWJMVfY9vcX2YbC4QCWsxXolXjm4DyuPUx8xUqdUfIXqIp0sJdxGVZD2ZhgcfWMOX9rD4Ah_qZ2qcMmK603K0LicqyYiD_OglIERjlUreSIy_swDW3MVTmh3apREV8tc420pKNZrXwQ_I9hN49XF3XFd9hEuFA28K2ecKe5xa4bDqT6UduPVW2oTWVghQHvUOHlmEMrDhkwhBomLBjoHJBv79AwH6xJOcrupvsyjVzW3IoZEb1EoYaBbqVRZkeEa3A7ZJK5SGjVljjfD-zfpNRlpoJ_Un7y40I9JO1JYhnG6RAHSoD4Zh87wVA0TtOqYD6EmNPgJ1F5945YJsf2Ez0pX35-Cki_IQT8FQgeBO0FS-C5pOgNAQHAjgeZ0xMf-y3EpxHW8jM8cY0rufZQ0k0GP0IROBd5sSfvdBd-AhJcW5emKfrAkzl1tYfLZOn3K6qu6dqws6mJ9l9ykCKylY9GbfTrA0y8aqtc33t_NarK6mLsw-JLMXSWdu_UMTsGOBommMqdlnFLlYB7iR_2uMWwGAIgR2nyOlgAcx08jBTpOu4sepJ3bZCpzIOBO6uksVCX3SzO-dXVeb5tmRVWcYlVjCpX6jXawGwK8_rIKtBwJxW--Lw=w429-h883-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;パスワードなどを入れるので若干怖いかもですが、アカウントを乗っ取られない限り大丈夫です。心配なら2 Factor Authの設定をしておくとよいです。&lt;/p&gt;
&lt;p&gt;環境変数の入力が終わったら画面一番下のDeploy appボタンを押すとHeroku側の設定が始まるので数分待ちます。これが終わったらもうサイトが出来上がっていて、登録もできるようになっています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/pmLyMtIHIlVBX8X1FKReXDWNQFn1iIb46OVSy99fhAnJDCJc5mGgJ5jwxcMXIrlt-gTPh6jaB2s475K1ZUjd9vfpdPXJnvwXE024TS_nfpN9f6o6lCBAiF8y2LHmsqkeyx4Dfa3d1DstGswPnGrz-nHx9V5uXJ7zJEw-L6lCu4kgT6ly0Oz9CmpXXzNvPsJjDrbn-d8BWiEje5pgHVymMzRvgrhkBtgvduwOvuNFBhEW6nqXrt2fpWnQ2JprcLPlATdpik4g6LvcN-dxKkAdgHUGw8YufGxe54z3lCxOgpUisczmkcW7d5kt_fsPEQD-71yWpSn-J5_1HiFhXuRPfSaDEcgvl2xQQ5oezrTPYJ7r_8LsgMe_y4S5pnogGL3UVjGdcrv7xFl6BxMoXMiQUBB4WEKv19SDzipWuVy_zHcNhNqXVDtKKM_tD9P5tinEBFvx1RJEKm3BoTmzPntHitaOgUOgu5X9UV1c_Ct2oaOjk73AO59eH76zvXRZOLfopW_D5KwsfBfoEjlGC5enUq99hCaIHq8wI6ylh-A-Y0KDo_9yaP86EH-jHd-vco8ym_oUVFfm8fdIjFYQWQQxc0V-qAtlUgD_5JpPs0pGg2Gw5qMfSi4OeL_kWiBQcAfGgYICAE4X3TE6Ipw0oxT8OlqonzIdupbGBg=w1560-h780-no"&gt;&lt;img src="https://lh3.googleusercontent.com/pmLyMtIHIlVBX8X1FKReXDWNQFn1iIb46OVSy99fhAnJDCJc5mGgJ5jwxcMXIrlt-gTPh6jaB2s475K1ZUjd9vfpdPXJnvwXE024TS_nfpN9f6o6lCBAiF8y2LHmsqkeyx4Dfa3d1DstGswPnGrz-nHx9V5uXJ7zJEw-L6lCu4kgT6ly0Oz9CmpXXzNvPsJjDrbn-d8BWiEje5pgHVymMzRvgrhkBtgvduwOvuNFBhEW6nqXrt2fpWnQ2JprcLPlATdpik4g6LvcN-dxKkAdgHUGw8YufGxe54z3lCxOgpUisczmkcW7d5kt_fsPEQD-71yWpSn-J5_1HiFhXuRPfSaDEcgvl2xQQ5oezrTPYJ7r_8LsgMe_y4S5pnogGL3UVjGdcrv7xFl6BxMoXMiQUBB4WEKv19SDzipWuVy_zHcNhNqXVDtKKM_tD9P5tinEBFvx1RJEKm3BoTmzPntHitaOgUOgu5X9UV1c_Ct2oaOjk73AO59eH76zvXRZOLfopW_D5KwsfBfoEjlGC5enUq99hCaIHq8wI6ylh-A-Y0KDo_9yaP86EH-jHd-vco8ym_oUVFfm8fdIjFYQWQQxc0V-qAtlUgD_5JpPs0pGg2Gw5qMfSi4OeL_kWiBQcAfGgYICAE4X3TE6Ipw0oxT8OlqonzIdupbGBg=w1560-h780-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;こんな感じの画面ができあがって、メールアドレスを入力してサブミットするとTestFlightからの招待メールが本当に届きました。&lt;/p&gt;
&lt;p&gt;Herokuのアカウントさえ持っていれば本当に一瞬で作れたので驚きました。&lt;/p&gt;</description></item><item><title>React NativeでAppleのヘルスケアデータを取得する</title><link>https://blog.piyo.tech/posts/2018-05-11-healthkit-react-native/</link><pubDate>Fri, 11 May 2018 06:33:40 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-11-healthkit-react-native/</guid><description>&lt;p&gt;React Nativeでヘルスケアに入っているデータを読み出せるかということを調査したので軽くまとめます。幸い睡眠や体重を記録しているのでそのデータを使って試してみました。&lt;/p&gt;
&lt;p&gt;React Nativeのライブラリとしてはこちらを利用しました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/terrillo/rn-apple-healthkit"&gt;terrillo/rn-apple-healthkit: A React Native package for interacting with Apple HealthKit&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;↓というのもあったのですが、&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/GregWilson/react-native-apple-healthkit"&gt;GregWilson/react-native-apple-healthkit: A React Native bridge module for interacting with Apple HealthKit data&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;This package is undergoing a new direction.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;Please submit issues and pull request to terrillo/rn-apple-healthkit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とのことで、&lt;code&gt;rn-apple-healthkit&lt;/code&gt;を使えばいいみたいです。&lt;/p&gt;
&lt;h1 id="導入編"&gt;導入編&lt;/h1&gt;
&lt;p&gt;導入は4ステップです。&lt;/p&gt;
&lt;p&gt;まずはライブラリを追加。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% npm install rn-apple-healthkit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次にリンク。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% react-native link rn-apple-healthkit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;3番目に&lt;code&gt;Info.plit&lt;/code&gt;にパーミッション関係のメッセージを入れておきます。これがないとアプリが落ちるはずです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;NSHealthShareUsageDescription&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;Read and understand health data.&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;NSHealthUpdateUsageDescription&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;Share workout data with other apps.&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最後に、&lt;code&gt;ios&lt;/code&gt;ディレクトリ以下のXcodeプロジェクト開いて、&lt;code&gt;Capabilities&lt;/code&gt;から&lt;code&gt;HealthKit&lt;/code&gt;をONにしましょう。READMEにも書いてあります。これがないと動きません。&lt;/p&gt;
&lt;h1 id="利用編"&gt;利用編&lt;/h1&gt;
&lt;h2 id="権限のリクエスト"&gt;権限のリクエスト&lt;/h2&gt;
&lt;p&gt;HealthKitへのアクセスをする前に、ユーザーに許可を求めるステップが必要です。ひとまずサンプル的に書くため、起動後に実行できるよう、React Nativeのルートコンポーネントと同じ場所に書いておきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AppleHealthKit&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;rn-apple-healthkit&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PERMS&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AppleHealthKit&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Constants&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Permissions&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;options&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;permissions&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;read&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#a6e22e"&gt;PERMS&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StepCount&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;PERMS&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Weight&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;PERMS&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;SleepAnalysis&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;AppleHealthKit&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;initHealthKit&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;options&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;results&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;error initializing Healthkit: &amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;results&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="データの取得"&gt;データの取得&lt;/h2&gt;
&lt;h3 id="体重"&gt;体重&lt;/h3&gt;
&lt;p&gt;例えば体重ならこんな感じで&lt;code&gt;getWeightSamples&lt;/code&gt;にオプションを渡すと指定した期間のデータが返ってきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AppleHealthKit&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;rn-apple-healthkit&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UNITS&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AppleHealthKit&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Constants&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Units&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;options&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;unit&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UNITS&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;gram&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;startDate&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Date(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;toISOString&lt;/span&gt;(), &lt;span style="color:#75715e"&gt;// 5月1日以降
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;AppleHealthKit&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getWeightSamples&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;options&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;results&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;results&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;余談ですが、JavascriptのDateはmonthの範囲が0~11であることをすっかり忘れていて、最初次のように書いていてデータが取れずしばらくハマリました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Date(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// これだと2018年6月1日になる
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;getWeightSamples&lt;/code&gt;のコードの&lt;code&gt;results&lt;/code&gt;にはこんな感じでオブジェクトが入ってきます。（Hugoの処理のせいか、変な&lt;code&gt;{1}&lt;/code&gt;っていうのが入るのはなんだろう…？あとで直します）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;startDate:&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;2018-05-08T07:09:51.974+0900&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;endDate:&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;2018-05-08T07:09:51.974+0900&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;value:&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;58799.9992370605&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;単位指定しないとポンドで来ちゃうから&lt;code&gt;gram&lt;/code&gt;に変更してます。&lt;/p&gt;
&lt;h3 id="睡眠"&gt;睡眠&lt;/h3&gt;
&lt;p&gt;睡眠はほぼ同じような感じで取れました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;options&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;startDate&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Date(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;toISOString&lt;/span&gt;(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;AppleHealthKit&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getSleepSamples&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;options&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;results&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;results&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;results&lt;/code&gt;にはこんな具合で、&lt;code&gt;INBET&lt;/code&gt;とか&lt;code&gt;ASLEEP&lt;/code&gt;といったステータスとその時間が返ってきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;startDate:&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;2018-05-07T01:14:00.000+0900&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;endDate:&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;2018-05-07T07:14:00.000+0900&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;value:&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;INBED&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;startDate:&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;2018-05-07T06:57:00.000+0900&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;endDate:&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;2018-05-07T07:14:00.000+0900&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;value:&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ASLEEP&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ヘルスケアアプリで見ると&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;INBED は就寝&lt;/li&gt;
&lt;li&gt;ASLEEP は睡眠&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;となっているようで、眠っているときと寝ようとしているときとでステータスを分けられるようです。&lt;/p&gt;
&lt;h1 id="サンプルアプリ"&gt;サンプルアプリ&lt;/h1&gt;
&lt;p&gt;動くと思われるアプリをGitHubに置いておきました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/pi-chan/RNHealthKitSample" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/52c68868c682a3a96028956dabbb7859d4effd65503d4436144a9cb0f8fea496/pi-chan/RNHealthKitSample" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - pi-chan/RNHealthKitSample: rn-apple-healthkit sample app&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;rn-apple-healthkit sample app. Contribute to pi-chan/RNHealthKitSample development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>Apple Watchで睡眠を記録して2ヶ月ぐらい経った</title><link>https://blog.piyo.tech/posts/2018-05-10-auto-sleep/</link><pubDate>Thu, 10 May 2018 06:01:19 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-10-auto-sleep/</guid><description>&lt;p&gt;眠るのが得意ではなく、ちゃんと眠れたかもよくわからないのでApple Watchとこちらのアプリを使って睡眠を記録してみました。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://itunes.apple.com/jp/app/id1164801111?mt=8" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;itunes.apple.com →&lt;/span&gt;&lt;span&gt;https://itunes.apple.com/jp/app/id1164801111?mt=8&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;使い始めるのはすごく簡単で、アプリを入れてヘルスケアへのアクセスを許可してあげるだけで利用を開始できました。&lt;/p&gt;
&lt;p&gt;だけどより凝った設定、パーソナライズした設定をできるようになっていて、検出精度を調整していくことができますし、iPhone操作中は起きているとみなすような設定をしたり、あとからデータを修正したりすることもできて、大変便利です。&lt;/p&gt;
&lt;p&gt;僕は睡眠の判定を少し緩めに変えていたような気がします。&lt;/p&gt;
&lt;p&gt;アプリでは&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;入眠時刻&lt;/li&gt;
&lt;li&gt;起床時刻&lt;/li&gt;
&lt;li&gt;深い睡眠/良質な睡眠の時間&lt;/li&gt;
&lt;li&gt;心拍数&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などなど、色々な情報を一覧できます。&lt;/p&gt;
&lt;h2 id="メイン画面その日の睡眠"&gt;メイン画面（その日の睡眠）&lt;/h2&gt;
&lt;p&gt;何時に寝て何時に起きて睡眠の質はどうだったのかがわかる、起動直後の画面です。&lt;/p&gt;
&lt;p&gt;この日は夜中に子どもに起こされてトイレに付き合ってあげたあと、しばらく眠れなかった様子がちゃんと記録されています。深い睡眠、14分はきついですね。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/5IEIz7ukLSlwG_WChVuRwdrDNf4UpQuc6X2VUTPj7t8a3c_6Rrv8wgLeXatmdnjkEchlbF5XatnHMKqYTaulj9Ts845rWnjStoaARmUz0kt_NXDDO9rujMZfmVaAw07MouydeAGFG6jvpBhmh4IdRYXD0PqDRjyyJgzHQ1U7V9RSAjSWS1TYOdeREiKsRWaP2qt_w5bsdv-wwWCscjJxFFBDSSFW-w40uFNMM3JTTQA6oAqrRfnRi6H1vE7q-m-eKuMHs9U6H-GQWNoTvIU8wBHnO8f8NaPSktP59K76cEQ2z7yZpJWycOVbl22t-jylUa8rLnDG-AL1tAtJnN1Hr2m0aSr7YQ613TTeB9wdmeI1W6CGv_5TTkp6jSKRDLMUteZ06d77GlfRXhpHRsfRqHNyA1rFOre43Jv-IUTEy736u6QWFtgIAYGknN6rw5q9_0X8iM4N-Thke1NsT4oYbiY3zUNxoDYGA5rYv7RKEwmC9fMPC9Odhj5txWycTEstPzocZPRguc4lhBZa92_j1uKffgZOwFYfRrEyk0DegN8idnSuENO5QLj_RMSF-htr_uIoiuqxF-22kVErmS7AXan3lxGbw0zt1vslD2If7h4jiTXIus1vAMM81chzGQZ_VfXrqIfRljYwnebgA5THhY7XPpKEjH8oGg=w429-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/5IEIz7ukLSlwG_WChVuRwdrDNf4UpQuc6X2VUTPj7t8a3c_6Rrv8wgLeXatmdnjkEchlbF5XatnHMKqYTaulj9Ts845rWnjStoaARmUz0kt_NXDDO9rujMZfmVaAw07MouydeAGFG6jvpBhmh4IdRYXD0PqDRjyyJgzHQ1U7V9RSAjSWS1TYOdeREiKsRWaP2qt_w5bsdv-wwWCscjJxFFBDSSFW-w40uFNMM3JTTQA6oAqrRfnRi6H1vE7q-m-eKuMHs9U6H-GQWNoTvIU8wBHnO8f8NaPSktP59K76cEQ2z7yZpJWycOVbl22t-jylUa8rLnDG-AL1tAtJnN1Hr2m0aSr7YQ613TTeB9wdmeI1W6CGv_5TTkp6jSKRDLMUteZ06d77GlfRXhpHRsfRqHNyA1rFOre43Jv-IUTEy736u6QWFtgIAYGknN6rw5q9_0X8iM4N-Thke1NsT4oYbiY3zUNxoDYGA5rYv7RKEwmC9fMPC9Odhj5txWycTEstPzocZPRguc4lhBZa92_j1uKffgZOwFYfRrEyk0DegN8idnSuENO5QLj_RMSF-htr_uIoiuqxF-22kVErmS7AXan3lxGbw0zt1vslD2If7h4jiTXIus1vAMM81chzGQZ_VfXrqIfRljYwnebgA5THhY7XPpKEjH8oGg=w429-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="履歴画面"&gt;履歴画面&lt;/h2&gt;
&lt;p&gt;ここではマンスリービューで過去の睡眠時間とその割合を一覧できます。日をタップすると画面下から詳細なビューが出てきて深い眠りの割合なんかを確認できます。&lt;/p&gt;
&lt;p&gt;7時間以上の睡眠が緑色になるようで、僕の場合は7時間寝られている日は月の3分の1程度だということがわかります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/wxScdu2pp6bzN9t9G96hU91xx5ePL9PoQoEbp-C1auc2eDeTUUsflphTth76q-_fQm-R3VawAjZ6AWrPhebCVaHU1gok8uO3iQ8XRSoMoXL1V6ucxxHQFo6aPzL8MEpCTipfwkxApMBNyYbXm_aMEzUeyvI3UkCc36laMVpMktdbyUMyoex6VqYFXAF4vFunWh8xa9NkMGAvUhvYkR3_5rSq8LoZAKZSoWMBqH1ZyEM_uNmvn41-h7paSeqiDambQr2gdzAv4_tIVHJ7cl3qdnfhuJEiccm1P68CLWGqAafWjgQUrNy3C1ttfINlGuOcdjGVzkdAg7NZQBmv1NNeRcoR4GMt4tpspqV7WJmm48nOOeHXFVtWjYs4PkpEpMFixitinMQc7gutyXzlBg87TIOBmslf8lHCLNtAvRDwIxq777S_Y3UmLCYBPVo4i67divetdrFIxByDtalszUpYXbk3jidrIzba0Zk-BuIN9eFyerVmLWFZFLGkntlkdpOuDB9Rwd0qxzXbMvrWrXLNhRqUUcA1m-HFBo_8cZoa9jZZdZO_pilVV3sLSCNV8uDZwOAhTgS67duEUR9H7AaVpVes6Fef-0j__2eNxW54QU3iSPB8ywnltaao1jETOdhRQ3zPopp4DuP2Qf1ScL1uw-aFScZAqL3fTg=w429-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/wxScdu2pp6bzN9t9G96hU91xx5ePL9PoQoEbp-C1auc2eDeTUUsflphTth76q-_fQm-R3VawAjZ6AWrPhebCVaHU1gok8uO3iQ8XRSoMoXL1V6ucxxHQFo6aPzL8MEpCTipfwkxApMBNyYbXm_aMEzUeyvI3UkCc36laMVpMktdbyUMyoex6VqYFXAF4vFunWh8xa9NkMGAvUhvYkR3_5rSq8LoZAKZSoWMBqH1ZyEM_uNmvn41-h7paSeqiDambQr2gdzAv4_tIVHJ7cl3qdnfhuJEiccm1P68CLWGqAafWjgQUrNy3C1ttfINlGuOcdjGVzkdAg7NZQBmv1NNeRcoR4GMt4tpspqV7WJmm48nOOeHXFVtWjYs4PkpEpMFixitinMQc7gutyXzlBg87TIOBmslf8lHCLNtAvRDwIxq777S_Y3UmLCYBPVo4i67divetdrFIxByDtalszUpYXbk3jidrIzba0Zk-BuIN9eFyerVmLWFZFLGkntlkdpOuDB9Rwd0qxzXbMvrWrXLNhRqUUcA1m-HFBo_8cZoa9jZZdZO_pilVV3sLSCNV8uDZwOAhTgS67duEUR9H7AaVpVes6Fef-0j__2eNxW54QU3iSPB8ywnltaao1jETOdhRQ3zPopp4DuP2Qf1ScL1uw-aFScZAqL3fTg=w429-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="別の日時ビュー"&gt;別の日時ビュー&lt;/h2&gt;
&lt;p&gt;別の見方のビューも提供されています（が、あまり使わないかな…）&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/3y2hOYwhM5SqZqNk9fsLq7xqHzBkCUDO_tIYiUtz1UGNxaXIgnTKEFHe_HQzJC8WwbFqx6MiI1xZSM1U22KJI_Nv7C1NrAEjs2EFanwzm3MoKV4ddpFHkziM-9YR0FiaWNhIzVaSm3ZTg6UYUjs_mXzf6hbG1-izFs2fdP-cuNpnQuzja5qjpL-oU327PmFIUafni4BgiwG6G2I7pi6aKoDc0rlef14XXUrSiCYmJAQn3z_It9v1gwUim6ljmKYQY8Lxz1i5y8hVqRaSeIs4vZae4pSNN3EZxeDVf5Ry1axSNQTedJTN8p4kfn438PJKniya4lytlJLD713NcJDG6R7_byFAPw8QVaQTp_3FbGaUYm-00k3MrDb2Af0trHY1xufAUkJqjeibnMeoa8I4yfiI12FL92htsdLTCcxe683FFWSr9ucQLzElwlj46-Xpv3-CjLru4Us8D0iKkleq6vzpm1Mhqme_1GUwjm4B9QGQnysaSWawGhewP28egH00gKRxg59F0bCpty9P8rak4MIUkqcfvYHxV_FQrzBBg4UeICguHdrtSSLuOASysAn4QOZBCVzVKKhrigMtA2lYVqR5VczssQvCjI6sts9jrjpP8wWgSi7cY4-A3_B8z_yInFgJRUSosWEICHyrTnP6YQbYUeRkolB03g=w429-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/3y2hOYwhM5SqZqNk9fsLq7xqHzBkCUDO_tIYiUtz1UGNxaXIgnTKEFHe_HQzJC8WwbFqx6MiI1xZSM1U22KJI_Nv7C1NrAEjs2EFanwzm3MoKV4ddpFHkziM-9YR0FiaWNhIzVaSm3ZTg6UYUjs_mXzf6hbG1-izFs2fdP-cuNpnQuzja5qjpL-oU327PmFIUafni4BgiwG6G2I7pi6aKoDc0rlef14XXUrSiCYmJAQn3z_It9v1gwUim6ljmKYQY8Lxz1i5y8hVqRaSeIs4vZae4pSNN3EZxeDVf5Ry1axSNQTedJTN8p4kfn438PJKniya4lytlJLD713NcJDG6R7_byFAPw8QVaQTp_3FbGaUYm-00k3MrDb2Af0trHY1xufAUkJqjeibnMeoa8I4yfiI12FL92htsdLTCcxe683FFWSr9ucQLzElwlj46-Xpv3-CjLru4Us8D0iKkleq6vzpm1Mhqme_1GUwjm4B9QGQnysaSWawGhewP28egH00gKRxg59F0bCpty9P8rak4MIUkqcfvYHxV_FQrzBBg4UeICguHdrtSSLuOASysAn4QOZBCVzVKKhrigMtA2lYVqR5VczssQvCjI6sts9jrjpP8wWgSi7cY4-A3_B8z_yInFgJRUSosWEICHyrTnP6YQbYUeRkolB03g=w429-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;とにかく、欲しい情報は各種ビューで大抵確認できるわけです。&lt;/p&gt;
&lt;h2 id="ヘルスケアと同期"&gt;ヘルスケアと同期&lt;/h2&gt;
&lt;p&gt;Appleのヘルスケアアプリにもデータが同期されているので、別のアプリから活用するなんてことも可能になります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/h3V5u8LJQpSxzXTbVzYwzKRohhGJO-qdEMlin_lxqzaBp7ui5ElBOeMbgjpWYIp-JXTCFYf4rLdqKuKRtNAaww46dquOHOSDRG_jdNBkUxVbLyhu44C2Xq2BDB2HDgzld1vFpmz_mom_fp6-gdqzhEV-xqBQd3azZMSl5L-EtfFDPz_XepsJDbyf8tbNrHgMcTfW7yJTFA_FtMmDJ9frqyZqwr70SoyJNrBPOfVbVCyCKYP4s_7gwPkFNodFQdSgdqHaaoxEogAVjPkaaimgZq6KWK7yhzR9263fbiqbS2ycAVpf0MyqbIxTec0SZjoUIyv6dTkY9V_8z81cV0XyOd6HMEhej8YWu3xXo4jFXLDuS1p2HPqBIa_73oTq4-qZcbhklUCmGvYjtxDB-tmf8KwPfea6YEfMyG5G8QzWCGTuVDwob8H1983tO0ZeQaiW1l-joYlq93kfc0g_HDXbqpCsHFN-hktacyVGxrl2tq4itYsoI1E7hG0-aUaJUvLoPj38IP7DPwsUj57Kkzjm9vvkLqmMD9rF1TF0TDQxNigk0V9YFTIs6oOtVMjTsLDsqoFJ0OXz6iSfH-Xkc2TipLpiNYMVnpmeWfHlbMg6F0jEcyz6t8YW6BT-QHUgpg2axGFtKXpoE6pW1z8AHSl2iPKbyMRUeuf2PQ=w674-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/h3V5u8LJQpSxzXTbVzYwzKRohhGJO-qdEMlin_lxqzaBp7ui5ElBOeMbgjpWYIp-JXTCFYf4rLdqKuKRtNAaww46dquOHOSDRG_jdNBkUxVbLyhu44C2Xq2BDB2HDgzld1vFpmz_mom_fp6-gdqzhEV-xqBQd3azZMSl5L-EtfFDPz_XepsJDbyf8tbNrHgMcTfW7yJTFA_FtMmDJ9frqyZqwr70SoyJNrBPOfVbVCyCKYP4s_7gwPkFNodFQdSgdqHaaoxEogAVjPkaaimgZq6KWK7yhzR9263fbiqbS2ycAVpf0MyqbIxTec0SZjoUIyv6dTkY9V_8z81cV0XyOd6HMEhej8YWu3xXo4jFXLDuS1p2HPqBIa_73oTq4-qZcbhklUCmGvYjtxDB-tmf8KwPfea6YEfMyG5G8QzWCGTuVDwob8H1983tO0ZeQaiW1l-joYlq93kfc0g_HDXbqpCsHFN-hktacyVGxrl2tq4itYsoI1E7hG0-aUaJUvLoPj38IP7DPwsUj57Kkzjm9vvkLqmMD9rF1TF0TDQxNigk0V9YFTIs6oOtVMjTsLDsqoFJ0OXz6iSfH-Xkc2TipLpiNYMVnpmeWfHlbMg6F0jEcyz6t8YW6BT-QHUgpg2axGFtKXpoE6pW1z8AHSl2iPKbyMRUeuf2PQ=w674-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Circle CIでHeadless Chrome 解決編</title><link>https://blog.piyo.tech/posts/2018-05-09-chrome-on-circleci/</link><pubDate>Wed, 09 May 2018 06:40:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-09-chrome-on-circleci/</guid><description>&lt;p&gt;CircleCIでHeadless Chromeを使ったテストが動かないっぽい件で、ひとまずunless使ってGemfileを条件分岐するというお行儀の悪いことをしていましたが、もしかしたら直ったような気がするので、改めてメモしておきます。&lt;/p&gt;
&lt;p&gt;前々回の記事と、&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-03-30-chrome-on-circleci/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/G7pKIkwdqr30uWreoaT3NnRbKcWME9s9VeWESZiVt-KUgrVfbw60Ny5fBT9HZfn7dS1_-BQ4CwbgGE_C4RZWuKRRB44AePvViRx5p-MBLmQ38FTeZa1mRtWUi0JfbSPNJyR_phcX--HqVC_AOsRDO4-P6zsG3vzYfjpgVPkdEyrVGvOES__d8mRU1DYz5EgVMBk8t0JR1SDalpwBG8YpUbKSf5Cqrn4BeFZt45dSvV5pEykROCzt7BvlhzkMtcef7WzSPADuMp8o4XEbNPygYGp3RgpLO2rsktOPTV0wVKP5jbOCSJYH3x4E1934S3IoFwy2i3pqA1nqGrKMXqDB3vq3-OLhUYeV8z-yY5MRh2yINn2xUItB3wilnZfNWLq60-gwK2YsFA4fjK2DcnhyFBIuNoGF3z29SeQGPsaUAxNA8Hcosxt7M_mdJa7R7vfZYdZtSNvrYsmqEHqqCL5_ZxuA5VijQAXlAjuP_5XqiVdWQ0eae6eFKPjlRpUm_z5UU4-1BUI4kv-XHucFz-LjCOTWYpEYn_WKSVNx4MUIk4EzaIf1CWcGskyrj3oqfnqKaCvOC3jLFo2cwr4idw_bNGAP-vcHfbTlYYrLOsex9bcZs9_GSdzXTrd0n_JKQ7bW5LjLrm_jUtRplwkdhhnH6ZC0CwMO-6lg0g=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Headless ChromeのテストがCircleCI上で動かなかった - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;おとといの記事でHeadlessChromeを使ってテストするようにしたよ、と書きました。 https://blog.piyo.tech/posts/2018-03-28-headless-chrome/ ですが、CircleCIではこんな感じのエラーを吐いて動きませんでした。 Selenium::WebDriver::Error::SessionNotCreatedError: session not created exception: Chrome version must be &amp;amp;gt;= 64.0.3282.0 どうやら、circleciのイメージに元々入っているchromedriverと、gemとしてインストールしている chromedriver-helper が衝突することによって起こるらしいということがわかりました。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;前回の記事がこのへん。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-04-20-circleci-chromedriver/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/G7pKIkwdqr30uWreoaT3NnRbKcWME9s9VeWESZiVt-KUgrVfbw60Ny5fBT9HZfn7dS1_-BQ4CwbgGE_C4RZWuKRRB44AePvViRx5p-MBLmQ38FTeZa1mRtWUi0JfbSPNJyR_phcX--HqVC_AOsRDO4-P6zsG3vzYfjpgVPkdEyrVGvOES__d8mRU1DYz5EgVMBk8t0JR1SDalpwBG8YpUbKSf5Cqrn4BeFZt45dSvV5pEykROCzt7BvlhzkMtcef7WzSPADuMp8o4XEbNPygYGp3RgpLO2rsktOPTV0wVKP5jbOCSJYH3x4E1934S3IoFwy2i3pqA1nqGrKMXqDB3vq3-OLhUYeV8z-yY5MRh2yINn2xUItB3wilnZfNWLq60-gwK2YsFA4fjK2DcnhyFBIuNoGF3z29SeQGPsaUAxNA8Hcosxt7M_mdJa7R7vfZYdZtSNvrYsmqEHqqCL5_ZxuA5VijQAXlAjuP_5XqiVdWQ0eae6eFKPjlRpUm_z5UU4-1BUI4kv-XHucFz-LjCOTWYpEYn_WKSVNx4MUIk4EzaIf1CWcGskyrj3oqfnqKaCvOC3jLFo2cwr4idw_bNGAP-vcHfbTlYYrLOsex9bcZs9_GSdzXTrd0n_JKQ7bW5LjLrm_jUtRplwkdhhnH6ZC0CwMO-6lg0g=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;[追記あり]再びCircleCIでsession not created exception - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;4/19あたりからCircleCIでまたこのエラーがでるようになりました。 1 session not created exception: Chrome version must be &amp;amp;gt;= 65.0.3325.0 多分、 Gemfile に入れていた chromedriver-helper とDockerイメージに入っているChromeのバージョンが衝突しているのが原因だと思います。以前の調査記事でも書いた内容です。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;そもそもの理由は&lt;code&gt;chromedriver-helper&lt;/code&gt;gemがインストールするchromeドライバーとCircleCIのイメージに入っているChromeのバージョンに整合性がないのがえらーとなっていた理由です。で、Chromeのアップグレードを色々試みたんですが、どうやらこれでいけそうでした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- &lt;span style="color:#f92672"&gt;run&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Install Latest Chrome&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;command&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sudo apt install libappindicator3-1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sudo dpkg -i google-chrome.deb
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sudo sed -i &amp;#39;s|HERE/chrome\&amp;#34;|HERE/chrome\&amp;#34; --disable-setuid-sandbox|g&amp;#39; /opt/google/chrome/google-chrome
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; rm google-chrome.deb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;バージョンの整合性は解決したものの、&lt;code&gt;Chrome failed to start: crashed&lt;/code&gt;のようなエラーが出たりとか、別のプロジェクトで&lt;code&gt;no such session&lt;/code&gt;という話も聞いたりしていたので、テスト用に&lt;code&gt;no-sandbox&lt;/code&gt;オプションを追加してこれらを回避することにしました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://sites.google.com/a/chromium.org/chromedriver/help/chrome-doesn-t-start" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;ログイン - Google アカウント&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;span class="truncate"&gt;sites.google.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;テストで一時的に使うのにセキュリティ上の理由はあまりないはずなので、sandbox外で実行するのは問題ないはず。これで起動しないなどのエラーを回避できたので、ひとまずこれで様子をみたいと思います。&lt;/p&gt;</description></item><item><title>iHerbでONゴールドスタンダードなど15%オフ！明日(5/9)までとのこと</title><link>https://blog.piyo.tech/posts/2018-05-08-iherb-sale/</link><pubDate>Tue, 08 May 2018 06:31:35 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-08-iherb-sale/</guid><description>&lt;p&gt;気づくのがギリギリになっちゃったんですが、5/9までOptimum Nutritionのプロテインなどなどが15%オフらしいです。&lt;/p&gt;
&lt;p&gt;→ &lt;a href="https://iherb.co/4MrevwG1"&gt;https://iherb.co/4MrevwG1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;いつも買ってるものだし、ちょうどなくなってきたので次を買っておこうかな。&lt;/p&gt;
&lt;p&gt;↓こんな風に22種類の味をランキングにしているツワモノもいるみたいです。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="http://kenkono1.com/optimum-ranking/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;kenkono1.com →&lt;/span&gt;&lt;span&gt;http://kenkono1.com/optimum-ranking/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;過去僕は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;クッキークリーム&lt;/li&gt;
&lt;li&gt;ダブルリッチチョコレート&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;と飲んできて、クッキークリームは甘すぎ、チョコはバナナとミキサーすればまあ美味しいけど単品はきつい、という感想でした。&lt;/p&gt;
&lt;p&gt;今回はアイスのなかではバニラが一番好きなこともあるので、バニラアイスクリーム味にチャレンジしてみようと思います。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://iherb.co/36NBswCA"&gt;Optimum Nutrition, Gold Standard 100%ホエイ、バニラアイスクリーム、5 lb (2.27 kg)&lt;/a&gt;&lt;/p&gt;</description></item><item><title>MobXでTodoアプリ[Part3] Storeをデバッグしてみる</title><link>https://blog.piyo.tech/posts/2018-05-07-mobx-app-part3/</link><pubDate>Mon, 07 May 2018 06:27:34 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-07-mobx-app-part3/</guid><description>&lt;p&gt;3部作のPart3です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2018-05-05-mobx-app-part1/"&gt;MobXでTodoアプリ[Part1] MobX導入まで&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2018-05-06-mobx-app-part2/"&gt;MobXでTodoアプリ[Part2] データを保存してみる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MobXでTodoアプリ[Part3] Storeをデバッグしてみる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;前回はMobXのStoreをAsyncStorageを使って永続化する&lt;code&gt;mobx-persist&lt;/code&gt;を使ってみました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-05-06-mobx-app-part2/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/y_i9fp87K99TSZkeLX2ZqCVu9aZ_itzXBB_AI90I1mycnWj72EQPc8YAlSOhDnWqOR-Tq2TNtMf1dIIwIB41o-tEjMH1Ahn90cPMyM-T83elsZBhs66peHCP2VfVWTT4R0OYwI65EU58kiApaDCGtXZLbQpBpg8mw4amb_Pu0o83H9sPVmkb8vDO08dFJoAeBghTwl0RJZFBzLPAvEo1yySRpKa1haI95sy4tF0fQD3H0VZF7yenhWdUvJtHk86DqtZGGZxA1KDPKFQ0MGBn6Q6vM785kgN1rWzWHxjmehqWLagVnwbhhBSukD-6rTB00p714JTqnff0BIK411edZRmzPaCaPzEbeM_i6WmbR6LcWPn-J5U7qn2O5GFjTpNF8ef0gvqD0dww9pNYC6yU1aFoyac9A1BVBzCHO5OoUgOVqn3PzE0fIv_J4twqGMYW2X34-yi11r2ZLbw9bbBGbz4lsuWSoGAyrMPvdwOPGG9eFn5MsLIK_-fMRmSDGeaDTi4yBa4-jw2xAy4HSi1VBSZkThJEuqm8nQdjd1u1Fz2cAtg2rVAdOfomS7FmFR_3i8UxLTUtNtU55U9Yc5wLwtZDOYz80cMG3PEP5g-5sYTEsOQ-fhil_IVIzdI-TCO2bmvTsvO0EwcM9SZXjZnEDFMANWVUPGfq3g=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;MobXでTodoアプリ[Part2] データを保存してみる - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;3部作のPart2です。 MobXでTodoアプリ[Part1] MobX導入まで MobXでTodoアプリ[Part2] データを保存してみる MobXでTodoアプリ[Part3] Storeをデバッグしてみる 前回MobXを導入してStoreにデータを追加すると画面が更新されるところまでできるようになりました。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;アプリケーションとして最低限のところはこれでなんとかなります。あとは開発を円滑に進めるべく、デバッグの方法がわかればOKかと思います。ストアにどんなデータが入っているかを自由に見られるとだいぶ効率が違います。&lt;/p&gt;
&lt;h1 id="デバッグ用アプリ"&gt;デバッグ用アプリ&lt;/h1&gt;
&lt;p&gt;手始めにDebuggerアプリを入れておきます。React NativeはChromeのDeveloperコンソールなんかでもデバッグ可能ですが、スタンドアローンのアプリを入れておくと何かと便利です。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/jhen0409/react-native-debugger" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/84db6b010e940583389868decb2afb47ad53ae0f896e6d6e67a2cf4a797c486c/jhen0409/react-native-debugger" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - jhen0409/react-native-debugger: The standalone app based on official debugger of React Native, and includes React Inspector / Redux DevTools&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;The standalone app based on official debugger of React Native, and includes React Inspector / Redux DevTools - jhen0409/react-native-debugger&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;デバッグ用アプリを起動した状態でここまでのTodoアプリを起動して、デバッグメニュー（iPhoneならcmdキー+dキー）から「Debug JS Remotely」でデバッグを有効にしてみます。アプリとデバッガが接続されますが、↓のようにstateは何も見えていません。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/wQ2rzqRPZPeri2i3qnZtePEum2zu-xnzMymx7u1wxoIet53OOKEXDPj9ZNIL_1mrfBS0H6UyxjX9sGCZRQmioQtPhbQLuu2agzFqMoRStDlr-IBKbLbeKJ1s6fwuyAEuuFMjiXzNW34cePeWsbYeoT3IZDKBfJUSw9BZanFbKmfRWlbd4jTkl-OCMA3CGumS2pd-pZJ4wXS0EVgNv9rYIpRcNs5utNlDLrmSolb5ciGxFAgbzMLAeNBhF1YnvvuUM1d9ibziFKstaDJc6Whn_l1UlPavoUNHJpzmERDW7TXHX8b0oCkB5dD1k7yWTd130hD1JRmB5AEr3WZS97zzN9nXBy-r2-PAbRPhIwjGz8nX8NqdDXDRGyXSLYjQ5GnuvZ5KxCkGdZp0I-wJGqwqgX5TAH9CWEUXh9NxXyBlPrBLAJ6gEoE0yTS6FAGP6B6txMmJHFxvIZZEv8vJJ9EiZGkX9PTowHYRUtF3KjN8jHByPpC_yr9JgR1U8f9dE6G7VIZYHDApTMC_lNbKdH0wGtj8kR_a59cmXLMwkIN-iCFPgXKYAk3fTluwr2fKtMeIQPC3XA34v6qhtV_F7mXPcgT6eBjUzu0V8zafoHwG_F2Uh84un1R4NJeaOX553BqMScHbvu1qROjd4d8zWbCESySFDdB4qPYsDw=w1296-h1646-no"&gt;&lt;img src="https://lh3.googleusercontent.com/wQ2rzqRPZPeri2i3qnZtePEum2zu-xnzMymx7u1wxoIet53OOKEXDPj9ZNIL_1mrfBS0H6UyxjX9sGCZRQmioQtPhbQLuu2agzFqMoRStDlr-IBKbLbeKJ1s6fwuyAEuuFMjiXzNW34cePeWsbYeoT3IZDKBfJUSw9BZanFbKmfRWlbd4jTkl-OCMA3CGumS2pd-pZJ4wXS0EVgNv9rYIpRcNs5utNlDLrmSolb5ciGxFAgbzMLAeNBhF1YnvvuUM1d9ibziFKstaDJc6Whn_l1UlPavoUNHJpzmERDW7TXHX8b0oCkB5dD1k7yWTd130hD1JRmB5AEr3WZS97zzN9nXBy-r2-PAbRPhIwjGz8nX8NqdDXDRGyXSLYjQ5GnuvZ5KxCkGdZp0I-wJGqwqgX5TAH9CWEUXh9NxXyBlPrBLAJ6gEoE0yTS6FAGP6B6txMmJHFxvIZZEv8vJJ9EiZGkX9PTowHYRUtF3KjN8jHByPpC_yr9JgR1U8f9dE6G7VIZYHDApTMC_lNbKdH0wGtj8kR_a59cmXLMwkIN-iCFPgXKYAk3fTluwr2fKtMeIQPC3XA34v6qhtV_F7mXPcgT6eBjUzu0V8zafoHwG_F2Uh84un1R4NJeaOX553BqMScHbvu1qROjd4d8zWbCESySFDdB4qPYsDw=w1296-h1646-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="アプリの変更"&gt;アプリの変更&lt;/h1&gt;
&lt;p&gt;デバッガでstateを閲覧できるようにしていきます。まずはデバッグ用のライブラリを最初にインストール。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% npm install mobx-remotedev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;といきたいところですが、残念ながら&lt;code&gt;mobx-remotedev&lt;/code&gt;のメインブランチでは最新のMobx 4系への対応がありません。開発頻度も落ちているので仕方ないので紹介されていたfork版参照して使ってみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% npm install &lt;span style="color:#e6db74"&gt;&amp;#39;crayonzx/mobx-remotedev#mobx4&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次にデバッガで見たいStoreにデコレータをつけてあげればOK。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;remotedev&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;mobx-remotedev&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;remotedev&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TodoStore&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでサーバーの再起動とアプリのリロードしたら↓のようにstateが表示されます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/b2K5bOkNpSxruFNQhzwoHfKUhdLn3tZwHq9m8B_nVcps5_hx1eHgCYrircj9dsW9Rl3cpP2LpqDX-QAws-8SIPgvJ1_rvR_Cbytb3lHEIneiM_4L2lXXSsEyg6WP-4RHIkvD2y2yXwdQZ6JJuZcmYZ_fPS1VBRkHcNGuX3gyVxvGB5lXGGf96LOBA4jjYdEkTiWP3aL1zTe1jKIZSgk9OpRtRo1YC0Ypr3flDXeLgPVOn3BGCQmiTANil0A-wTRGl7dqUvvTZxH1pkmjjWAHeGV8jC0BIguMW5265VOG0J1-XuOWJJFwG1s6GBuWw1dwi3X-nJDt-ISkvSA_CvimmLkgVJWf3CvgUYCsOVLTckDhSMK3r0_bZoABOVEOL205BrEt6P-Dz6_7ytpk8aS4cuTQAo-vum0EQQZwLuOnq5_ygcnhu2ma9PT9pAZsq4MwH7asizisU1LWfnBKhM0vVTQYlDompvUxuoq_1Bu0iPaGxvqKMMCUPddM2qfiOI-lS1SRU7vQgiA1MoCXWdW6KoZQ7zcdirIQVMgL687M8gSlnNXcQi4jBzwzGCYv7ViqjdV8eh6Mbm90N8nFrIgbuRJzudmtaCmf6ztkSHywHVLBpPYTW5pque0jgtVHWwRXeekiGijaz1lF5ZeYhNCL3pzZMhCAQ1Iacw=w1532-h1630-no"&gt;&lt;img src="https://lh3.googleusercontent.com/b2K5bOkNpSxruFNQhzwoHfKUhdLn3tZwHq9m8B_nVcps5_hx1eHgCYrircj9dsW9Rl3cpP2LpqDX-QAws-8SIPgvJ1_rvR_Cbytb3lHEIneiM_4L2lXXSsEyg6WP-4RHIkvD2y2yXwdQZ6JJuZcmYZ_fPS1VBRkHcNGuX3gyVxvGB5lXGGf96LOBA4jjYdEkTiWP3aL1zTe1jKIZSgk9OpRtRo1YC0Ypr3flDXeLgPVOn3BGCQmiTANil0A-wTRGl7dqUvvTZxH1pkmjjWAHeGV8jC0BIguMW5265VOG0J1-XuOWJJFwG1s6GBuWw1dwi3X-nJDt-ISkvSA_CvimmLkgVJWf3CvgUYCsOVLTckDhSMK3r0_bZoABOVEOL205BrEt6P-Dz6_7ytpk8aS4cuTQAo-vum0EQQZwLuOnq5_ygcnhu2ma9PT9pAZsq4MwH7asizisU1LWfnBKhM0vVTQYlDompvUxuoq_1Bu0iPaGxvqKMMCUPddM2qfiOI-lS1SRU7vQgiA1MoCXWdW6KoZQ7zcdirIQVMgL687M8gSlnNXcQi4jBzwzGCYv7ViqjdV8eh6Mbm90N8nFrIgbuRJzudmtaCmf6ztkSHywHVLBpPYTW5pque0jgtVHWwRXeekiGijaz1lF5ZeYhNCL3pzZMhCAQ1Iacw=w1532-h1630-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;他にもstate全体を見たりデータの変化（アクション）を見たり、Storeに対して色々できる、見られるようになるので必須と言えそうです。&lt;/p&gt;
&lt;p&gt;今日までのソースコードはpart3タグとしてここにおいてあります。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/pi-chan/MobxTodoApp/tree/part3" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/b7c26480ab70e2c1e489c78e67c06cf69ed2b44b4e9b51df51fc6be41a484b39/pi-chan/MobxTodoApp" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - pi-chan/MobxTodoApp at part3&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Contribute to pi-chan/MobxTodoApp development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>MobXでTodoアプリ[Part2] データを保存してみる</title><link>https://blog.piyo.tech/posts/2018-05-06-mobx-app-part2/</link><pubDate>Sun, 06 May 2018 06:54:41 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-06-mobx-app-part2/</guid><description>&lt;p&gt;3部作のPart2です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2018-05-05-mobx-app-part1/"&gt;MobXでTodoアプリ[Part1] MobX導入まで&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MobXでTodoアプリ[Part2] データを保存してみる&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2018-05-07-mobx-app-part3/"&gt;MobXでTodoアプリ[Part3] Storeをデバッグしてみる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;前回MobXを導入してStoreにデータを追加すると画面が更新されるところまでできるようになりました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-05-05-mobx-app-part1/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/y_i9fp87K99TSZkeLX2ZqCVu9aZ_itzXBB_AI90I1mycnWj72EQPc8YAlSOhDnWqOR-Tq2TNtMf1dIIwIB41o-tEjMH1Ahn90cPMyM-T83elsZBhs66peHCP2VfVWTT4R0OYwI65EU58kiApaDCGtXZLbQpBpg8mw4amb_Pu0o83H9sPVmkb8vDO08dFJoAeBghTwl0RJZFBzLPAvEo1yySRpKa1haI95sy4tF0fQD3H0VZF7yenhWdUvJtHk86DqtZGGZxA1KDPKFQ0MGBn6Q6vM785kgN1rWzWHxjmehqWLagVnwbhhBSukD-6rTB00p714JTqnff0BIK411edZRmzPaCaPzEbeM_i6WmbR6LcWPn-J5U7qn2O5GFjTpNF8ef0gvqD0dww9pNYC6yU1aFoyac9A1BVBzCHO5OoUgOVqn3PzE0fIv_J4twqGMYW2X34-yi11r2ZLbw9bbBGbz4lsuWSoGAyrMPvdwOPGG9eFn5MsLIK_-fMRmSDGeaDTi4yBa4-jw2xAy4HSi1VBSZkThJEuqm8nQdjd1u1Fz2cAtg2rVAdOfomS7FmFR_3i8UxLTUtNtU55U9Yc5wLwtZDOYz80cMG3PEP5g-5sYTEsOQ-fhil_IVIzdI-TCO2bmvTsvO0EwcM9SZXjZnEDFMANWVUPGfq3g=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;MobXでTodoアプリ[Part1] MobX導入まで - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;3部作のPart1です。 MobXでTodoアプリ[Part1] MobX導入まで MobXでTodoアプリ[Part2] データを保存してみる MobXでTodoアプリ[Part3] Storeをデバッグしてみる 以前も書いたように、ここ1年ほどReact Nativeによるアプリ開発を時々行っています。凝ったアプリでなければ割とサクッと作れるのが良いです。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;前回までの実装だとアプリを起動し直したとき（React Native開発版ではリロードしたときも該当）に作ったTodoが消えてしまいます。今日はこれをキープできるような実装に変えたいと思います。&lt;/p&gt;
&lt;p&gt;今日の分のソースコードはここに、前と別のタグを打って置いてあります。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/pi-chan/MobxTodoApp/tree/part2" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/b7c26480ab70e2c1e489c78e67c06cf69ed2b44b4e9b51df51fc6be41a484b39/pi-chan/MobxTodoApp" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - pi-chan/MobxTodoApp at part2&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Contribute to pi-chan/MobxTodoApp development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="前回からの変更箇所"&gt;前回からの変更箇所&lt;/h1&gt;
&lt;p&gt;まずは&lt;code&gt;mobx-persist&lt;/code&gt;というライブラリを導入します。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/pinqy520/mobx-persist" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/557402cb11435a1ff57c148d2f05164cba2c52a404606673c877b698fd4d1ef7/pinqy520/mobx-persist" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - pinqy520/mobx-persist: persist mobx stores&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;persist mobx stores. Contribute to pinqy520/mobx-persist development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% npm install mobx-persist
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今回変更する箇所は2箇所です。作ったストアを&lt;code&gt;AsyncStorage&lt;/code&gt;を使って永続化するところと、ストアのうち、どの値を永続化対象にするのか？というところです。&lt;/p&gt;
&lt;p&gt;全体の差分が多くないので全部載せちゃう。&lt;/p&gt;
&lt;script src="https://gist.github.com/pi-chan/b46cba2e316b260ba6060557ddce86e8.js"&gt;&lt;/script&gt;
&lt;h2 id="hydrate"&gt;hydrate&lt;/h2&gt;
&lt;p&gt;まず&lt;code&gt;hydrate&lt;/code&gt;のところ、ここがストアとストレージを同期するための部分です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;hydrate&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;todos&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;todoStore&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この一行で起動時に読み込んでくれるし、&lt;code&gt;todoStore&lt;/code&gt;に更新があったら保存しておいてくれます。&lt;/p&gt;
&lt;h2 id="persist"&gt;persist&lt;/h2&gt;
&lt;p&gt;次にストア側の記述です。ここでは&lt;code&gt;@persist&lt;/code&gt;というデコレータを値に付けることで保存対象とします。通常の値であれば&lt;code&gt;@persist&lt;/code&gt;と書くだけでOKですが、配列やオブジェクトの場合には&lt;code&gt;@persist('list')&lt;/code&gt;などとして、型のようなものを指示しないと動きません。&lt;/p&gt;
&lt;h1 id="保存されている様子"&gt;保存されている様子&lt;/h1&gt;
&lt;p&gt;リロード後にも残っているのがわかります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/LQRaFq6luAri9OvngoEhItKO02nwxnFZcaQWcZwnG_FpLqgmh9PeCOyXEr61BUY3KMsOB-JjOQVXeU7t1tUI6IaRneoOP3et9q4c4MoY5GA0sR3OsBHQNtA2OMNoxT-XK53aN3mGPDdBxx8B-yDPvVudW_-LzTgHgqWBpKVmIOOHYGGwu5m1IGraTkb4OF3ThcC9q7eppdOmPJZEGUzBpjgu-TCqpH_biAZnNJDuNIWhdhzjOLfm-3dZH_1mklXH_exqknpDKZCQ6gB-5yEbsHNcmjAVTo1c4fFMMHnlQ3NKaXdogwwLE8PUIQ3KS-wKj7pGB_E5jjnyxPqpws7mtsOk84lpepNxYE-jPOpdSLQ_286YcI1J-nW6MqVefyLJjHrtGSS2YtjnZ2e-EqZ6OYb9TJo3m-ZUPgeG-Pbw8KItoKgEqZpH2yRETPEZs0rOsQ-76f1AY_YnPGzSuxTAKuRWhPpuc6Oc8GLodQ6B9rjqS7bns2TTDDD4_fo8XgXdMaP7bKGyCSS17Y6cOILJUNG3B8xs95RDpbYWeAtVh-yA_fxJ3_1mfXVJZcrClSYIwG9Y_8nsIeoENh-VXnHQQhPnbsoUiuMgFVPcnE69SvV8XG7Pyq3_r-C8V65o3DCsbu56BqEV7nUwbbDitjFTQvMQ5vI3duG51Q=w390-h681-no"&gt;&lt;img src="https://lh3.googleusercontent.com/LQRaFq6luAri9OvngoEhItKO02nwxnFZcaQWcZwnG_FpLqgmh9PeCOyXEr61BUY3KMsOB-JjOQVXeU7t1tUI6IaRneoOP3et9q4c4MoY5GA0sR3OsBHQNtA2OMNoxT-XK53aN3mGPDdBxx8B-yDPvVudW_-LzTgHgqWBpKVmIOOHYGGwu5m1IGraTkb4OF3ThcC9q7eppdOmPJZEGUzBpjgu-TCqpH_biAZnNJDuNIWhdhzjOLfm-3dZH_1mklXH_exqknpDKZCQ6gB-5yEbsHNcmjAVTo1c4fFMMHnlQ3NKaXdogwwLE8PUIQ3KS-wKj7pGB_E5jjnyxPqpws7mtsOk84lpepNxYE-jPOpdSLQ_286YcI1J-nW6MqVefyLJjHrtGSS2YtjnZ2e-EqZ6OYb9TJo3m-ZUPgeG-Pbw8KItoKgEqZpH2yRETPEZs0rOsQ-76f1AY_YnPGzSuxTAKuRWhPpuc6Oc8GLodQ6B9rjqS7bns2TTDDD4_fo8XgXdMaP7bKGyCSS17Y6cOILJUNG3B8xs95RDpbYWeAtVh-yA_fxJ3_1mfXVJZcrClSYIwG9Y_8nsIeoENh-VXnHQQhPnbsoUiuMgFVPcnE69SvV8XG7Pyq3_r-C8V65o3DCsbu56BqEV7nUwbbDitjFTQvMQ5vI3duG51Q=w390-h681-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>MobXでTodoアプリ[Part1] MobX導入まで</title><link>https://blog.piyo.tech/posts/2018-05-05-mobx-app-part1/</link><pubDate>Sat, 05 May 2018 06:58:38 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-05-mobx-app-part1/</guid><description>&lt;p&gt;3部作のPart1です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MobXでTodoアプリ[Part1] MobX導入まで&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2018-05-06-mobx-app-part2/"&gt;MobXでTodoアプリ[Part2] データを保存してみる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2018-05-07-mobx-app-part3/"&gt;MobXでTodoアプリ[Part3] Storeをデバッグしてみる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以前も書いたように、ここ1年ほどReact Nativeによるアプリ開発を時々行っています。凝ったアプリでなければ割とサクッと作れるのが良いです。&lt;/p&gt;
&lt;p&gt;さてReact Native（というかReact）単体だとデータ管理が面倒、バケツリレーが云々という話がよくあります。その問題に対応すべく色々なFluxなフレームワークが存在していて、中でもReduxがよく使われるようになったという流れが2年前ぐらいにあったと記憶しています。&lt;/p&gt;
&lt;p&gt;そういう流れで僕もReduxを使ってアプリ開発をしていましたが、ここ数ヶ月MobXというのをよく聞くようになりました。データ管理の用途だったらMobXで十分だよという話をよく見かけたようが気がするので、まずは試そうということでTodo的なアプリを作ってみることにしました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/mobxjs/mobx-react" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/dce68d40a13d891d89e73a828bb9876816cfe4fa43924b297a9b5de0f9165186/mobxjs/mobx-react" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - mobxjs/mobx-react: React bindings for MobX&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;React bindings for MobX. Contribute to mobxjs/mobx-react development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;結論としてはActionやらReducerやらを書かなくていいのでかなりシンプルになるなあという感想です。最低限動く状態を目指してTodoアプリを作るところをやってみようと重います。&lt;/p&gt;
&lt;p&gt;ソースコードはタグを打って公開してあります。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/pi-chan/MobxTodoApp/tree/part1" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/b7c26480ab70e2c1e489c78e67c06cf69ed2b44b4e9b51df51fc6be41a484b39/pi-chan/MobxTodoApp" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - pi-chan/MobxTodoApp at part1&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Contribute to pi-chan/MobxTodoApp development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="準備"&gt;準備&lt;/h1&gt;
&lt;p&gt;アプリを作ったり、MobXを入れたりします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;% react-native init MobxTodoApp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd MobxTodoApp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;% npm install mobx mobx-react&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Decoratorを使うためにbabelのプラグインをいれます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;% npm install babel-plugin-transform-decorators-legacy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.babelrc&lt;/code&gt;を以下のように変更&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;presets&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;react-native&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;plugins&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;transform-decorators-legacy&amp;#34;&lt;/span&gt;] &lt;span style="color:#75715e"&gt;// この行を追加
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="ストアを書く"&gt;ストアを書く&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;TodoStore&lt;/code&gt;というのを作って、追加と削除をできるようにしてみます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/MobxTodoApp/blob/part1/src/TodoStore.js"&gt;MobxTodoApp/TodoStore.js at part1 · pi-chan/MobxTodoApp&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;observable&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;action&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;mobx&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TodoStore&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;observable&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;todos&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;action&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;bound&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;onAdd&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;todo&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;todos&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [...&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;todos&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;todo&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;action&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;bound&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;onDelete&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;todo&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;todos&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;todos&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;filter&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;t&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt; &lt;span style="color:#f92672"&gt;!==&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;todo&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;todoはArrayで持つ&lt;/li&gt;
&lt;li&gt;onAddではArrayの末尾に新しい項目を追加&lt;/li&gt;
&lt;li&gt;onDeleteでは一致するものを削除&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="入力と一覧の画面を作る"&gt;入力と一覧の画面を作る&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/MobxTodoApp/blob/part1/src/TodoScreen.js"&gt;MobxTodoApp/TodoScreen.js at part1 · pi-chan/MobxTodoApp&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;import { inject, observer } from &amp;#39;mobx-react&amp;#39;;
@inject(&amp;#39;todo&amp;#39;)
@observer
export default class TodoScreen extends Component {
render() {
// 略
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;@observer&lt;/code&gt;はプロパティの変更に応じて再描画するための指定で、&lt;code&gt;@inject('todo')&lt;/code&gt;のところは、todoというストアをpropsにinjectするよの指定です。ざっくりいうと。ここは僕ももうちょとちゃんと理解しないと、な箇所です。&lt;/p&gt;
&lt;p&gt;ともあれ、これで&lt;code&gt;TodoStore&lt;/code&gt;の内容を使えるようになるし、新しいTodoが追加されれば再renderされるようになりました。&lt;/p&gt;
&lt;p&gt;renderの中身は省略しますが、適当にテキスト入力があって、todosの内容を&lt;code&gt;FlatList&lt;/code&gt;で表示するというシンプルな内容になってます。&lt;/p&gt;
&lt;h1 id="providerで囲む"&gt;Providerで囲む&lt;/h1&gt;
&lt;p&gt;injectで各storeを使うためにはProviderを使うと便利です。。内部的にはReactの&lt;code&gt;Context&lt;/code&gt;の仕組みが使われているようで、Provider配下のコンポーネントで使いたいストアを渡しておくと、配下のコンポーネントにinjectできるようになるという理解をしています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/MobxTodoApp/blob/part1/App.js"&gt;MobxTodoApp/App.js at part1 · pi-chan/MobxTodoApp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;storeを作ってProviderに渡してます。Provider配下には↑で作った&lt;code&gt;TodoScreen&lt;/code&gt;が居ます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;todoStore&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TodoStore&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stores&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;todo&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;todoStore&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Props&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;App&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Props&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Provider&lt;/span&gt; {...&lt;span style="color:#a6e22e"&gt;stores&lt;/span&gt;}&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;TodoScreen&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/Provider&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="最低限動いた様子"&gt;最低限動いた様子&lt;/h1&gt;
&lt;p&gt;ステータスバーの下に潜っちゃってるのはご愛嬌。特に永続化していないのでリロードするたびに新たにストアが作られてデータ消えちゃいます。Part2では永続化のことを書いてみようかと思ってます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/oQZHgYB-IBV6xHKqQiBph9tjs46ZypYZ6apKFbltjJ_TXg2MT3beNSJexKTfjX73S-bFLF2ZC20p_VEqs5jDm6BYYUEQTRM_FFsrkOmejOykNPNXuPU1hUOorecnc-5hxoR3Fith2Ou3aVzOFPX_4srPXi5UsQaeuzeMe54K_r0vmfurMIIErPp-Af5RYq8tb7MsKZofpf-3dZEzdM32qJXKJUj8nj99I7KD4taN47v-jd_5uWHKrGRYK6JieOIAss14C4dtvMQXbIM_qkkNbrWwGeLXV1sEPTjW7-AqsJDRW4WKkvv7viOcSW0BokcUpyRB0d31EBXbQBxGt_Sr2Vj5bSr99Fyb98rOkNT8Xa6VqjH8nzuFGFocTAZcRtQXWCL1l4sWU5_os5ej78UDX_JVWrrlER8OwLkAQbWh2XZEo5WxpBOQCb-c2gJPFyfA1caGUPtfBuU1V2xKF8uJKapsZt1tJrCHzVDfxFWOKoNjo8uK817baWbiv20t3JP_HbImJvZWGOMAd6XeQKD-9pNc4waB2LubQyMkmcd-zriCmsJ0t5RADygWcx9CCJHQn-xGsVImINHxBFZ34QH_gMdKY4EXEiXIz5JJrXLaU3Ajy1j7iCEOplywA7ryuZomgQ7oPOumdnlUVamMOpsQf6n0pOaAt8Ukkg=w390-h681-no"&gt;&lt;img src="https://lh3.googleusercontent.com/oQZHgYB-IBV6xHKqQiBph9tjs46ZypYZ6apKFbltjJ_TXg2MT3beNSJexKTfjX73S-bFLF2ZC20p_VEqs5jDm6BYYUEQTRM_FFsrkOmejOykNPNXuPU1hUOorecnc-5hxoR3Fith2Ou3aVzOFPX_4srPXi5UsQaeuzeMe54K_r0vmfurMIIErPp-Af5RYq8tb7MsKZofpf-3dZEzdM32qJXKJUj8nj99I7KD4taN47v-jd_5uWHKrGRYK6JieOIAss14C4dtvMQXbIM_qkkNbrWwGeLXV1sEPTjW7-AqsJDRW4WKkvv7viOcSW0BokcUpyRB0d31EBXbQBxGt_Sr2Vj5bSr99Fyb98rOkNT8Xa6VqjH8nzuFGFocTAZcRtQXWCL1l4sWU5_os5ej78UDX_JVWrrlER8OwLkAQbWh2XZEo5WxpBOQCb-c2gJPFyfA1caGUPtfBuU1V2xKF8uJKapsZt1tJrCHzVDfxFWOKoNjo8uK817baWbiv20t3JP_HbImJvZWGOMAd6XeQKD-9pNc4waB2LubQyMkmcd-zriCmsJ0t5RADygWcx9CCJHQn-xGsVImINHxBFZ34QH_gMdKY4EXEiXIz5JJrXLaU3Ajy1j7iCEOplywA7ryuZomgQ7oPOumdnlUVamMOpsQf6n0pOaAt8Ukkg=w390-h681-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>nodebrewでnode.js v10を入れる</title><link>https://blog.piyo.tech/posts/2018-05-04-node-v10/</link><pubDate>Fri, 04 May 2018 06:58:23 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-04-node-v10/</guid><description>&lt;p&gt;nodebrew自体はhomebrewでインストールしました。&lt;/p&gt;
&lt;p&gt;まず、nodebrew自体が古いとアレなのでアップデートします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% nodebrew selfupdate
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次に、v10があるかどうかを一応確認。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% nodebrew ls-remote
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;v10.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ありました。次にバイナリをインストールします。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;% nodebrew install-binary …
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;とこの時点でzshの補完が効くかなと思ったんですが、参照している内容が違うのか&lt;code&gt;v10&lt;/code&gt;は見当たりませんでした。&lt;/p&gt;
&lt;p&gt;仕方ないので直打ちしてインストールを試みます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% nodebrew install-binary v10.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;Fetching: https://nodejs.org/dist/v10.0.0/node-v10.0.0-darwin-x64.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;######################################################################## 100.0%&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;Installed successfully
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;アッサリ終わりました。&lt;/p&gt;
&lt;p&gt;実は最初、補完に出ないからまだ使えないのかなーと思ってしまったのです。入った入った。&lt;/p&gt;</description></item><item><title>Apple WatchやAirPodsの充電に困ったのでDockを買いました</title><link>https://blog.piyo.tech/posts/2018-05-03-apple-watch-dock/</link><pubDate>Thu, 03 May 2018 06:32:18 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-05-03-apple-watch-dock/</guid><description>&lt;p&gt;Macbookのスタンドを昨日紹介しました。今日はさらに小物の充電周りの話を書きます。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-05-02-macbook-pro-stand/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;blog.piyo.tech →&lt;/span&gt;&lt;span&gt;https://blog.piyo.tech/posts/2018-05-02-macbook-pro-stand/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Apple WatchやらAirPodsやらもっているのですが、最新ではないのでAirPowerのような充電には対応していません。最近はiPadやApple Pencilなども増えて充電周りが困った感じになってしまいました。&lt;/p&gt;
&lt;p&gt;色々と調べた結果、Apple WatchとAirPodsとiPhoneを同時に充電できるDockをお手頃な値段で見つけたのでものは試しと思い購入してみました。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-orange-300 rounded p-3 text-sm"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B07BGXNM18/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline"&gt;
&lt;span class="text-orange-600 mr-1"&gt;amazon.co.jp →&lt;/span&gt;ASIN: B07BGXNM18
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;そして、早速使ってみたのがこちらです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Tcp95TQUsktErZqkIA1VsR2qKZT57hB9qTHaIvwW1h2R8LK7eOdLz3ANoKQsUZlS5yPP0uhMkNrNjV7t6z07r2bhyVM1y6kxHPAxDdhCTTr4n8VyNV2_BzdmdVswRnIjgz8wU9JDgmZedQN5AwofrX_w5S-0F8w7WDkUo-LnIg4OMK_Ogf2FFn3oRIZhhhZBaRoPm3Al_WnpGRxLB-g5z6hwQgXIsna7ENtS2RS0uRYEtBq2_VdwABRIPvgdqwXC63IhyBm9OzYJp6LXGGrjAr-KKhaggvLMWmkYjHEZnlGRfmk2o35bx-iZgtkXsdl2X0Il3Fw0qlNLzk7b6bU2BfMQM9Xtu_sEc-xXZW4WVUwrF9oKqhv5nwfDUtExefseHOkNTaSQ2xP3ceMMJwl9sIsb1zoBOkTqkTGNHwaHJhhD7LTd7kY4NupC_l0KS835Bl3O3uxH37HPD18FR93D9IOjZ7hh5ACJjVwHMn_Yvv6V7l24FWckkc4udooyNW8eN-7_7-mlUNu3BWZLZZwzmdnJ8JtE9yOQx4b_RhyHrhReFEefV8K24nhvc95i0PKYdiTVa_KN-GrSZO9FAlEvlwV8gxOefl-7L3zWh_K0AxEhSDp9mAB-w6sa_LumWJ3Vm0zQTR9cNVYn5TBBQ96brwa3xniXr5Ve9Q=s1708-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Tcp95TQUsktErZqkIA1VsR2qKZT57hB9qTHaIvwW1h2R8LK7eOdLz3ANoKQsUZlS5yPP0uhMkNrNjV7t6z07r2bhyVM1y6kxHPAxDdhCTTr4n8VyNV2_BzdmdVswRnIjgz8wU9JDgmZedQN5AwofrX_w5S-0F8w7WDkUo-LnIg4OMK_Ogf2FFn3oRIZhhhZBaRoPm3Al_WnpGRxLB-g5z6hwQgXIsna7ENtS2RS0uRYEtBq2_VdwABRIPvgdqwXC63IhyBm9OzYJp6LXGGrjAr-KKhaggvLMWmkYjHEZnlGRfmk2o35bx-iZgtkXsdl2X0Il3Fw0qlNLzk7b6bU2BfMQM9Xtu_sEc-xXZW4WVUwrF9oKqhv5nwfDUtExefseHOkNTaSQ2xP3ceMMJwl9sIsb1zoBOkTqkTGNHwaHJhhD7LTd7kY4NupC_l0KS835Bl3O3uxH37HPD18FR93D9IOjZ7hh5ACJjVwHMn_Yvv6V7l24FWckkc4udooyNW8eN-7_7-mlUNu3BWZLZZwzmdnJ8JtE9yOQx4b_RhyHrhReFEefV8K24nhvc95i0PKYdiTVa_KN-GrSZO9FAlEvlwV8gxOefl-7L3zWh_K0AxEhSDp9mAB-w6sa_LumWJ3Vm0zQTR9cNVYn5TBBQ96brwa3xniXr5Ve9Q=s1708-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;どうしてもケーブル周りはごちゃっとしがちで整理しきれませんでしたが、Apple Watchの充電がしやすくなったことと、AirPodsの充電場所ができたことでかなり便利になったかと思います。&lt;/p&gt;
&lt;p&gt;ちなみにこの製品、iPadにも対応していると書いてありましたが、実際にiPhoneのところにiPadをさしてみるとギリギリささるものの、WatchのDockと干渉してしまい斜めになってしまいます。その上、iPhoneなら支えられる背もたれもiPadでは重くて支えられずにDock全体が倒れてしまいます。iPad対応とはよく言ったもんだ、という感じなのでiPadユーザーの人は注意してください。&lt;/p&gt;
&lt;p&gt;ちなみに、DockスタンドなりiPhoneスタンドなりに、Pencil充電用のアダプターをつなぐことでPencilの充電を場所を取らずに充電できます。これはこれで便利です。むしろ、iPhoneの場所をPencil専用にしてもいいぐらい。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/T9ubzkVjguyNU8OblBPFCv6jYhjjskATyM2zZBlQOSv-OUC4z8r6UEiFd1P6wbtBKpcr0LndmiaLDq7r0FXkqObzR-_DRAF8CZH69mfEsVHMSGZIdZWowRll5JcIFQziYTjN1D7XOMtTLmtzN0bD6qSJuh-JuvBcGXQDUzEodH9tTlptQ06pedJ3cy82PJmk1Gz8ABJWYXJSRsbglgwERR-fsJKbpWl1nwk0cQkfsmwPbEVWL2Y1haM8GjAUEJWYXo1tnBRFOldIcXTNr-9mycxuxPTweu2g70nCVgw4J6LKJnginKBWcqfgblC-ZL9F0_J1ESzGsJZK2Nfdz2I6kK83Pke66o2JOH-N-CtjwTGsZ4sEuPqL6iZaGwF3Jr3Zi7Xbm7yqR-5fUhYkzdVN5_eFXxb05aUQgSItnWMEZ3fG71vWg0Squ3FBqpbt5sbaKXf_oxr_jRzG3J1jF2Er-UfFUOd3dw6oKRn-sAK4AYTC6KLa_4zv7stcERmm0tLsXqks_co2l0aqBLDAqIvnSJU6nWy0TIBtsp3WfsC6O3QX1gRp1asKTyeucEfr_AbCtLEZqtOrLZ5Wq_tD5-3YKODeqhzbgexKvgAO62KLMVmD3yRyV-k27VqgKQG08qJgq12k3CDrBKrAU_s2zD1JZiaQZmiu1DbRQw=s1708-no"&gt;&lt;img src="https://lh3.googleusercontent.com/T9ubzkVjguyNU8OblBPFCv6jYhjjskATyM2zZBlQOSv-OUC4z8r6UEiFd1P6wbtBKpcr0LndmiaLDq7r0FXkqObzR-_DRAF8CZH69mfEsVHMSGZIdZWowRll5JcIFQziYTjN1D7XOMtTLmtzN0bD6qSJuh-JuvBcGXQDUzEodH9tTlptQ06pedJ3cy82PJmk1Gz8ABJWYXJSRsbglgwERR-fsJKbpWl1nwk0cQkfsmwPbEVWL2Y1haM8GjAUEJWYXo1tnBRFOldIcXTNr-9mycxuxPTweu2g70nCVgw4J6LKJnginKBWcqfgblC-ZL9F0_J1ESzGsJZK2Nfdz2I6kK83Pke66o2JOH-N-CtjwTGsZ4sEuPqL6iZaGwF3Jr3Zi7Xbm7yqR-5fUhYkzdVN5_eFXxb05aUQgSItnWMEZ3fG71vWg0Squ3FBqpbt5sbaKXf_oxr_jRzG3J1jF2Er-UfFUOd3dw6oKRn-sAK4AYTC6KLa_4zv7stcERmm0tLsXqks_co2l0aqBLDAqIvnSJU6nWy0TIBtsp3WfsC6O3QX1gRp1asKTyeucEfr_AbCtLEZqtOrLZ5Wq_tD5-3YKODeqhzbgexKvgAO62KLMVmD3yRyV-k27VqgKQG08qJgq12k3CDrBKrAU_s2zD1JZiaQZmiu1DbRQw=s1708-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これ、ケーブル汚いなｗ もうちょっとまとめます。&lt;/p&gt;</description></item><item><title>Gmailやカレンダーやチャットアプリを複数アカウントで使ってるならFranzが便利</title><link>https://blog.piyo.tech/posts/2018-04-30-franz-app/</link><pubDate>Mon, 30 Apr 2018 06:54:32 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-30-franz-app/</guid><description>&lt;p&gt;個人でも会社でもGoogle関連のサービスを使っていると、双方のアカウントを行き来するような感じなったり、思ってたのと違う方のアカウントでDriveの共有URL開いてしまったり、ブラウザのタブ数が大きく増えてしまったり、まあ色々不便なことがあります。&lt;/p&gt;
&lt;p&gt;そこで僕はFranzというアプリを使っています。Franzはチャット、メッセンジャー系のアプリを1つにまとめて管理できるよというのが元々の売りでしたが、（設定を書けば）Webアプリケーションであればなんでも埋め込むことができます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://meetfranz.com" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://meetfranz.com/static/images/shareimage.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Franz – a free messaging app for Slack, Facebook Messenger, WhatsApp, Telegram and more&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Franz is a free messaging app /former emperor of Austria, that combines chat &amp;amp; messaging services into one application.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://meetfranz.com/static/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;meetfranz.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Franzでは、よく使うサービスをFranzアプリの中にタブのような感じで登録して、常に開いた状態にできるという感じのアプリです。&lt;/p&gt;
&lt;p&gt;複数のアカウントでGmailやGoogleカレンダーを使っている場合は、それぞれを別のセッションで独立した状態で立ち上げたままにできるのでいつでもそれぞれのアカウントにアクセスできます。&lt;/p&gt;
&lt;p&gt;SlackやFacebookメッセンジャーなどのメッセージアプリは通知をまとめてバッジにすることなどもでき、とりあえずFranzを開けばOKという状態にできます。&lt;/p&gt;
&lt;p&gt;という話を先日同僚に勧めたらめちゃくちゃヒットしたのでブログにしました。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p lang="ja" dir="ltr"&gt;ぴーちゃん(&lt;a href="https://twitter.com/pi_cha_n?ref_src=twsrc%5Etfw"&gt;@pi_cha_n&lt;/a&gt;) に教えてもらった Frantz がめっちゃ便利&lt;br&gt;仕事用の Inbox やら Calendar やらをまとめるのにも便利だし、プライベート用のちらかった Discord をまとめるのにも便利&lt;/p&gt;&amp;mdash; Hirokatsu Endo (@ruzia) &lt;a href="https://twitter.com/ruzia/status/990030894604808193?ref_src=twsrc%5Etfw"&gt;April 28, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;ついでに、最新バージョンであるバージョン5がベータ版として配布されていることがわかったので新しいのに変えてみました。タブが上にあったのが左側に来てて見慣れないけど、ちょっとシュッとした感じで良い。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/6Ujm5mlxDTcs-MOh1fKTsZR6dbjc0IZpFTYUquo6bhRt5ZWu5requrNj1eJZCQhfuqJklx6tKaIc4dIgH5Z7O25ffTwaKm52TDqxuakUlg6wv_x5E3XZcnZoA39m5zHzG_79f_F5lH9ZhGupi9qsDeRzNunsHGXaaTUpS6LQQRvGJ4xXfxpNP96t4uQK__S-Us_L-Y9Et0sNmW4Y8TU9bl9xIQDDnpI8Yz6RUP2rKPYr6OmJjeRewTxx3NEFANB-wmz5u6d50IrmIBFgWyWMyncXfzhJJ8xMxKyftSmanWGNTelkv5w_8lqoxfe10OgVk7Tmu61-dZ08_PnUsREQmBtIuJiRuPs713i1xFuPzcjQ6zy5UPBuJsMrEfisqz0c670nAdSvKxmimcXpwBKf7i7vVCFIfeHXYMX6_pvfPdP4K2riU5zLuA5OKeRl3X7hon800ajoAblvVa0ixS7apaTHMlAAk4ARs9JeFaEBYMQWNJ1QaXGafJrj9qYHheTb4044GAXaSNpozzHZSaLOoX6mZ08IyV17gSd9flB1YT5KIyt4ja3qPYRL7rXY0xUjyhQbJ35MO_qodL-xaF7hE2OdLqdk1lp0EJHg6hK_Yig4hyGude-xPi-e53Hf3XcMB-4EgFDw4Umcx8YqeqAJjcGWPhxs-Td4Mw=w751-h515-no"&gt;&lt;img src="https://lh3.googleusercontent.com/6Ujm5mlxDTcs-MOh1fKTsZR6dbjc0IZpFTYUquo6bhRt5ZWu5requrNj1eJZCQhfuqJklx6tKaIc4dIgH5Z7O25ffTwaKm52TDqxuakUlg6wv_x5E3XZcnZoA39m5zHzG_79f_F5lH9ZhGupi9qsDeRzNunsHGXaaTUpS6LQQRvGJ4xXfxpNP96t4uQK__S-Us_L-Y9Et0sNmW4Y8TU9bl9xIQDDnpI8Yz6RUP2rKPYr6OmJjeRewTxx3NEFANB-wmz5u6d50IrmIBFgWyWMyncXfzhJJ8xMxKyftSmanWGNTelkv5w_8lqoxfe10OgVk7Tmu61-dZ08_PnUsREQmBtIuJiRuPs713i1xFuPzcjQ6zy5UPBuJsMrEfisqz0c670nAdSvKxmimcXpwBKf7i7vVCFIfeHXYMX6_pvfPdP4K2riU5zLuA5OKeRl3X7hon800ajoAblvVa0ixS7apaTHMlAAk4ARs9JeFaEBYMQWNJ1QaXGafJrj9qYHheTb4044GAXaSNpozzHZSaLOoX6mZ08IyV17gSd9flB1YT5KIyt4ja3qPYRL7rXY0xUjyhQbJ35MO_qodL-xaF7hE2OdLqdk1lp0EJHg6hK_Yig4hyGude-xPi-e53Hf3XcMB-4EgFDw4Umcx8YqeqAJjcGWPhxs-Td4Mw=w751-h515-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;上から順に&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;個人のInbox&lt;/li&gt;
&lt;li&gt;会社のInbox&lt;/li&gt;
&lt;li&gt;個人のカレンダー&lt;/li&gt;
&lt;li&gt;会社のカレンダー&lt;/li&gt;
&lt;li&gt;Tweetdeck&lt;/li&gt;
&lt;li&gt;Facebook Messenger&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;を登録してます。&lt;/p&gt;</description></item><item><title>React NativeのPlatform.selectについて</title><link>https://blog.piyo.tech/posts/2018-04-29-platform-select/</link><pubDate>Sun, 29 Apr 2018 06:21:32 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-29-platform-select/</guid><description>&lt;p&gt;&lt;code&gt;react-native init&lt;/code&gt;が生成するコードの↓の部分にある、&lt;code&gt;Platform.select&lt;/code&gt;を知らなかったので調べてみました。いやー、いっつもさっさと削除しちゃってちゃんと見てなかったです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;instructions&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Platform&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;select&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ios&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Press Cmd+R to reload,\n&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Cmd+D or shake for dev menu&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;android&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Double tap R on your keyboard to reload,\n&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Shake or press menu button for dev menu&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちなみに使い方はこう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Text&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;instructions&lt;/span&gt;}&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;instructions&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/Text&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;単に置くだけ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://facebook.github.io/react-native/docs/platform-specific-code.html"&gt;ドキュメント&lt;/a&gt; によると、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There is also a Platform.select method available, that given an object containing Platform.OS as keys, returns the value for the platform you are currently running on.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ということで環境に応じて値を切り替えるときに使えるわけですねー。いやー、いつもifとか三項演算子とかで書いてたー。↓みたいな感じで。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;apiKey&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Platform&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;OS&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;ios&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;key-for-ios&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;key-for-android&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;で、この手のコードって読みづらくなるんですよねー。今後は&lt;code&gt;Platform.select&lt;/code&gt;で書くのがよさそうだなと思いました。&lt;/p&gt;
&lt;h1 id="selectの仕組み"&gt;selectの仕組み&lt;/h1&gt;
&lt;p&gt;この&lt;code&gt;select&lt;/code&gt;、どういう仕組みかを簡単に説明します。&lt;/p&gt;
&lt;p&gt;そもそも&lt;code&gt;import { Platform } from 'react-native'&lt;/code&gt; した時点で、iosなりandroidなりのコードが読まれています。これはReact Nativeの仕組みで環境ごとに別のコードを読み込みわける仕組みによって実現されています。なので、iOSではimportした時点でこの&lt;code&gt;Platform&lt;/code&gt;はiOS用の&lt;code&gt;Platform&lt;/code&gt;なんですよね。&lt;/p&gt;
&lt;p&gt;では、これのselect関数を見てみましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Platform&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;select&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; Object) =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;ios&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ios&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;select&lt;/code&gt;に渡されたオブジェクトに&lt;code&gt;ios&lt;/code&gt;というキーがあればその値を、なければ&lt;code&gt;default&lt;/code&gt;キーのものを返す、という実装になっています。&lt;/p&gt;
&lt;p&gt;従って、最初のコードでは&lt;code&gt;instructions&lt;/code&gt;には単純に文字列が入っていることになるわけです。&lt;/p&gt;</description></item><item><title>React NativeのSectionListの覚書</title><link>https://blog.piyo.tech/posts/2018-04-28-section-list/</link><pubDate>Sat, 28 Apr 2018 06:42:54 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-28-section-list/</guid><description>&lt;p&gt;React Nativeでリストを表示するときは&lt;code&gt;FlatList&lt;/code&gt;を使いますが、セクションに分かれているような場合には&lt;code&gt;SectionList&lt;/code&gt;を使います。&lt;/p&gt;
&lt;p&gt;0.42まではどちらもFlatListで、結構頑張らないといけなかったのですが、0.34からFlatList, SectionListの2つが導入されました。メモリ使用やパフォーマンスなど色々な面でListViewに勝るようです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://reactnative.dev/blog/2017/03/13/better-list-views" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://reactnative.dev/img/logo-share.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Better List Views in React Native · React Native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Many of you have started playing with some of our new List components already after our teaser announcement in the community group, but we are officially announcing them today! No more ListViews or DataSources, stale rows, ignored bugs, or excessive memory consumption - with the latest React Native March 2017 release candidate (0.43-rc.1) you can pick from the new suite of components what best fits your use-case, with great perf and feature sets out of the box:&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://facebook.github.io/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;facebook.github.io&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;FlatListはグループ分けのないリスト、SectionListはグループ分けのあるリストです。FlatListのデータは単にArrayであればよいですが、SectionListではデータやメタデータをオブジェクトにしたもののArrayになるのでちょっと複雑です（と言ってもListViewの頃に比べたらシンプル）&lt;/p&gt;
&lt;p&gt;以下、一画面分の画面イメージとサンプルコード載せときます。あとで自分が困って検索する自信あるので、スニペット的に残しておきます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/33D49UwZb2M6q-DrSXF_qv8J3HFDv2VzjiZuTi7d0RvG81vwoGvhHTrDlmTr9NcdsLwtVHKeU18BIOWzlsrjBoXcxKEwSvPzAWC7rklRNb9f7ELVqHBPA0qxZmZgk-kGdNB0WK7ck5S5JfNIrMqx43GXJHFiX8YcIzzNwEPg_9I-MrP-HQiio7Hs28uOuXH0d70VUiAaY1jI9q18hmWh13oKHZVnG9ilpvlneldnhONzIBCk2G7IE1H8hPm2ffOEQ43-ImNJRqJ9fLtWPJmOxMxNtx4Tmdfg9qp5iKNBjwsVj4qVoB22PwstU974yVSq8KKuJXOwaKzMak85CxrffyokgksYTQh5RfMdG5dt_d9nh8Kyd-LMXLsMJgtdJatvZfSr8gtx12QaGAcaGEIJfqVz4R241X0OX5PHHto-7jf2SAbFSGZk22SK16tAA3o-kXmSGjeyRFg_4HtZm3tczPLcalDNSYkJ_mKkX5dJRq5_M4SS1jiJdLujEPVbyuJG7Huc57v4qtef9tAsFXHwDrlP1wNFvWvikAAn2PywHYTzzlQtySQRpEcd9MhMzO1qqpznVOPOqkkXZ3SCx9QMZjurFXDJUkxDAmdMa77Bxidm5CrvyKugjhQHIKoytAX5Wf2lSdskWJIZqt_5r-o0c1AGJKTtVrId3w=w390-h681-no"&gt;&lt;img src="https://lh3.googleusercontent.com/33D49UwZb2M6q-DrSXF_qv8J3HFDv2VzjiZuTi7d0RvG81vwoGvhHTrDlmTr9NcdsLwtVHKeU18BIOWzlsrjBoXcxKEwSvPzAWC7rklRNb9f7ELVqHBPA0qxZmZgk-kGdNB0WK7ck5S5JfNIrMqx43GXJHFiX8YcIzzNwEPg_9I-MrP-HQiio7Hs28uOuXH0d70VUiAaY1jI9q18hmWh13oKHZVnG9ilpvlneldnhONzIBCk2G7IE1H8hPm2ffOEQ43-ImNJRqJ9fLtWPJmOxMxNtx4Tmdfg9qp5iKNBjwsVj4qVoB22PwstU974yVSq8KKuJXOwaKzMak85CxrffyokgksYTQh5RfMdG5dt_d9nh8Kyd-LMXLsMJgtdJatvZfSr8gtx12QaGAcaGEIJfqVz4R241X0OX5PHHto-7jf2SAbFSGZk22SK16tAA3o-kXmSGjeyRFg_4HtZm3tczPLcalDNSYkJ_mKkX5dJRq5_M4SS1jiJdLujEPVbyuJG7Huc57v4qtef9tAsFXHwDrlP1wNFvWvikAAn2PywHYTzzlQtySQRpEcd9MhMzO1qqpznVOPOqkkXZ3SCx9QMZjurFXDJUkxDAmdMa77Bxidm5CrvyKugjhQHIKoytAX5Wf2lSdskWJIZqt_5r-o0c1AGJKTtVrId3w=w390-h681-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt;, { &lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Text&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;View&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;SectionList&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;StatusBar&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;} &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react-native&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Props&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;App&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Props&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;componentDidMount&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;StatusBar&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setHidden&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;renderItem&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;item&lt;/span&gt; }) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;View&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;height&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;justifyContent&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;center&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;borderTopWidth&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;borderTopColor&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#EAEAEA&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Text&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;item&lt;/span&gt;}&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/Text&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/View&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;renderSectionHeader&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;section&lt;/span&gt; }) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;View&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;height&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;28&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;backgroundColor&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#F0F0F0&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;justifyContent&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;center&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Text&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;section&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;}&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/Text&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/View&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;42&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;43&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;44&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;45&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;46&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SectionList&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;47&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ &lt;span style="color:#a6e22e"&gt;flex&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;48&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;keyExtractor&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;item&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;item&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;49&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;renderItem&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;renderItem&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;)}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;50&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;renderSectionHeader&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;renderSectionHeader&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;)}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;51&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;sections&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;52&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;53&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;グループA&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;54&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;ロシア&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;ウルグアイ&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;エジプト&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;サウジアラビア&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;55&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;56&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;57&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;グループB&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;58&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;ポルトガル&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;スペイン&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;イラン&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;モロッコ&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;59&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;60&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;61&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;グループC&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;62&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;フランス&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;ペルー&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;デンマーク&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;オーストラリア&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;63&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;64&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;65&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;グループD&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;66&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;アルゼンチン&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;クロアチア&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;アイスランド&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;ナイジェリア&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;67&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;68&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;69&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;グループE&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;70&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;ベルギー&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;スイス&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;コスタリカ&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;セルビア&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;71&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;72&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;73&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;グループF&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;74&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;ドイツ&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;メキシコ&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;スウェーデン&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;韓国&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;75&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;76&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;77&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;グループG&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;78&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;ベルギー&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;イングランド&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;チュニジア&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;パナマ&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;79&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;80&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;81&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;グループH&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;82&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;ポーランド&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;コロンビア&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;セネガル&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;日本&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;83&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;84&lt;/span&gt;&lt;span&gt; ]}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;85&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;86&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;87&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;88&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;keyExtractor&lt;/code&gt;を忘れると警告がでます。というか大体忘れて警告が出て、なんだっけ？となる。Reactでkeyを渡す必要があるのと同じ理由でリスト内の各アイテムにkeyが必要です。そのkeyにdataの何を使うかを返す関数を渡しておけばOK。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;renderItem&lt;/code&gt;や&lt;code&gt;renderSectionHeader&lt;/code&gt;でそれぞれの要素をどう描画するか指定しています。今回はサボって&lt;code&gt;&amp;lt;View&amp;gt;&lt;/code&gt;使ってますが、コンポーネント使っても良さそう。&lt;/p&gt;
&lt;p&gt;もうすぐワールドカップですね。&lt;/p&gt;</description></item><item><title>Markdown対応のノートアプリついて</title><link>https://blog.piyo.tech/posts/2018-04-27-quiver/</link><pubDate>Fri, 27 Apr 2018 06:16:30 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-27-quiver/</guid><description>&lt;p&gt;仕事のメモや個人的なメモ、ブログの下書きなどを、ノートアプリで書いています。元々はEvernoteを使っていた部分だけど、あれはMarkdownに対応してなくて文章などを書くのに不便だったのでやめました。&lt;/p&gt;
&lt;p&gt;今はQuiverというアプリを利用しています。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="http://happenapps.com/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;yliansoft&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;I am an indie app developer focusing on building high-quality productivity and educational apps.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="http://happenapps.com/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;happenapps.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;このアプリはPCでの体験はそれはもう100点満点で、Markdown対応、ショートカット、シンタックスハイライト、テーマ、なんならLaTexなんかも書けるということでかなり便利に使っています。&lt;/p&gt;
&lt;p&gt;ノートは専用のフォーマットでファイルに書き出されます。ファイルベースなのでDropboxで容易に同期することが可能です。その他、iCloud DriveやGoogle Driveなどの同期対象になっているディレクトリ配下に置くことでファイルを同期できます。&lt;/p&gt;
&lt;h1 id="唯一の困りごと"&gt;唯一の困りごと&lt;/h1&gt;
&lt;p&gt;（実用に耐える）アプリがないです。公式アプリがあるもののDropboxベースの同期をするためか動機が非常に遅いです。またDropboxのファイルを更新できないので、Read-Onlyです。PCにいないときに考えたことなどを追記できません。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="http://happenapps.com/#quiver-ios" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;yliansoft&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;I am an indie app developer focusing on building high-quality productivity and educational apps.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="http://happenapps.com/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;happenapps.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;仕方がないので今はAppleのメモアプリを併用して、iPhoneではメモに書き、PCでQuiverに書き写すみたいなことをしています。&lt;/p&gt;
&lt;p&gt;（Quiverでこの下書きを書いている間に3回ぐらい固まってレインボー出た。たまに起こる。）&lt;/p&gt;
&lt;h1 id="気になる乗り換え先"&gt;気になる乗り換え先&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Inkdrop&lt;/strong&gt; というやつが気になっています。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://blog.odoruinu.net/2016/10/04/inkdrop/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;blog.odoruinu.net →&lt;/span&gt;&lt;span&gt;https://blog.odoruinu.net/2016/10/04/inkdrop/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;PC版の使い勝手はQuiverに劣らずというかかなりいい感じで使え、iPhoneアプリもあり書き込みにも対応しています。トライアルで触った感想はほぼ「買い」。&lt;/p&gt;
&lt;p&gt;だけど1つハードルがありました。それはQuiverのNotebookの移行を考えなければならないこと。インポートプラグインみたいなものがいくつかあるんですが、Quiverフォーマットをそのまま取り込めるものはありません。MarkdownやHTMLにしたものをインポートならできそうでした。&lt;/p&gt;
&lt;p&gt;なんとなくそのあたりの方法でインポートを実行してみたのですが、ノートの日時が引き継げなくてそれ以上は断念しました。&lt;/p&gt;
&lt;p&gt;バックエンドにはPouch DBとやらを利用しているようで、直接そのDBに書き込むことで対応は可能かもしれないです。ただほとんど知識がないので添付ファイルの扱いなどが簡単には対応できなそうだなーと思いあきらめたとこでした。&lt;/p&gt;
&lt;h1 id="何か良いものはないかな"&gt;何か良いものはないかな&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Markdownで書ける&lt;/li&gt;
&lt;li&gt;プレビューできる&lt;/li&gt;
&lt;li&gt;個別ファイルで管理する必要がない（裏で勝手にやってくれる）&lt;/li&gt;
&lt;li&gt;アプリで閲覧・編集できる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Inkdropが大体満たしているんですよねー。移行ツールをがんばって書くのが一番いいのかな…&lt;/p&gt;</description></item><item><title>Hugoブログのシンタックスハイライトに行番号をつける</title><link>https://blog.piyo.tech/posts/2018-04-23-add-line-number/</link><pubDate>Mon, 23 Apr 2018 06:02:42 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-23-add-line-number/</guid><description>&lt;p&gt;このブログ、ソースコードを載せることが多いです。載せたコードについて書く時、◯行目とかいいたくなったので行番号を表示したいなと思いました。&lt;/p&gt;
&lt;p&gt;でも、Hugoってどうやってソースコード出してるんだろう？ということで調べてみると、元々は&lt;code&gt;Pygments&lt;/code&gt;、現在はGo実装の&lt;code&gt;Chroma&lt;/code&gt;というのを使っているようです。&lt;/p&gt;
&lt;p&gt;でも、色々設定を変えてみても変わらない。何かと思ったらRobustテーマは&lt;code&gt;highlight.js&lt;/code&gt;を使っているようでした。&lt;/p&gt;
&lt;p&gt;仕組みを変えると大変そうなので、この仕組のまま行番号を出せないかなと思い調べてみると、&lt;code&gt;highlight.js&lt;/code&gt;の行番号拡張みたいなのがあり、すごく楽に使えそうだったので導入しました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/yauhenipakala/highlightjs-line-numbers.js" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/05793736037ae76f280e8d0a7ebf30cf94ab1d79f57f3e5ad538845db73dbd3c/yauhenipakala/highlightjs-line-numbers.js" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - yauhenipakala/highlightjs-line-numbers.js: Line numbering plugin for Highlight.js&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Line numbering plugin for Highlight.js . Contribute to yauhenipakala/highlightjs-line-numbers.js development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;まず、ベースのhtmlでスクリプトを読み込むようにします。元々&lt;code&gt;highlight.min.js&lt;/code&gt;があったのでその次の行に入れました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;//cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.3.0/highlightjs-line-numbers.min.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そのすぐ下の&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;タグで実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;hljs&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;initHighlightingOnLoad&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;hljs&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;initLineNumbersOnLoad&lt;/span&gt;(); &lt;span style="color:#f92672"&gt;&amp;lt;--&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;この行を追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ついでにカラーテーマを&lt;code&gt;solarized-dark&lt;/code&gt;から&lt;code&gt;monokai-sublime&lt;/code&gt;に変更しました。&lt;/p&gt;
&lt;p&gt;軽くcssで微調整をして完成です。Before/Afterはこんな感じ。&lt;/p&gt;
&lt;h1 id="before"&gt;Before&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/wgJhxOiY5zHAEoWFQ-c9EWEjVvVKsLOxlqt3I8bjz1SA8CdznDUiY0XonKgjCYbh6jg2pcN8oLwj7UXwFJmGL80CXhxr2J1zbg4FC4ijuswsLm2ZhiVcOf6G7cvINfh3A7yd-ySNzftgAo2PzmQbuaAkGHuSQKj1K5aMaW_dLnJdBK35NOqMBq2GVAWBy6I8HGIO6Rwy_0OR1PAFB0B49w76VTL68-iG0ct66LzybmGZh52ryR07m5M5EItgqY-j7XFdXH9OulQvWSF32AwrvZVrWVcCN3rSlGw9w92lU_cyRX8enu-tgdKmvHvz4s-rXYNQMyow1N3w1NY6b7civHQPyAi6gWZGsUCCuMyA7TDWSUcSuPVy9IhLug8mK0MM99jFv-fkOQxjhpBW61ZY0dBgUQKixDsGLjJrXIfdAJzNiT-ZsAxCnUV2TiOXoGXqYQN6E6VlePFvZcDGCh36mpB7AELaMsF7DO5akAJJhsbHCyRRXEIEWZ75e3wrsj_s44wvM0Nxw3BeD1s6HLZQwHD16VHCuHqX1sAJmj6DjbuKhy-2LWs2dqTZQP7hbs5IOj0_3HgQWVLAwAytJktAUZ1N6iyjC77HWueYKsGeW4xAdQ7eX-9gaYUCVWXlEwIPX3odP9hkhchAXPbc9Bur16rnYL0GQIkRJg=w853-h467-no"&gt;&lt;img src="https://lh3.googleusercontent.com/wgJhxOiY5zHAEoWFQ-c9EWEjVvVKsLOxlqt3I8bjz1SA8CdznDUiY0XonKgjCYbh6jg2pcN8oLwj7UXwFJmGL80CXhxr2J1zbg4FC4ijuswsLm2ZhiVcOf6G7cvINfh3A7yd-ySNzftgAo2PzmQbuaAkGHuSQKj1K5aMaW_dLnJdBK35NOqMBq2GVAWBy6I8HGIO6Rwy_0OR1PAFB0B49w76VTL68-iG0ct66LzybmGZh52ryR07m5M5EItgqY-j7XFdXH9OulQvWSF32AwrvZVrWVcCN3rSlGw9w92lU_cyRX8enu-tgdKmvHvz4s-rXYNQMyow1N3w1NY6b7civHQPyAi6gWZGsUCCuMyA7TDWSUcSuPVy9IhLug8mK0MM99jFv-fkOQxjhpBW61ZY0dBgUQKixDsGLjJrXIfdAJzNiT-ZsAxCnUV2TiOXoGXqYQN6E6VlePFvZcDGCh36mpB7AELaMsF7DO5akAJJhsbHCyRRXEIEWZ75e3wrsj_s44wvM0Nxw3BeD1s6HLZQwHD16VHCuHqX1sAJmj6DjbuKhy-2LWs2dqTZQP7hbs5IOj0_3HgQWVLAwAytJktAUZ1N6iyjC77HWueYKsGeW4xAdQ7eX-9gaYUCVWXlEwIPX3odP9hkhchAXPbc9Bur16rnYL0GQIkRJg=w853-h467-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="after"&gt;After&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/xqni36OcFFiwFfiqgaVXcz96I-a3CsxaJ3TwnvShpLKJfdiD5ILoqZSWaIyTa1oQR5foTt6W-V0J9umRJbon5qh0JyLTF4vM6dDPGDpEXIXRU3EhTyljKrm_Qy4PhJIrVANUt6ql35NaQcsAv3I7r2c1oH12lacd7dPBXCwRSMBNMbgxKE2gaEykEWXL7hhUhOgsWJt98EeTnE6XzwpqpW8cPkI5FPHulO_LiixJmPF0sJcr19y_qmA_l-Zw4wuqLPHGB25q9ZoPCZ2_VDfxME-y0mVLIvWVdGtTeghb3HFv2iewE8QVhv7qyLccsOkfLvW2BVRPaH1XfrMH_Lh84RlAj21uTfhtnWJI-dvypRQJRJmwfu2JSiwPUkYt84lycTf7PApeiwwvVrqhNgy7qVQu6Rvj_aldJxgSK6__THUZiNQ4qDokQhXMAuJK-BYkV0DSCX2tY28W1bOqQsXzux-mayvrPP5t_HysXxJ_JjSRWQDhlxKGFmMvrjNrvbKRMV1IvNW3YIk77nuA9swPMZuEgkqAvFQu3udEFX04WIfQcGVdWhs-LdnxXjX4P7e4n9PjOobFQE5TbURlSgnhQp5TcwQ-oneritBU6_rS1K1xy-7MLcCQT6TqCKbSGXRe4PIC52OgwdTlpldTytxp_QV9g2S9IuxI9g=w841-h475-no"&gt;&lt;img src="https://lh3.googleusercontent.com/xqni36OcFFiwFfiqgaVXcz96I-a3CsxaJ3TwnvShpLKJfdiD5ILoqZSWaIyTa1oQR5foTt6W-V0J9umRJbon5qh0JyLTF4vM6dDPGDpEXIXRU3EhTyljKrm_Qy4PhJIrVANUt6ql35NaQcsAv3I7r2c1oH12lacd7dPBXCwRSMBNMbgxKE2gaEykEWXL7hhUhOgsWJt98EeTnE6XzwpqpW8cPkI5FPHulO_LiixJmPF0sJcr19y_qmA_l-Zw4wuqLPHGB25q9ZoPCZ2_VDfxME-y0mVLIvWVdGtTeghb3HFv2iewE8QVhv7qyLccsOkfLvW2BVRPaH1XfrMH_Lh84RlAj21uTfhtnWJI-dvypRQJRJmwfu2JSiwPUkYt84lycTf7PApeiwwvVrqhNgy7qVQu6Rvj_aldJxgSK6__THUZiNQ4qDokQhXMAuJK-BYkV0DSCX2tY28W1bOqQsXzux-mayvrPP5t_HysXxJ_JjSRWQDhlxKGFmMvrjNrvbKRMV1IvNW3YIk77nuA9swPMZuEgkqAvFQu3udEFX04WIfQcGVdWhs-LdnxXjX4P7e4n9PjOobFQE5TbURlSgnhQp5TcwQ-oneritBU6_rS1K1xy-7MLcCQT6TqCKbSGXRe4PIC52OgwdTlpldTytxp_QV9g2S9IuxI9g=w841-h475-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>React Nativeでのアニメーションについて整理しとく</title><link>https://blog.piyo.tech/posts/2018-04-22-react-native-animation/</link><pubDate>Sun, 22 Apr 2018 06:12:18 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-22-react-native-animation/</guid><description>&lt;p&gt;React NativeにはUIをアニメーションさせる機能があり、こちらの記事で取り上げたアプリでも一部で使用しています。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-04-11-react-native/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/y_i9fp87K99TSZkeLX2ZqCVu9aZ_itzXBB_AI90I1mycnWj72EQPc8YAlSOhDnWqOR-Tq2TNtMf1dIIwIB41o-tEjMH1Ahn90cPMyM-T83elsZBhs66peHCP2VfVWTT4R0OYwI65EU58kiApaDCGtXZLbQpBpg8mw4amb_Pu0o83H9sPVmkb8vDO08dFJoAeBghTwl0RJZFBzLPAvEo1yySRpKa1haI95sy4tF0fQD3H0VZF7yenhWdUvJtHk86DqtZGGZxA1KDPKFQ0MGBn6Q6vM785kgN1rWzWHxjmehqWLagVnwbhhBSukD-6rTB00p714JTqnff0BIK411edZRmzPaCaPzEbeM_i6WmbR6LcWPn-J5U7qn2O5GFjTpNF8ef0gvqD0dww9pNYC6yU1aFoyac9A1BVBzCHO5OoUgOVqn3PzE0fIv_J4twqGMYW2X34-yi11r2ZLbw9bbBGbz4lsuWSoGAyrMPvdwOPGG9eFn5MsLIK_-fMRmSDGeaDTi4yBa4-jw2xAy4HSi1VBSZkThJEuqm8nQdjd1u1Fz2cAtg2rVAdOfomS7FmFR_3i8UxLTUtNtU55U9Yc5wLwtZDOYz80cMG3PEP5g-5sYTEsOQ-fhil_IVIzdI-TCO2bmvTsvO0EwcM9SZXjZnEDFMANWVUPGfq3g=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;React Nativeで自社サービスのiOS/Androidアプリをリプレイスした話 - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;自社サービスRemottyのアプリを作り直すためにReact Nativeを習得してリプレイスしました&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;とはいえ、そのときは作ること優先でかなりベタに書くやり方をしました。今回はアニメーションの実装の仕方について整理したり、OSSのライブラリがどのような実装をしているのか、などを見ていきたいと思います。&lt;/p&gt;
&lt;h1 id="ベーシックな書き方"&gt;ベーシックな書き方&lt;/h1&gt;
&lt;p&gt;公式ドキュメントのアニメーションのページにある最初のサンプルコードが一番シンプルな事例と言えそうなのでそれを持ってきます。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://reactnative.dev/docs/animations" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://reactnative.dev/img/logo-share.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Animations · React Native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Animations are very important to create a great user experience. Stationary objects must overcome inertia as they start moving. Objects in motion have momentum and rarely come to a stop immediately. Animations allow you to convey physically believable motion in your interface.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://facebook.github.io/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;facebook.github.io&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;FadeInView&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fadeAnim&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Animated&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Value&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;), &lt;span style="color:#75715e"&gt;// Initial value for opacity: 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;componentDidMount&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Animated&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;timing&lt;/span&gt;( &lt;span style="color:#75715e"&gt;// Animate over time
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;fadeAnim&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// The animated value to drive
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;toValue&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// Animate to opacity: 1 (opaque)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;duration&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10000&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// Make it take a while
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; ).&lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;(); &lt;span style="color:#75715e"&gt;// Starts the animation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;fadeAnim&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Animated&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;View&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Special animatable View
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; ...&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;opacity&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fadeAnim&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// Bind opacity to animated value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;children&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/Animated.View&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ポイントは3つかなと思っています。&lt;/p&gt;
&lt;h2 id="animatedvalue"&gt;Animated.Value&lt;/h2&gt;
&lt;p&gt;アニメーションで変化する値。コンポーネントはこれをstateに持ちます。&lt;/p&gt;
&lt;p&gt;styleや色々なpropertyとして使うことができます。&lt;/p&gt;
&lt;h2 id="animatedview"&gt;Animated.View&lt;/h2&gt;
&lt;p&gt;アニメーション可能な&lt;code&gt;&amp;lt;View&amp;gt;&lt;/code&gt;で、stateとして持っている&lt;code&gt;Animated.Value&lt;/code&gt;な値をstyleに持っていて、値の変化に応じてViewが変化していきます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Animated&lt;/code&gt;には他にも&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Animated.Image&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Animated.ScrollView&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Animated.Text&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などがあるそうですが、使ったことないです。Text！？って感じです。&lt;/p&gt;
&lt;h2 id="animatedtiming"&gt;Animated.timing&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Animated.Value&lt;/code&gt;な値をどのように変化させるか、というアニメーションの肝を司る命令です。この例ではコンポーネントマウント時に値を変化させるため、&lt;code&gt;componentDidMount()&lt;/code&gt;内でstartさせています。&lt;/p&gt;
&lt;p&gt;と、ここまでは僕の知ってる書き方で、うんまあそうだねという感じ。&lt;/p&gt;
&lt;h1 id="ライブラリを覗いてみる"&gt;ライブラリを覗いてみる&lt;/h1&gt;
&lt;h2 id="react-native-message-bar"&gt;react-native-message-bar&lt;/h2&gt;
&lt;p&gt;アプリの上にニュッと出てくるアラートみたいなのを手軽に実装できるライブラリで、先のアプリでは通信の失敗のときなんかに使っています。滅多に見ないはず。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/KBLNY/react-native-message-bar" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/3bf00523f207f6faafdb02a34cee787a408921d0df1dd152a4e3dd5608e52804/KBLNY/react-native-message-bar" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - KBLNY/react-native-message-bar: A notification bar alert displayed at the top of the screen for react-native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;A notification bar alert displayed at the top of the screen for react-native - KBLNY/react-native-message-bar&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;メインのコンポーネントを覗いてみます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/KBLNY/react-native-message-bar/blob/master/MessageBar.js"&gt;react-native-message-bar/MessageBar.js at master · KBLNY/react-native-message-bar&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 初期設定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;animatedValue&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Animated&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Value&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 表示するとき
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Animated&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;timing&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;animatedValue&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;toValue&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;duration&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;durationToShow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;}).&lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_showMessageBarAlertComplete&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 非表示にするとき
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Animated&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;timing&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;animatedValue&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;toValue&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;duration&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;durationToHide&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;}).&lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_hideMessageBarAlertComplete&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;なるほど、&lt;code&gt;Animated.Value&lt;/code&gt;と&lt;code&gt;Animated.timing&lt;/code&gt;が使われていて、最初の例とあまり変わらないですね。&lt;/p&gt;
&lt;p&gt;では、この&lt;code&gt;this.animatedValue&lt;/code&gt;がどのように使われるかを見てみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;_apllyAnimationTypeTransformation&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 略
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;animationType&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;SlideFromTop&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;animationY&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;animatedValue&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;interpolate&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;inputRange&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;outputRange&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;windowHeight&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;animationTypeTransform&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [{ &lt;span style="color:#a6e22e"&gt;translateY&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;animationY&lt;/span&gt; }];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 略
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここでのポイントは、&lt;code&gt;this.animationValue.interpolate&lt;/code&gt;です。&lt;code&gt;inputRange&lt;/code&gt;の区間を&lt;code&gt;outputRange&lt;/code&gt;の区間に置き換えます。ここでは&lt;code&gt;0〜1&lt;/code&gt;を&lt;code&gt;-windowHeight〜0&lt;/code&gt;としています。&lt;/p&gt;
&lt;p&gt;ここで代入されている&lt;code&gt;this.animationTypeTransform&lt;/code&gt;は↓な感じで&lt;code&gt;Animated.View&lt;/code&gt;のスタイルとして使われています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Animated&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;View&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ &lt;span style="color:#a6e22e"&gt;transform&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;animationTypeTransform&lt;/span&gt;, ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;transformY&lt;/code&gt;は&lt;code&gt;-windowHeight〜0&lt;/code&gt;の間で変化するというわけですね。このようにinterpolateを使うと、&lt;code&gt;Animated.Value&lt;/code&gt;の変化を別の区間にマッピングして使うことができます。&lt;/p&gt;
&lt;p&gt;このライブラリは設定によって表示位置変えることができます。そのため、設定に応じてアニメーションに必要なパラメータは異なります。それぞれに&lt;code&gt;Animated.Value&lt;/code&gt;を用いるのではなく、&lt;code&gt;0〜1&lt;/code&gt;に変化する1つのパラメータを設定内容と&lt;code&gt;interpolate&lt;/code&gt;によって使いまわすことでシンプルな実装にできています。&lt;/p&gt;
&lt;p&gt;もう1個ぐらい見てみましょう。&lt;/p&gt;
&lt;h2 id="react-native-mentions"&gt;react-native-mentions&lt;/h2&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/harshq/react-native-mentions" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/6539bab3ab0c600b65af7110b41f58cd45ba031fc883af4f3b487753d71847f8/harshq/react-native-mentions" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - harshq/react-native-mentions: Mentions textbox for React Native. Works on both ios and android.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Mentions textbox for React Native. Works on both ios and android. :whale: - harshq/react-native-mentions&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;メンション候補をサジェストしてくれるUIをもったInputです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/harshq/react-native-mentions/blob/master/screens/screen1.gif?raw=true"&gt;&lt;img src="https://github.com/harshq/react-native-mentions/blob/master/screens/screen1.gif?raw=true" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;こちらは下からニュッと出て、また下にニュッと消える動きですね。&lt;/p&gt;
&lt;p&gt;アニメーションの実装部分を抜粋するとこんな感じです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/harshq/react-native-mentions/blob/master/src/MentionsTextInput.js"&gt;react-native-mentions/MentionsTextInput.js at master · harshq/react-native-mentions&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 初期設定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;suggestionRowHeight&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Animated&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Value&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 表示
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Animated&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;timing&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;suggestionRowHeight&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;toValue&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;height&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;height&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;suggestionRowHeight&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;duration&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;}).&lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 非表示
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Animated&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;timing&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;suggestionRowHeight&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;toValue&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;duration&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;}).&lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こちらはシンプルに&lt;code&gt;0&lt;/code&gt;から&lt;code&gt;height&lt;/code&gt;まで値を変化させてますね。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;render()&lt;/code&gt;では、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Animated&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;View&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{[{ ...&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;suggestionsPanelStyle&lt;/span&gt; }, { &lt;span style="color:#a6e22e"&gt;height&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;suggestionRowHeight&lt;/span&gt; }]}&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/Animated.View&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;という感じで値をそのまま使っています。シンプル。&lt;/p&gt;
&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Animated.Value&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Animated.View&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Animated.timing&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;の3つに加えて、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;interpolate&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;辺りを把握しておけば基本的なことは大体できそうな感じがしました。&lt;/p&gt;
&lt;p&gt;あとアニメーションが絡む場合はコンポーネントに切り出して、アニメーション絡みのコードをコンポーネントに閉じたほうがよさそうです。と、ライブラリのコードを読んで思いました。
初期設定、表示、非表示とそれだけでコード量が増えるんですよね。リファクタリングしたい気持ち。&lt;/p&gt;</description></item><item><title>テキスト入力し忘れをユーザースクリプトで少しばかり回避する</title><link>https://blog.piyo.tech/posts/2018-04-21-aws-user-script/</link><pubDate>Sat, 21 Apr 2018 06:55:20 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-21-aws-user-script/</guid><description>&lt;p&gt;なんてことはない話です。&lt;/p&gt;
&lt;p&gt;AWSのOpsworks上での操作において、あるプロジェクトでは運用上コメントを書いてボタンをポチする必要があるケースがあります。先日コメントを書き忘れる事案が発生したので、ユーザースクリプトでちょっと工夫しました。&lt;/p&gt;
&lt;p&gt;これで回避できるのか？という感じもしますけどとりあえずはやってみましょう。&lt;/p&gt;
&lt;p&gt;まず、ブラウザにTampermonkeyを入れます。ユーザースクリプトを登録したり自分で書いたりできるブラウザ拡張です。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.tampermonkey.net/index.php?browser=chrome&amp;amp;locale=en" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://www.tampermonkey.net/images/og_image.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;ホーム | Tampermonkey&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;ホーム&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://tampermonkey.net/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;tampermonkey.net&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Tampermonkeyをインストールしたらおもむろにスクリプトを書きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ==UserScript==
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// @name name
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// @namespace http://tampermonkey.net/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// @version 0.1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// @description try to take over the world!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// @author You
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// @match https://console.aws.amazon.com/opsworks/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// @grant none
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ==/UserScript==
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;use strict&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Your code here...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;setTimeout&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;button[data-action=&amp;#34;deploy.app&amp;#34;]&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;prop&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;disabled&amp;#34;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; }, &lt;span style="color:#ae81ff"&gt;5000&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(document).&lt;span style="color:#a6e22e"&gt;on&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;change&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;textarea#deployment_comment&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;button[data-action=&amp;#34;deploy.app&amp;#34;]&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;prop&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;disabled&amp;#34;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;})();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今回は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ボタンをdisabledにする&lt;/li&gt;
&lt;li&gt;コメントのテキストエリアを変更したらボタンがenabledになる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;としました。&lt;/p&gt;
&lt;p&gt;画面的にはこんな感じです。右下のボタンはページロード後に追加で表示されるため、表示後にdisabledにしてあげる必要があります。きちんとやるのは面倒だったので適当に5秒待ってから実施しています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/H8nKiIrn6hsboPAcvWYostro4ZoQRZwUfP6IOw6BYfrtOE9TuLnDEQExYIISJG6bmguI2J12Ly3Vl9akY9YSOWROAcG_7AUmn0nojJdgCtIPNG9JlE6cGR6qXT7U-i0jb6Rlsqh_OOA_H-6pyE94_0vv3uh28rq7fTKvJQ9hI2sBANExK4bt-9z_CN4C26rkS4T9OZjAkacKGHLJLXH9b_VPVsGDmHn7Y_84FItKGd1gn2Dhm3EA_o2T04PCmcEWG8R6kf_su8rgb8Z2VE5akzjOapFpLq_TNIPetXaXRkvAcreTq0ZdiXDhX3dPX_YC2CBPbtlqbnVS0kYKDrbgnlWFCNedBDumKRgLEhiCmui_L-w_3bHNwEpOZVG0vT531PVfpBzEV4hn1NoOt_pjXjOJqvnEqBpxGvW7ukh-PQP6qLR7d_JQPXTYHbQ-MDgdrLLLkECGxF62n4cPdeUiR9E7IHClpGf8UFiqrmzCPKSDllctfFcVHjEbumqWuywqffgkbVRTq8FIHgfHJk-hWtqfBqxC8CzpygQLMowMdT7M-VQdLgvfLhZi2EITcG-XlT5dg3zzSMTj9G6I0XvKBy6AJeaBORhFwQvEH-zYBAu8U5F634CWrMGx7-LiQZ-GMEdvWttRYDM6HcwYMRTuMIXWXjWuxuVjqw=w989-h560-no"&gt;&lt;img src="https://lh3.googleusercontent.com/H8nKiIrn6hsboPAcvWYostro4ZoQRZwUfP6IOw6BYfrtOE9TuLnDEQExYIISJG6bmguI2J12Ly3Vl9akY9YSOWROAcG_7AUmn0nojJdgCtIPNG9JlE6cGR6qXT7U-i0jb6Rlsqh_OOA_H-6pyE94_0vv3uh28rq7fTKvJQ9hI2sBANExK4bt-9z_CN4C26rkS4T9OZjAkacKGHLJLXH9b_VPVsGDmHn7Y_84FItKGd1gn2Dhm3EA_o2T04PCmcEWG8R6kf_su8rgb8Z2VE5akzjOapFpLq_TNIPetXaXRkvAcreTq0ZdiXDhX3dPX_YC2CBPbtlqbnVS0kYKDrbgnlWFCNedBDumKRgLEhiCmui_L-w_3bHNwEpOZVG0vT531PVfpBzEV4hn1NoOt_pjXjOJqvnEqBpxGvW7ukh-PQP6qLR7d_JQPXTYHbQ-MDgdrLLLkECGxF62n4cPdeUiR9E7IHClpGf8UFiqrmzCPKSDllctfFcVHjEbumqWuywqffgkbVRTq8FIHgfHJk-hWtqfBqxC8CzpygQLMowMdT7M-VQdLgvfLhZi2EITcG-XlT5dg3zzSMTj9G6I0XvKBy6AJeaBORhFwQvEH-zYBAu8U5F634CWrMGx7-LiQZ-GMEdvWttRYDM6HcwYMRTuMIXWXjWuxuVjqw=w989-h560-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;コメントを書かないと右下のボタンを押せません。厳密に言うと文字を入れてから消した場合にもボタンが押せちゃいますが、それはそれでOKとします。特定のプロジェクトにのみ必要な対応なのです。&lt;/p&gt;
&lt;p&gt;ユーザースタイルとかユーザースクリプト、個人的にはあまり使わないですが、運用上気をつけないといけないことに対応する用途はいいかもですね。本番サイトに警告を出すみたいなことが柔軟できそうだし。&lt;/p&gt;</description></item><item><title>[追記あり]再びCircleCIでsession not created exception</title><link>https://blog.piyo.tech/posts/2018-04-20-circleci-chromedriver/</link><pubDate>Fri, 20 Apr 2018 06:55:33 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-20-circleci-chromedriver/</guid><description>&lt;p&gt;4/19あたりからCircleCIでまたこのエラーがでるようになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;session not created exception: Chrome version must be &amp;gt;= 65.0.3325.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;多分、&lt;code&gt;Gemfile&lt;/code&gt;に入れていた&lt;code&gt;chromedriver-helper&lt;/code&gt;とDockerイメージに入っているChromeのバージョンが衝突しているのが原因だと思います。以前の調査記事でも書いた内容です。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-03-30-chrome-on-circleci/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/G7pKIkwdqr30uWreoaT3NnRbKcWME9s9VeWESZiVt-KUgrVfbw60Ny5fBT9HZfn7dS1_-BQ4CwbgGE_C4RZWuKRRB44AePvViRx5p-MBLmQ38FTeZa1mRtWUi0JfbSPNJyR_phcX--HqVC_AOsRDO4-P6zsG3vzYfjpgVPkdEyrVGvOES__d8mRU1DYz5EgVMBk8t0JR1SDalpwBG8YpUbKSf5Cqrn4BeFZt45dSvV5pEykROCzt7BvlhzkMtcef7WzSPADuMp8o4XEbNPygYGp3RgpLO2rsktOPTV0wVKP5jbOCSJYH3x4E1934S3IoFwy2i3pqA1nqGrKMXqDB3vq3-OLhUYeV8z-yY5MRh2yINn2xUItB3wilnZfNWLq60-gwK2YsFA4fjK2DcnhyFBIuNoGF3z29SeQGPsaUAxNA8Hcosxt7M_mdJa7R7vfZYdZtSNvrYsmqEHqqCL5_ZxuA5VijQAXlAjuP_5XqiVdWQ0eae6eFKPjlRpUm_z5UU4-1BUI4kv-XHucFz-LjCOTWYpEYn_WKSVNx4MUIk4EzaIf1CWcGskyrj3oqfnqKaCvOC3jLFo2cwr4idw_bNGAP-vcHfbTlYYrLOsex9bcZs9_GSdzXTrd0n_JKQ7bW5LjLrm_jUtRplwkdhhnH6ZC0CwMO-6lg0g=w1200-h630-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Headless ChromeのテストがCircleCI上で動かなかった - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;おとといの記事でHeadlessChromeを使ってテストするようにしたよ、と書きました。 https://blog.piyo.tech/posts/2018-03-28-headless-chrome/ ですが、CircleCIではこんな感じのエラーを吐いて動きませんでした。 Selenium::WebDriver::Error::SessionNotCreatedError: session not created exception: Chrome version must be &amp;amp;gt;= 64.0.3282.0 どうやら、circleciのイメージに元々入っているchromedriverと、gemとしてインストールしている chromedriver-helper が衝突することによって起こるらしいということがわかりました。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;テスト周りの設定は何も変更していない中でこれが起きました。Dockerイメージが怪しいので見てみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hub.docker.com/r/circleci/ruby/"&gt;circleci/ruby - Docker Hub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;すると、こんな感じで最終更新が11 hours agoになっています。これ、怪しいかも？（これ書いてるのは4/19の夜です）&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/TsrOotEyohCp6xY232dIazvlZUF4qG1pUvTQLCWxrE1wq4hPoZGqxLd1XOshVqp4VzLsIqwi7TkAlPHdJKmpekqCQe8ffvcVbIi0M1Dx78UFJEx6J86vnuALFRu5xXscbv--_rGzB7B91oSJ_oRiRf9YZ-amtILyBVzM_k9boorY1vm0wVcz-Z86B96f7c4aJ-0b-XIXwYzNdmFa7iYr-AhxZ5eHjLTxEL6K5rtJaDI9jzTM2L6ii6cn-UJz9dtbyYqnfcuZMUaa4CYFFqmdN6iCnB8VPMbecov2q4GHXOxs5ivWdPmQ0K0BPtQ3SopsCYTB67RY7_-YQHRtzUvznSn4OToaOJ18vD3pLxg5NEjXtZW93vUikc10gAlMTgDzmEOAOvV0UR3skbQcFE3Nkw7-72x9fhkhd3HU_EY3n0zBGVOuz17i9Gm7ILV4OgvIZwv0qciMRgRh_rTD301BE75bKEvfKvOIuBmIcJBOLTgKkpEa_sQjnKZp6rmn6rktVRN-kBbK3-UKMKYu8_L9iIrc_HiGTL3MSXFr5HLl6A8yt_AIPVqfOOvtAfXwRYtSYp3M6qBNXgzGA9i_f6xkp_JzBPqueLYx3DDPinBjAiKohH2zsiXqi99aezdwReuKEn6tQidxDc9k-tc19zyiY8ocZVb2UJqCjA=w532-h310-no"&gt;&lt;img src="https://lh3.googleusercontent.com/TsrOotEyohCp6xY232dIazvlZUF4qG1pUvTQLCWxrE1wq4hPoZGqxLd1XOshVqp4VzLsIqwi7TkAlPHdJKmpekqCQe8ffvcVbIi0M1Dx78UFJEx6J86vnuALFRu5xXscbv--_rGzB7B91oSJ_oRiRf9YZ-amtILyBVzM_k9boorY1vm0wVcz-Z86B96f7c4aJ-0b-XIXwYzNdmFa7iYr-AhxZ5eHjLTxEL6K5rtJaDI9jzTM2L6ii6cn-UJz9dtbyYqnfcuZMUaa4CYFFqmdN6iCnB8VPMbecov2q4GHXOxs5ivWdPmQ0K0BPtQ3SopsCYTB67RY7_-YQHRtzUvznSn4OToaOJ18vD3pLxg5NEjXtZW93vUikc10gAlMTgDzmEOAOvV0UR3skbQcFE3Nkw7-72x9fhkhd3HU_EY3n0zBGVOuz17i9Gm7ILV4OgvIZwv0qciMRgRh_rTD301BE75bKEvfKvOIuBmIcJBOLTgKkpEa_sQjnKZp6rmn6rktVRN-kBbK3-UKMKYu8_L9iIrc_HiGTL3MSXFr5HLl6A8yt_AIPVqfOOvtAfXwRYtSYp3M6qBNXgzGA9i_f6xkp_JzBPqueLYx3DDPinBjAiKohH2zsiXqi99aezdwReuKEn6tQidxDc9k-tc19zyiY8ocZVb2UJqCjA=w532-h310-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Docker側のChromeのバージョンが上がったような気がします。先日のエラーのときは&lt;code&gt;Chrome version must be &amp;gt;= 64.0.3282.0&lt;/code&gt;でしたから。&lt;/p&gt;
&lt;p&gt;以前まではたまたま&lt;code&gt;gem 'chromedriver-helper'&lt;/code&gt;とDocker側が一致していたのだと思います。なので前記事でも試したように、CircleCI側では&lt;code&gt;chromedriver-helper&lt;/code&gt;を使わないように分岐してあげ、CircleCI側で&lt;code&gt;Rebuild without Cache&lt;/code&gt;したところビルドが通るようになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;group &lt;span style="color:#e6db74"&gt;:test&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;chromedriver-helper&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;key?(&lt;span style="color:#e6db74"&gt;&amp;#39;CIRCLECI&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この分岐は基本入れておいたほうが良さそうです。&lt;/p&gt;
&lt;p&gt;また、CI側ではcacheを使わずに毎回&lt;code&gt;bundle install&lt;/code&gt;するのが無難です。&lt;code&gt;Gemfile&lt;/code&gt;に&lt;code&gt;unless&lt;/code&gt;による条件分岐があるせいで、キャッシュを使うとリポジトリの&lt;code&gt;Gemfile.lock&lt;/code&gt;を見る（＝chromedriverが入っている状態になる）なので、結局バージョンの不整合が起こり得ます。&lt;/p&gt;
&lt;h1 id="追記"&gt;追記&lt;/h1&gt;
&lt;p&gt;もうちょっと詳細にバージョンを調べてみました。&lt;/p&gt;
&lt;p&gt;今回使ってたイメージは&lt;code&gt;circleci/ruby:2.4.3-node-browsers&lt;/code&gt;です。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;google-chrome&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;circleci@6fb99568c11a:~$ google-chrome --version
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;Google Chrome 64.0.3282.186
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;chromedriver&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;circleci@6fb99568c11a:~$ chromedriver
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;Starting ChromeDriver 2.38.551591 &lt;span style="color:#f92672"&gt;(&lt;/span&gt;bcc4a2cdef0f6b942b2bb8049068f65340fa2a69&lt;span style="color:#f92672"&gt;)&lt;/span&gt; on port &lt;span style="color:#ae81ff"&gt;9515&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;ChromeDriverの対応&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;リリースノートには、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;----------ChromeDriver v2.38 (2018-04-17)----------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;Supports Chrome v65-67
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とあるので、このバージョンの食い違いが原因でした。もしかするとChromeDriver gem側で入るバージョンが変わったのかもしれないです。&lt;/p&gt;
&lt;p&gt;イメージ側のchromeに合わせるのであれば、CIでテストを流す前に&lt;code&gt;chromedriver-update&lt;/code&gt;でダウングレードさせればいけそうでした（ローカルのCircleCIで確認済）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- &lt;span style="color:#f92672"&gt;run&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Downgrade chromedriver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;command&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; bundle exec chromedriver-update 2.37&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;だけど、Rubyのバージョンアップなんかでイメージ側を変えるときにここの指定バージョン変えるのも面倒ですよねー。なのでひとまずはunlessで逃げることにして、問題でたら考えます。&lt;/p&gt;</description></item><item><title>Rubyで繰り返し予定を扱えるice_cube gemをざっくり紹介</title><link>https://blog.piyo.tech/posts/2018-04-19-ruby-icecube/</link><pubDate>Thu, 19 Apr 2018 06:36:26 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-19-ruby-icecube/</guid><description>&lt;p&gt;Googleカレンダーみたいな繰り返し予定をRubyやRailsで扱う方法を解説します。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/ice-cube-ruby/ice_cube" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/59889abe3c567335314a3fb8c3f407e584949aea634f8d8fa6f51f9df1cd31ae/ice-cube-ruby/ice_cube" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - ice-cube-ruby/ice_cube: Ruby Date Recurrence Library - Allows easy creation of recurrence rules and fast querying&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Ruby Date Recurrence Library - Allows easy creation of recurrence rules and fast querying - ice-cube-ruby/ice_cube&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ice_cube gemは繰り返し予定用のRubyのライブラリです。ちなみにRailsとは直接は連携しませんが工夫することで使えます。&lt;/p&gt;
&lt;h1 id="簡単な使い方"&gt;簡単な使い方&lt;/h1&gt;
&lt;p&gt;かなりざっくり言うと、ice_cubeは繰り返し予定に関するいろいろな条件を与えたとき、その条件に該当する日付に関する処理を行うことができるライブラリです。&lt;/p&gt;
&lt;p&gt;ユースケースで考えたほうがわかりやすいかもしれないですね。&lt;/p&gt;
&lt;p&gt;例えば、2018年4月1日以降の毎月1日に繰り返す予定を表すとしましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;schedule &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;IceCube&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Schedule&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(now &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Date&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_recurrence_rule &lt;span style="color:#66d9ef"&gt;IceCube&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Rule&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;monthly
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでOK。では&lt;code&gt;schedule.all_occurrences&lt;/code&gt;で全ての日付を取得してみましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;all_occurrences
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;ArgumentError&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;All&lt;/span&gt; recurrence rules must specify &lt;span style="color:#f92672"&gt;.&lt;/span&gt;until &lt;span style="color:#f92672"&gt;or&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;count to use &lt;span style="color:#e6db74"&gt;`all_occurrences&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;怒られました。それもそうで、終わりを決められるようなルールがない場合は無限の集合になってしまうからですね。繰り返し回数か終了日を設定するか、日付の問い合わせを期間指定にすることで日付のArrayを得ることができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;schedules&lt;span style="color:#f92672"&gt;.&lt;/span&gt;occurrences(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;year&lt;span style="color:#f92672"&gt;.&lt;/span&gt;from_now)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;06&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;09&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2019&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2019&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2019&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;03&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2019&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;occurrences_between(&lt;span style="color:#66d9ef"&gt;Date&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;), &lt;span style="color:#66d9ef"&gt;Date&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;31&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;06&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;first(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;06&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="終わりがある繰り返し"&gt;終わりがある繰り返し&lt;/h1&gt;
&lt;p&gt;繰り返し回数を指定してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;schedule &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;IceCube&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Schedule&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(now &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Date&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_recurrence_rule &lt;span style="color:#66d9ef"&gt;IceCube&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Rule&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;monthly&lt;span style="color:#f92672"&gt;.&lt;/span&gt;count(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;all_occurrences
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;06&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;終了日を指定してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;schedule &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;IceCube&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Schedule&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(now &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Date&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_recurrence_rule &lt;span style="color:#66d9ef"&gt;IceCube&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Rule&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;monthly&lt;span style="color:#f92672"&gt;.&lt;/span&gt;until(&lt;span style="color:#66d9ef"&gt;Date&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;all_occurrences&lt;span style="color:#f92672"&gt;.&lt;/span&gt;count
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="除外日を設定する"&gt;除外日を設定する&lt;/h1&gt;
&lt;p&gt;Googleカレンダーなんかで繰り返し予定を作って、ある特定の日だけ予定を消そうとすると、このイベントだけ削除みたいなことができます。あれを実現できます。&lt;/p&gt;
&lt;p&gt;4月1日から4回繰り返す、だけどその内の5月1日は無しにしてね、という感じでルールを指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;schedule &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;IceCube&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Schedule&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(now &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Date&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_recurrence_rule &lt;span style="color:#66d9ef"&gt;IceCube&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Rule&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;monthly&lt;span style="color:#f92672"&gt;.&lt;/span&gt;count(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_exception_time(&lt;span style="color:#66d9ef"&gt;Date&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;all_occurrences
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;06&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;繰り返しが3回しか現れないですね。&lt;/p&gt;
&lt;h1 id="シリアライズする"&gt;シリアライズする&lt;/h1&gt;
&lt;p&gt;これまでice_cubeのscheduleクラスに色々設定してきた繰り返しルールをyamlやical形式などでテキスト化できます。&lt;/p&gt;
&lt;p&gt;このgemを調べるまでしらなかったのですが、繰り返しルールの記述はRFCで定義されているんですね。icalがこの記法でデータを持っているようです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.kanzaki.com/docs/ical/rrule.html" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;iCalendar spec: 4.8.5.4 Recurrence Rule&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;span class="truncate"&gt;www.kanzaki.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;例えば先ほど除外日を使ったときのscheduleをyamlやicalにしてみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;schedule &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;IceCube&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Schedule&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(now &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Date&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_recurrence_rule &lt;span style="color:#66d9ef"&gt;IceCube&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Rule&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;monthly&lt;span style="color:#f92672"&gt;.&lt;/span&gt;count(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_exception_time(&lt;span style="color:#66d9ef"&gt;Date&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;yaml&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;:start_time&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;2018-04-01 00:00:00.000000000 +09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;:rrules&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;- &lt;span style="color:#f92672"&gt;:validations&lt;/span&gt;: {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;:rule_type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;IceCube::MonthlyRule&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;:interval&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;:count&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;:rtimes&lt;/span&gt;: []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;:extimes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;- &lt;span style="color:#e6db74"&gt;2018-05-01 00:00:00.000000000 +09&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;ical&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;DTSTART;TZID=JST:20180401T000000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;RRULE:FREQ=MONTHLY;COUNT=4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;EXDATE;TZID=JST:20180501T000000
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;またこれらの形式からscheduleクラスに戻すことも可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;ical &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;DTSTART;TZID=JST:20180401T000000&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;RRULE:FREQ=MONTHLY;COUNT=4&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;EXDATE;TZID=JST:20180501T000000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;schedule &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;IceCube&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Schedule&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;from_ical(ical)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;schedule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;all_occurrences
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;06&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2018&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0900&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;特に編集しないアプリケーションであれば、yamlやicalの形式でDBに保存しておいて、使うときは再びscheduleに変換して使うことが可能です。&lt;/p&gt;
&lt;p&gt;ただの紹介になっちゃったので詳しくはREADMEを見てもらうとして、今度は簡単なサンプルアプリを作って例を紹介してみようかなーと思っています。&lt;/p&gt;</description></item><item><title>storybook.jsとは何か？何も知らずに触ってみた。</title><link>https://blog.piyo.tech/posts/2018-04-18-storybookjs/</link><pubDate>Wed, 18 Apr 2018 06:49:38 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-18-storybookjs/</guid><description>&lt;p&gt;Vue.jsの文脈でStorybookというものを見つけ、ReactやReact Nativeでも使えるらしいことやGitHubスター数が2万超えで半端ないことを知りました。手始めに触ってみることにしました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://storybook.js.org" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://storybook.js.org/opengraph-image.jpg?841db310ba5a3a1e" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Storybook: Frontend workshop for UI development&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Storybook is a frontend workshop for building UI components and pages in isolation. Thousands of teams use it for UI development, testing, and documentation. It&amp;#39;s open source and free.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://storybook.js.org/icon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;storybook.js.org&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;以下の数ステップで準備が整います&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;$ react-native init StorybookExample
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;$ cd StorybookExample
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;$ npm -g i @storybook/cli
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;$ getstorybook
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; getstorybook - the simplest way to add a storybook to your project.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; • Detecting project type. ✓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; • Adding storybook support to your &lt;span style="color:#e6db74"&gt;&amp;#34;React Native&amp;#34;&lt;/span&gt; app. ✓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; • Preparing to install dependencies. ✓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;React Nativeのアプリケーションだということを検知してセットアップをしてくれるようですね。&lt;code&gt;getstorybook&lt;/code&gt;後に&lt;code&gt;npm run storybook&lt;/code&gt;せい、という指示があるので実行してみましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ npm run storybook
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;すると何やらローカルホストの&lt;code&gt;7007&lt;/code&gt;ポートでサーバーが立ち上がった様子。見てみましょう。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/VzWM-H8o3hgBhv8tLNPJtboYgbIfZDfnBujVit7DuydDmXjwEZV-7IOAamZZ9hgPtGfQXNu-bc9KGARaih3fC44isiYkrKEJfpmxWCJ4FTxKQ4y4Z0ci999E1ElyvesQrulyf6p5CiLCJuDz_SAVOc7ajeW6msndsPvKKQ299auOLALioE8jjT5j5E1yovokyppzrHw26U6MKq9ua4jXN9UgXqnashT_avnUwnCtQm1xuY7EgyyBJ8-z_d5K-pw8Sic_uh00383Go59jSy98Mj_1X9edbjmzepuY1QBZKlhl6EIby9ekv4CmLMNGfywhU5XZgSTncib0GZXHQcZiU_4G6Aogp3kmt8nfj0qSTmaGwOPBPs5116JcBkY4tML3DAhANdeKe5qBroQCs5wTPL9sn4A2SBZlSOUQpXJPPYvTFxww0zgrrX2HsLAUxJBI83502dO6RNGL-9rdOF-4khoIrozXM6B96HhpyOHyNHCOBmNu79okInNJj1JkNQ6saWYoM8I6dtN712KU15OV3OPecfnE-K5kN4qGnk7VC4nBdwWfUJKEViCCkab4cg0GYIqVOB7Ddk14F2bCg51Dt0a-ZaKTpshtPFZgy1E-RO4gtnR-aPD40I3OS-oq5EevyYYVEnMGaBRIKAODb1nX3XxuImQx97zK4g=w906-h594-no"&gt;&lt;img src="https://lh3.googleusercontent.com/VzWM-H8o3hgBhv8tLNPJtboYgbIfZDfnBujVit7DuydDmXjwEZV-7IOAamZZ9hgPtGfQXNu-bc9KGARaih3fC44isiYkrKEJfpmxWCJ4FTxKQ4y4Z0ci999E1ElyvesQrulyf6p5CiLCJuDz_SAVOc7ajeW6msndsPvKKQ299auOLALioE8jjT5j5E1yovokyppzrHw26U6MKq9ua4jXN9UgXqnashT_avnUwnCtQm1xuY7EgyyBJ8-z_d5K-pw8Sic_uh00383Go59jSy98Mj_1X9edbjmzepuY1QBZKlhl6EIby9ekv4CmLMNGfywhU5XZgSTncib0GZXHQcZiU_4G6Aogp3kmt8nfj0qSTmaGwOPBPs5116JcBkY4tML3DAhANdeKe5qBroQCs5wTPL9sn4A2SBZlSOUQpXJPPYvTFxww0zgrrX2HsLAUxJBI83502dO6RNGL-9rdOF-4khoIrozXM6B96HhpyOHyNHCOBmNu79okInNJj1JkNQ6saWYoM8I6dtN712KU15OV3OPecfnE-K5kN4qGnk7VC4nBdwWfUJKEViCCkab4cg0GYIqVOB7Ddk14F2bCg51Dt0a-ZaKTpshtPFZgy1E-RO4gtnR-aPD40I3OS-oq5EevyYYVEnMGaBRIKAODb1nX3XxuImQx97zK4g=w906-h594-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;よくよく読んでみると、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We&amp;rsquo;ve added some basic stories inside the storybook/stories directory. A story is a single state of one or more UI components. You can have as many stories as you want. Basically a story is like a visual test case.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;とあります。ファイルを追加したみたいです。確かにプロジェクトディレクトリに新しいファイルなどが追加されていました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;storybook
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;├── addons.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;├── index.android.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;├── index.ios.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;├── index.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;├── stories
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;│   ├── Button
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;│   │   ├── index.android.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;│   │   └── index.ios.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;│   ├── CenterView
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;│   │   ├── index.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;│   │   └── style.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;│   ├── Welcome
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;│   │   └── index.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;│   └── index.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;└── storybook.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;4 directories, 11 files
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実行してくれ、とあるので実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ react-native run-ios
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;なんかでた。ブラウザ側を触るとモバイル側も連動してますね。何か連携しているんでしょうか？&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/JTNWSc64CLIF53GDQmL_qgkQxGBSCkA75dSTjliGlaVOespOUzXdJ_z-ljuYiMr71owM1daqO20VTPZ72ISNkeiGlEwzWqEGScadI34hzI19n6ownag20yLqcebjuV9LmmsAPxnY-ihi7_cji75qxRxbRC77baEMqrs-RMryDiBXB5CjR59B773PP-trfa75NJcPmRBLu8muR0EgDeFJ4LUIrCc4-jD9wsixvlXWzXEAkeyqNq1ivaG8urnvFTdyOmfIwhVph0AO4TsDrfbeSD7tu4Jv7haGp2t7sD1rDfTeuvaB-2GUj-z0cTVMAL4YffjTDOnCDz9d3tr8enNLAGbub4ajqjXH5KD4k9GpzeIuE6asTP70AucWfZ886UTucWlZ_NCm8yTydL4CGoCzNrMcw8YUrE9hmEpeOs9YVUzve8t7aOTuBwfFutHQ_fK9u2OE5prf--i9QzUMyd7WutQ5gVqtACO8Jl-pzQwFVH0gVIvIQzwxjFtlgwQwWRFCTX9dMoAA93Q9FqMsyi42fhyCxmc8sd4VnzDR_NZ8XKxPLDO2GsErdOdOLSWyqtPL8E_3hNyde8akDZUY83C4xuAo3nRMBAU8CCuacfbwl4rS5Dw7sRB4tr56Nc7Nyz5UUh0LruZIspLGHI7FUpnDCDsB3PSk1qMq9A=w1317-h772-no"&gt;&lt;img src="https://lh3.googleusercontent.com/JTNWSc64CLIF53GDQmL_qgkQxGBSCkA75dSTjliGlaVOespOUzXdJ_z-ljuYiMr71owM1daqO20VTPZ72ISNkeiGlEwzWqEGScadI34hzI19n6ownag20yLqcebjuV9LmmsAPxnY-ihi7_cji75qxRxbRC77baEMqrs-RMryDiBXB5CjR59B773PP-trfa75NJcPmRBLu8muR0EgDeFJ4LUIrCc4-jD9wsixvlXWzXEAkeyqNq1ivaG8urnvFTdyOmfIwhVph0AO4TsDrfbeSD7tu4Jv7haGp2t7sD1rDfTeuvaB-2GUj-z0cTVMAL4YffjTDOnCDz9d3tr8enNLAGbub4ajqjXH5KD4k9GpzeIuE6asTP70AucWfZ886UTucWlZ_NCm8yTydL4CGoCzNrMcw8YUrE9hmEpeOs9YVUzve8t7aOTuBwfFutHQ_fK9u2OE5prf--i9QzUMyd7WutQ5gVqtACO8Jl-pzQwFVH0gVIvIQzwxjFtlgwQwWRFCTX9dMoAA93Q9FqMsyi42fhyCxmc8sd4VnzDR_NZ8XKxPLDO2GsErdOdOLSWyqtPL8E_3hNyde8akDZUY83C4xuAo3nRMBAU8CCuacfbwl4rS5Dw7sRB4tr56Nc7Nyz5UUh0LruZIspLGHI7FUpnDCDsB3PSk1qMq9A=w1317-h772-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;なるほど、コンポーネントカタログみたいなやつかな！？&lt;/p&gt;
&lt;h1 id="storyを追加してみる"&gt;storyを追加してみる&lt;/h1&gt;
&lt;p&gt;物は試し、&lt;code&gt;stories/index.js&lt;/code&gt;に以下のようなコードで2個ほどコンポーネントを追加してみました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;storiesOf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Components&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;module&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;背景色があるView&amp;#39;&lt;/span&gt;, () =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;View&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ &lt;span style="color:#a6e22e"&gt;flex&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;backgroundColor&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#FFAAAA&amp;#39;&lt;/span&gt;}}&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/View&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;アバターとコメント&amp;#39;&lt;/span&gt;, () =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;CenterView&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;TouchableOpacity&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ &lt;span style="color:#a6e22e"&gt;backgroundColor&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#FFF&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;width&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;100%&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;flexDirection&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;row&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;padding&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;backgroundColor&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#EEE&amp;#39;&lt;/span&gt; }}&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Image&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ &lt;span style="color:#a6e22e"&gt;height&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;width&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;marginRight&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; }} &lt;span style="color:#a6e22e"&gt;source&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{&lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;https://blog.piyo.tech/images/prof.png&amp;#39;&lt;/span&gt;}} &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;View&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ &lt;span style="color:#a6e22e"&gt;backgroundColor&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;transparent&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;flex&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;height&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; }}&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Text&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;We&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;ve&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;added&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;some&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;basic&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stories&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;inside&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;the&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;storybook&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;stories&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;directory&lt;/span&gt;. &lt;span style="color:#a6e22e"&gt;A&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;story&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;is&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;single&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;one&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;or&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;more&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UI&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;components&lt;/span&gt;. &lt;span style="color:#a6e22e"&gt;You&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;can&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;have&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;as&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;many&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stories&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;as&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;you&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;want&lt;/span&gt;. &lt;span style="color:#a6e22e"&gt;Basically&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;story&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;is&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;like&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;visual&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;test&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/Text&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/View&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/TouchableOpacity&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/CenterView&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そしてシミュレータをリロードしてみると、うん、追加されてますね。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/kCPGTdTVaGWT1pJZcUp5S8Nbo553DGMAIuym4B9mLNpV-BZMkWPR-GjPyV0E8RMj5vZCsrYf67-IokZKvt9If2b_YknNRrJckOwT6th77GdAAhNBgtF4p7Lbze2Zcxi9JLkjXiMlDDJNfWB0WwsdyYbd9mkT9bdjXc92cAJYmAc61lrq5giRHWALi_b2Fgksy7M0FQgIy4llk35TastrznC0uqgQBjRlgg2yht5fSa1clKI4znH5l0ixhsjjc1N7Kxzprx8lHT3vHRqD8cLuAk5dRAvy-rjVCpU4PnB4qz0GB-HcGlUacWbo0OYDnfAS42EGAvDjqpXZIaaNK5kBqX7ZtCg0Szh2Q--7YKmzHSbCI0JIEHingxVql7d29dmjHvq74QDlOb3VXOF8q6iV5PWIUUoz1XIfuVSUM-TcQ64SmSwmnJyMPp69BiA4broYGTXagIFQArPu2dBHJLqE4cQid-WGPIEp-WtIYx3gN-jOoFw_zRVrdclvkhccAFBJxXCwcYZi4y13zrwl1GSsYnKCbHnt9ZdrRHlrKvq81JrdzSKfd6MKjdzMpS13a6E4oTtMNyUPF4KS3IpuLECZhkrQHprTOUhxPyime74HflnYEbvOySRz3xPnWsdCFxBthYxWGfhiWNwMbuuEWsxavC3B4AAn1B5BTw=w408-h703-no"&gt;&lt;img src="https://lh3.googleusercontent.com/kCPGTdTVaGWT1pJZcUp5S8Nbo553DGMAIuym4B9mLNpV-BZMkWPR-GjPyV0E8RMj5vZCsrYf67-IokZKvt9If2b_YknNRrJckOwT6th77GdAAhNBgtF4p7Lbze2Zcxi9JLkjXiMlDDJNfWB0WwsdyYbd9mkT9bdjXc92cAJYmAc61lrq5giRHWALi_b2Fgksy7M0FQgIy4llk35TastrznC0uqgQBjRlgg2yht5fSa1clKI4znH5l0ixhsjjc1N7Kxzprx8lHT3vHRqD8cLuAk5dRAvy-rjVCpU4PnB4qz0GB-HcGlUacWbo0OYDnfAS42EGAvDjqpXZIaaNK5kBqX7ZtCg0Szh2Q--7YKmzHSbCI0JIEHingxVql7d29dmjHvq74QDlOb3VXOF8q6iV5PWIUUoz1XIfuVSUM-TcQ64SmSwmnJyMPp69BiA4broYGTXagIFQArPu2dBHJLqE4cQid-WGPIEp-WtIYx3gN-jOoFw_zRVrdclvkhccAFBJxXCwcYZi4y13zrwl1GSsYnKCbHnt9ZdrRHlrKvq81JrdzSKfd6MKjdzMpS13a6E4oTtMNyUPF4KS3IpuLECZhkrQHprTOUhxPyime74HflnYEbvOySRz3xPnWsdCFxBthYxWGfhiWNwMbuuEWsxavC3B4AAn1B5BTw=w408-h703-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;なるほど、なんとなくわかってきた。&lt;/p&gt;
&lt;h1 id="オワリ"&gt;オワリ&lt;/h1&gt;
&lt;p&gt;なるほどコンポーネントをたくさん作っておいて、スタイルガイド的に使うのかなー？React Nativeアップデートのときとかに便利かもなーなどと思いました。&lt;/p&gt;
&lt;p&gt;だけど一人で開発していることが多いからしばらくはなくても大丈夫そうです。&lt;/p&gt;</description></item><item><title>Googleカレンダーの予定を毎朝LINEに通知する</title><link>https://blog.piyo.tech/posts/2018-04-17-line-notify/</link><pubDate>Tue, 17 Apr 2018 06:39:28 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-17-line-notify/</guid><description>&lt;p&gt;小ネタです。カレンダーアプリを見ればいいだけの話なんですが、どうも見忘れてしまうのでLINEに通知しようと思い立ち実施したよという話です。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p lang="ja" dir="ltr"&gt;今日の予定を毎朝LINEに送ってくれるbotないかな？ありそうなもんだけど&lt;/p&gt;&amp;mdash; Hiromasa Ohno（ぴー） (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/status/841811134575403008"&gt;March 15, 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;IFTTTがいけるかもしれないなと思って調べましたが、Googleカレンダー関係では新規予定の登録や予定開始の15分前になったらといったトリガーしかなく、自分が参照しているカレンダーの予定を一括で取ってきてどうこうみたいなことは難しそう。&lt;/p&gt;
&lt;p&gt;なのでGoogleAppsScriptを使ってみることにしました。似たようなことをチャットワーク宛に実現している方がいたのでそちらを参考にしつつ、元のコードが1つのカレンダーにしか対応していなかったのを全カレンダーを対象にしたり、LINE Notifyに対応したりといった改修を行っています。&lt;/p&gt;
&lt;h1 id="line-notifyのトークン取得"&gt;LINE Notifyのトークン取得&lt;/h1&gt;
&lt;p&gt;LINE NotifyはLINEにメッセージを通知するため仕組みです。LINE Notify APIにトークンとメッセージを送るとトークンが紐づけられたグループにメッセージが届きます。&lt;/p&gt;
&lt;p&gt;本来はウェブサービスなどからOAuthで認証して使うサービスなのですが、開発者向けにパーソナルトークンを発行できるようになっているので、今回のような用途ではパーソナルトークンを使うほうがいいでしょう。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://notify-bot.line.me/doc/ja/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;LINE Notify&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;span class="truncate"&gt;notify-bot.line.me&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;このサイトの右上リンクからLINEのIDログインして、画面下にある「トークンを発行する」から進みます。今回の連携に名前を付け、適当送信先のグループを選べばトークンが発行されますのでそれを控えておきます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://qiita-image-store.s3.amazonaws.com/0/19098/0104867d-fd72-c10a-323a-921ae645e45c.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;送信先グループはLINE Notifyとの1:1のチャットか、グループを選べます。グループを選んだ場合はLINE Notifyアカウントをそのグループに追加しておかなければなりません。&lt;/p&gt;
&lt;p&gt;僕の場合は、「今日の予定」という自分（+ LINE Notify）だけのグループを作り、そこに送るよう設定しました。&lt;/p&gt;
&lt;p&gt;(※初めて登録したときの流れを忘れてしまっています。もしかしたらログイン以外にも何かしなければいけなかったかもしれません）&lt;/p&gt;
&lt;h1 id="google-apps-script"&gt;Google Apps Script&lt;/h1&gt;
&lt;p&gt;Googleドライブの適当な場所にスクリプトを置きます。右クリックして「Google Apps Script」を選びます。見当たらない場合は一番下の「アプリを追加」からGoogle Apps Scriptを追加したあと同じ操作をします。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://qiita-image-store.s3.amazonaws.com/0/19098/555cc27f-3356-347d-f074-f7ec8487a871.png" alt="スクリーンショット 2017-03-15 13.17.36.png"&gt;&lt;/p&gt;
&lt;p&gt;エディタが出るのでこのコードをパッと貼ります。一番上の行にはLINE Notifyで取得したトークンを入れます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;lineToken&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;YOUR-LINE-TOKEN&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;calendars&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CalendarApp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getAllCalendars&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;text&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Utilities&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;formatDate&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Date(), &lt;span style="color:#e6db74"&gt;&amp;#39;JST&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;yyyy/MM/dd&amp;#39;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;calendars&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;calendar&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;calendars&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;events&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;calendar&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getEventsForDay&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Date());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;( &lt;span style="color:#a6e22e"&gt;events&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;text&lt;/span&gt; &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;◆ &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;calendar&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getName&lt;/span&gt;() &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;events&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;event&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;events&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;event&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getTitle&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;start&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;toTime&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;event&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getStartTime&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;end&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;toTime&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;event&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getEndTime&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;text&lt;/span&gt; &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;start&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39; - &amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;end&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;( &lt;span style="color:#a6e22e"&gt;events&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;text&lt;/span&gt; &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;sendToLine&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;text&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sendToLine&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;text&lt;/span&gt;){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;token&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;lineToken&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;options&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;method&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;post&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;payload&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;message=&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;text&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;headers&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;Authorization&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Bearer &amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;token&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;UrlFetchApp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;fetch&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;https://notify-api.line.me/api/notify&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;options&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;42&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;43&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;toTime&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;str&lt;/span&gt;){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;44&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Utilities&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;formatDate&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;str&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;JST&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;HH:mm&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;45&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;メニューの「実行」から&lt;code&gt;main&lt;/code&gt;を選ぶとスクリプトが実行されますが、一番最初の起動時はカレンダーの認証が入ります。一旦許可したあとは認証されたものとして、そのアカウントが参照しているカレンダー全てから予定を集めてLINEにメッセージを飛ばしてくれるはずです。&lt;/p&gt;
&lt;p&gt;あとは毎朝自動でこのスクリプトが走るようにすれば良いですね。メニュー下にあるツールバーの時計のようなアイコンからトリガーを追加し、希望の時間に設定すればOKです。&lt;/p&gt;
&lt;h1 id="参考"&gt;参考&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://tonari-it.com/gas-calendar/"&gt;毎朝、当日の予定をGoogleカレンダーから取得してチャットワークに送る&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://qiita.com/tadaken3/items/5f916a12587e42ece814"&gt;Google App ScriptからLINE NotifyでLINEにメッセージを送る&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Blazer gemでRailsにSQL集計ダッシュボードをつける</title><link>https://blog.piyo.tech/posts/2018-04-16-rails-blazer/</link><pubDate>Mon, 16 Apr 2018 06:43:45 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-16-rails-blazer/</guid><description>&lt;p&gt;◯◯なユーザーのリストが欲しい、といった類の要望をお客さんにもらうことがあります。SQLでデータを引っ張ってくればリストを作れるものの、本番DBに繋いでSQL投げて出てきたものを渡す、ってことを考えると大変です。いずれ見たい情報が増えることを考えるとWeb側にそれ用の画面を用意するのは現実的ではありません。&lt;/p&gt;
&lt;p&gt;そこで登場するのが今回取り上げた&lt;a href="https://github.com/ankane/blazer"&gt;Blazer&lt;/a&gt;というgemです。BlazerはRailsのmountable engineの仕組みで自分のRailsアプリにBlazerの画面を簡単にマウントできるようになっています。Blazerの画面でSQLを書いて実行し、保存しておくことができます。保存済のクエリの画面へ行くと、現在のDBからそのクエリで情報を取り出して一覧にしてくれ、CSVダウンロードも可能です。&lt;/p&gt;
&lt;p&gt;さらにBlazerは↓な感じでチャートを表示することもできるらしい。まだ使いこなせてないですが、かっこいいです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/XFzLPqSo0OBCL2RuQhJhGZubWGn-f8QBjv66Z9SdZMY4qYJ3hja7ze26UaY-2ZjoskJfvYLxMk41s92_DeJXaZquAbTU3O2XQgRQBMnc4GKyEbcOFIanVe5OtGFfDh2z28utafzy5V8GVyJl-CG7u7_aavCMmDwTBB3gxtY8IS1bAw9iWXxJZEExaD6TWoKpRLFOoTysxiFZvT7Fe39uZRBlzLxgovQBfa0QGzCxz4oRw5_v8ow8aEqNcn0kRKeSuTmspzuB69Z0Fl1KECKRyNzdJH_dmhaDntII75FMXSW6Q0c7GK9xf_4grqPfrRxTStzLJ2cbY-_g9l_eaeEs_VygRRKMuRH0ZSfDqDwvZwFpIAodxahNsV5N0fvVgT4OWg6KGzOtHL4XAMF7PJSS4DE6ka-JWcjx9HJ9mHdnE5YBxz79SA6izGCv9KNN6U6oVH3w9pflERTTifNIBFa69Wdyicu3UQpHiwaQf-lyigccB-JjtEk3Y-i5sDkP4lXoMne6vhkcCihtvmpmCtft1jmXVEEnJp8smDL8NNaTzZN02MvwjcnYNSGTAYu2LgIORad82-tAPeeeWr3BhP_U3JO2EWx-_na9p2CeJeBNM5ED414G_qEUAx1Qj1FbApliQaDdX5dV8YiTohUBn9WsVXECsosTWxbycA=w1174-h645-no"&gt;&lt;img src="https://lh3.googleusercontent.com/XFzLPqSo0OBCL2RuQhJhGZubWGn-f8QBjv66Z9SdZMY4qYJ3hja7ze26UaY-2ZjoskJfvYLxMk41s92_DeJXaZquAbTU3O2XQgRQBMnc4GKyEbcOFIanVe5OtGFfDh2z28utafzy5V8GVyJl-CG7u7_aavCMmDwTBB3gxtY8IS1bAw9iWXxJZEExaD6TWoKpRLFOoTysxiFZvT7Fe39uZRBlzLxgovQBfa0QGzCxz4oRw5_v8ow8aEqNcn0kRKeSuTmspzuB69Z0Fl1KECKRyNzdJH_dmhaDntII75FMXSW6Q0c7GK9xf_4grqPfrRxTStzLJ2cbY-_g9l_eaeEs_VygRRKMuRH0ZSfDqDwvZwFpIAodxahNsV5N0fvVgT4OWg6KGzOtHL4XAMF7PJSS4DE6ka-JWcjx9HJ9mHdnE5YBxz79SA6izGCv9KNN6U6oVH3w9pflERTTifNIBFa69Wdyicu3UQpHiwaQf-lyigccB-JjtEk3Y-i5sDkP4lXoMne6vhkcCihtvmpmCtft1jmXVEEnJp8smDL8NNaTzZN02MvwjcnYNSGTAYu2LgIORad82-tAPeeeWr3BhP_U3JO2EWx-_na9p2CeJeBNM5ED414G_qEUAx1Qj1FbApliQaDdX5dV8YiTohUBn9WsVXECsosTWxbycA=w1174-h645-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;（ちなみに、同様の機能を提供する&lt;a href="https://github.com/esminc/adhoq"&gt;Adhoq&lt;/a&gt;というgemもあります。こちらは日本の永和システムマネジメントさん中心に開発されています）&lt;/p&gt;
&lt;h1 id="最低限の導入"&gt;最低限の導入&lt;/h1&gt;
&lt;p&gt;ローカルで最低限動くようにするために必要なのはたった3ステップです。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;gem追加&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Gemfileに&lt;code&gt;gem 'blazer'&lt;/code&gt;を追記して、&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ bundle install
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;インストール&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ rails g blazer:install
$ rake db:migrate
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;routes.rb更新&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;mount Blazer::Engine, at: &amp;#34;blazer&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これで&lt;code&gt;localhost:3000/blazer&lt;/code&gt;でBlazerのダッシュボードにアクセスできるようになります。 &lt;code&gt;blazer_path&lt;/code&gt;というURLヘルパーも使えるようになります。&lt;/p&gt;
&lt;p&gt;ちなみにBlazer公式のDemoサイトがこちらです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blazer.dokkuapp.com/"&gt;Blazer Demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここでは実際にクエリを発行して試せるはず。気になったら触ってみるといいと思います。&lt;/p&gt;
&lt;h1 id="認証をつける"&gt;認証をつける&lt;/h1&gt;
&lt;p&gt;ベーシック認証、Deviseのresourceを使った認証といった簡易に設定できる認証があります。今回のRailsアプリの場合はDeviseにUserモデルとAdministratorモデルがあるなどして、簡易な方法ではうまく動かなかったこともあって、&lt;code&gt;before_action&lt;/code&gt;を利用する方法を採りました。&lt;/p&gt;
&lt;p&gt;READMEのこの部分に該当します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ankane/blazer#other"&gt;ankane/blazer: Business intelligence made simple&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;blazer.yml&lt;/code&gt;内の&lt;code&gt;user_class&lt;/code&gt;, &lt;code&gt;user_method&lt;/code&gt;, &lt;code&gt;before_action&lt;/code&gt;を次のように書き換えました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;user_class&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Administrator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;user_method&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;current_administrator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;before_action&lt;/span&gt;: :&lt;span style="color:#ae81ff"&gt;authenticate_blazer_user!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;user_class&lt;/code&gt;はBlazerの画面のユーザーとなるモデルのクラス、ここでは&lt;code&gt;Administrator&lt;/code&gt;を指定しました。&lt;code&gt;user_method&lt;/code&gt;はそのユーザーを返すメソッドで、ここではDeviseの&lt;code&gt;current_administrator&lt;/code&gt;ヘルパーメソッドを指定します。&lt;/p&gt;
&lt;p&gt;最後の&lt;code&gt;before_action&lt;/code&gt;が認証の本体で、メソッドのシンボルを指定します。これを&lt;code&gt;application_controller.rb&lt;/code&gt;に書きます。current_administratorがいなければリダイレクトするよ、となってます。これで管理者として正しく認証できていないときにはリダイレクトされる（＝使えない）ことになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rb" data-lang="rb"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;authenticate_blazer_user!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; redirect_to root_url &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; current_administrator
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="本番で使う"&gt;本番で使う&lt;/h1&gt;
&lt;p&gt;READMEのこの部分が該当します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ankane/blazer#permissions"&gt;ankane/blazer: Business intelligence made simple&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;読み取り権限のみの専用ユーザーを作って使おう、という話です。ここでユーザーを作ったら、本番環境の&lt;code&gt;BLAZER_DATABASE_URL&lt;/code&gt;にDBのURLをユーザー名、パスワード付で指定します。&lt;/p&gt;
&lt;p&gt;僕の場合はpostgresqlだったのでこんな感じになります。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;postgres://blazer:your-password@your-db-host-name/your-db-name
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;p&gt;これで、お客さんに〇〇データが欲しい、と言われたときに簡単にデータを抽出できるわけです。こないだ勉強したSQLが火を吹きますね。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-03-25-sql/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://images-na.ssl-images-amazon.com/images/I/71krcGTLsKL.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;O/RマッパーからDB触り始めた人にSQL書き方ドリルがおすすめ - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;tl;dr SQL苦手な人にこの本めちゃくちゃオススメです。特に手を動かさないと頭に入らない人向け。すごく凝ったことはできるようにならないかもしれないけど、少なくともSQLへの苦手意識は払拭されます。 https://www.amazon.co.jp/o/ASIN/4774180661/ 僕とRDBMSとの関わり ↓のような感じの仕事歴で、前半はRDBMSにほとんど接する機会がありませんでした。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4774180661/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/71krcGTLsKL._SL1000_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;改訂第3版 すらすらと手が動くようになる SQL書き方ドリル (WEB&amp;#43;DB PRESS plus)&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ダッシュボード機能とチャートについては今度書こう。&lt;/p&gt;</description></item><item><title>WebStormでファイルを保存する度にESLintする</title><link>https://blog.piyo.tech/posts/2018-04-14-eslint-auto-fix/</link><pubDate>Sat, 14 Apr 2018 06:40:06 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-14-eslint-auto-fix/</guid><description>&lt;p&gt;みんなも使ってるESList。自動でFixできるところはどんどん勝手に直して欲しい。WebStormならそんな想いを実現してくれることがわかりました。&lt;/p&gt;
&lt;p&gt;（※ちなみにJetBrainsのIDEならどれでも対応しているはずです。RubyMineでも似たようなことができるでしょう）&lt;/p&gt;
&lt;h1 id="1-file-watcherを使う"&gt;1. File Watcherを使う&lt;/h1&gt;
&lt;p&gt;File Watcherという、ファイルを監視する仕組みがあることを知りました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.jetbrains.com/help/webstorm/settings-tools-file-watchers.html" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://resources.jetbrains.com/storage/products/webstorm/img/meta/preview.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;File Watchers | WebStorm&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://jetbrains.com/favicon-32x32.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;www.jetbrains.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;File WatcherはWebStormシステムで、ファイルの変更を追跡し、サードパーティのスタンドアロンアプリケーションを実行します。 WebStormは、このような一般的な一般的なサードパーティのツール（コンパイラ、コンプレッサ、プリティファクタなど）のための定義済みのFile Watcherテンプレートを提供します。他のサードパーティのツールを実行するようにカスタムFile Watcherを設定することもできます。
（ページ内の概要をGoogle翻訳）&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;設定のしかた&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Preferenceを開く&lt;/li&gt;
&lt;li&gt;「File Watcher」と検索&lt;/li&gt;
&lt;li&gt;Tools以下のFile Wathchersが見つかる&lt;/li&gt;
&lt;li&gt;下にある＋ボタンを押す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/0yTuvumJBl0LVM3O6LM6RK8CdxRhNbycg7CL5BHmTsX3inhJrH9VC-5mWkr-MAuRLycJ9eih9QqDXv6jhmzyIbN3AhrQaLBGDDNWHfCgAp7R5sjVgf0f4oXk6mm4YUFmI58vVWv1gSgleIatMYIZHouEr_fcANkFikqdddjkZVP2eorMSh_tqWaOfdv9WDdluPKIZKimNVVeGNN_8ewuAFQS-ASgHTp0e0YmhOVysPvUHXcZotolb4bynzevr1GxiuoOOb98zxIXfNDlhZaDNPXmWPxSUJroqBuVbOgm4sUni9HJEq_gY1Sk-InCX1PMHIAA5UZ1oTPhV4VaLkZHmzznhzH3rq-eYUCPYtaUCIyEVoyp9rFVXkwlM_hPNzzTXTQpJeBZ6IcrsJC4Z_3n6GmXOsrtMHRz32wihQE_sdL1bcO6e32dnnUAbkX4Br9IvNvtDkDRPytuQwppjdXBRnen8DYHqGorWZ2mZF9pihrxuKEI0ZopxJFDos6h7W1eNP0H6WL-mptuw1EZM1SrbWY544maNl3zBXTz65vGZytQxCCjn0S-L03f-utdzozl1GZ1OHgO70cxDtQbVgsG_AJw4NRXstBr16zrrxy7j9Zn61qUYAiWnCxFjOQvus0hq5Jii_tg9REAes--tEmvtOKPfGGWNv53ZQ=w704-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/0yTuvumJBl0LVM3O6LM6RK8CdxRhNbycg7CL5BHmTsX3inhJrH9VC-5mWkr-MAuRLycJ9eih9QqDXv6jhmzyIbN3AhrQaLBGDDNWHfCgAp7R5sjVgf0f4oXk6mm4YUFmI58vVWv1gSgleIatMYIZHouEr_fcANkFikqdddjkZVP2eorMSh_tqWaOfdv9WDdluPKIZKimNVVeGNN_8ewuAFQS-ASgHTp0e0YmhOVysPvUHXcZotolb4bynzevr1GxiuoOOb98zxIXfNDlhZaDNPXmWPxSUJroqBuVbOgm4sUni9HJEq_gY1Sk-InCX1PMHIAA5UZ1oTPhV4VaLkZHmzznhzH3rq-eYUCPYtaUCIyEVoyp9rFVXkwlM_hPNzzTXTQpJeBZ6IcrsJC4Z_3n6GmXOsrtMHRz32wihQE_sdL1bcO6e32dnnUAbkX4Br9IvNvtDkDRPytuQwppjdXBRnen8DYHqGorWZ2mZF9pihrxuKEI0ZopxJFDos6h7W1eNP0H6WL-mptuw1EZM1SrbWY544maNl3zBXTz65vGZytQxCCjn0S-L03f-utdzozl1GZ1OHgO70cxDtQbVgsG_AJw4NRXstBr16zrrxy7j9Zn61qUYAiWnCxFjOQvus0hq5Jii_tg9REAes--tEmvtOKPfGGWNv53ZQ=w704-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;変更時に何をするのかを設定する画面となります。&lt;/p&gt;
&lt;p&gt;↓画像枠の部分にESLintのコマンドとコマンドの引数、再読込するパスなどを指定します。他にもオプションが幾つかあるので必要に応じて設定します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/GSMOirLTXTL1AmlKzmW185b_WPUD08aCNjFC4mpDAxRB-KrOXzKc6chZv7XgcBbiKUDbvmf_E-SHyHw2dtqjgxd5W9xCu-fbwIvZSv_7bSPPN_6fRKg-4fkszwYATc5tmZN2JU5wZJUYa2bp56Azc9y0CDepI_95OFf4c5iphFZST4Ltb0Ac9eGBmW27q7tFYkGQxfCotGt7wVYdFxP-gUZWy3pAuuIpjElDMMKuEqdDLtKaQyOomSJP66HguJxdeXE_zgUofbiocxee9LMK_8ru8rwIu05dZLLvf1q9Jnro8k84gQOD46BgKsgcPdALeo12812kXnypuTaTFOLzl00B04trJCAS5ESnqmxflZ_bjQbFV4Yxl0kE_lvj9OAnqceDmrMCg3YStbT6nRQlN14K9UAo5vlGVpyO6dBYYYcTZc4j8w2Wm_JKCOFn6j7aTqNSpbWGrteWEeVuQkfyd__O-ntTkP-MDZXiTEeDkTMxY5foSemvCGl-5tg8UI6bduLu8R8KokaWzeQYPNT4vlybvbkEzUEq6oO17UtyhxxdNk44APbgXrWPVMEsCrto03yIRcLClTAimlsZDvQyjlvVTsRGZuWXFBAyc71Q2w47tsoYDncqHuV3OTwQGhZ3BZqzMgtEZxVva27XOLT3pro37oEjZfFTsg=w1156-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/GSMOirLTXTL1AmlKzmW185b_WPUD08aCNjFC4mpDAxRB-KrOXzKc6chZv7XgcBbiKUDbvmf_E-SHyHw2dtqjgxd5W9xCu-fbwIvZSv_7bSPPN_6fRKg-4fkszwYATc5tmZN2JU5wZJUYa2bp56Azc9y0CDepI_95OFf4c5iphFZST4Ltb0Ac9eGBmW27q7tFYkGQxfCotGt7wVYdFxP-gUZWy3pAuuIpjElDMMKuEqdDLtKaQyOomSJP66HguJxdeXE_zgUofbiocxee9LMK_8ru8rwIu05dZLLvf1q9Jnro8k84gQOD46BgKsgcPdALeo12812kXnypuTaTFOLzl00B04trJCAS5ESnqmxflZ_bjQbFV4Yxl0kE_lvj9OAnqceDmrMCg3YStbT6nRQlN14K9UAo5vlGVpyO6dBYYYcTZc4j8w2Wm_JKCOFn6j7aTqNSpbWGrteWEeVuQkfyd__O-ntTkP-MDZXiTEeDkTMxY5foSemvCGl-5tg8UI6bduLu8R8KokaWzeQYPNT4vlybvbkEzUEq6oO17UtyhxxdNk44APbgXrWPVMEsCrto03yIRcLClTAimlsZDvQyjlvVTsRGZuWXFBAyc71Q2w47tsoYDncqHuV3OTwQGhZ3BZqzMgtEZxVva27XOLT3pro37oEjZfFTsg=w1156-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これで保存のたびにESLintがかかります。&lt;/p&gt;
&lt;h1 id="2-ショートカットを上書きする"&gt;2. ショートカットを上書きする&lt;/h1&gt;
&lt;p&gt;ショートカットを上書きすることでWebStormにある「Fix ESlint Problem」というコマンド（アクション？）を保存のたびに呼ぶ方法です。&lt;/p&gt;
&lt;p&gt;ちょっと見づらくなってしまってますが、「Fix　ESLint Problem」のコマンドのショートカットを「⌘S」に割り当てています。通常「保存（Save All）」に使われるショートカットです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/bW0Y5fJgm3w5IzcLJkHrc94qinXplefyBEXRPf7NRMVItvmgArhkvlVL2X0yAHpZWuwhtTuKmQZue1n6JbCDkMB9Fiv3HRzRcXps7kmfPuPXTl5l_g2Ti1uWF3bTCXcTAagX4fBok25tS5fL81Rz4E00kI8wQnXCJv6ZfrsJzVg6CeE4ij6Vp-nWVUkxlXTNiQGj0jQPVFdlj04pwYv_UOKz4RPjRlop5uxBv74QoWh8XDeBVEUeYoTxi1p4RXDkUJ1ArOTltlAVSNjiAzFoEgZWyFnwgOP2jhW8ddQHgo-OW3wgOENeWx0i_MLsiNVd6-3dfREQwELnSMWkDkS1ZZu8wfvy77ZDPTu38alAw3hP5KzkyANEAaizsoey25pE8GZafVeesAMeOzb3b7QhvFrR0lYr9q2J0GyHe3hYSBwTsuvzh0QZez3b_H1S4Iuon-DQ95Mp8oParDiNY3gYcm_5PEKhDWRNjxUhwj_485UCLU-Ws1zJ-QEcpHzyhyRkp5dSOQTS7TTNL7rNkDjQAIIGa2KVn5BT7S3qQMEri7hMXOfNLLk9swFo8WIbWYAbvCC7rSA9gyPt6pw8L4vuWciGeQspM3LoE1a1KEvAmnDp6xIRWYXTGaOwoBHQBIi1IsTMdac1XzfluKPz4GgzbengGFrJgwb6vg=w1403-h928-no"&gt;&lt;img src="https://lh3.googleusercontent.com/bW0Y5fJgm3w5IzcLJkHrc94qinXplefyBEXRPf7NRMVItvmgArhkvlVL2X0yAHpZWuwhtTuKmQZue1n6JbCDkMB9Fiv3HRzRcXps7kmfPuPXTl5l_g2Ti1uWF3bTCXcTAagX4fBok25tS5fL81Rz4E00kI8wQnXCJv6ZfrsJzVg6CeE4ij6Vp-nWVUkxlXTNiQGj0jQPVFdlj04pwYv_UOKz4RPjRlop5uxBv74QoWh8XDeBVEUeYoTxi1p4RXDkUJ1ArOTltlAVSNjiAzFoEgZWyFnwgOP2jhW8ddQHgo-OW3wgOENeWx0i_MLsiNVd6-3dfREQwELnSMWkDkS1ZZu8wfvy77ZDPTu38alAw3hP5KzkyANEAaizsoey25pE8GZafVeesAMeOzb3b7QhvFrR0lYr9q2J0GyHe3hYSBwTsuvzh0QZez3b_H1S4Iuon-DQ95Mp8oParDiNY3gYcm_5PEKhDWRNjxUhwj_485UCLU-Ws1zJ-QEcpHzyhyRkp5dSOQTS7TTNL7rNkDjQAIIGa2KVn5BT7S3qQMEri7hMXOfNLLk9swFo8WIbWYAbvCC7rSA9gyPt6pw8L4vuWciGeQspM3LoE1a1KEvAmnDp6xIRWYXTGaOwoBHQBIi1IsTMdac1XzfluKPz4GgzbengGFrJgwb6vg=w1403-h928-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これを乗っ取る（＝元のは削除）することで保存したつもりがESlintをかけていた、という状態になります。&lt;/p&gt;
&lt;h1 id="終わり"&gt;終わり&lt;/h1&gt;
&lt;p&gt;最近はなんとなく2の方を使っています。&lt;/p&gt;
&lt;p&gt;FileWatcherの仕組みは他にも活用方法がありそうでいいなーと思ってます。そういえば昔はRails開発でファイルを変更したら自動的に該当箇所をテストするようなことやってたなーというのを思い出したり。&lt;/p&gt;</description></item><item><title>React Nativeでテキスト付きのローディングインジケーターを出す</title><link>https://blog.piyo.tech/posts/2018-04-12-react-native-indicator/</link><pubDate>Thu, 12 Apr 2018 06:05:37 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-12-react-native-indicator/</guid><description>&lt;p&gt;昨日はReact Nativeやってるよーな話を書きました。今日超具体的なライブラリの小ネタを書きます。長いのはたまにしか書けないね。&lt;/p&gt;
&lt;p&gt;読み込み時のクルクルについてです。React Nativeには標準でローディングインジケーターが用意されています。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://reactnative.dev/docs/activityindicator" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://reactnative.dev/img/logo-share.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;ActivityIndicator · React Native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Displays a circular loading indicator.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://facebook.github.io/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;facebook.github.io&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;なんだけど、色や大きさなどちょっとしたオプションしかなく、テキストと一緒に表示させることができません。もちろん&lt;code&gt;Text&lt;/code&gt;と一緒に使えばいいし、コンポーネントを作ってもいいし。&lt;/p&gt;
&lt;p&gt;でもまあ、これだけ汎用的なコンポーネントはさっさとパッケージを使うのが良いと思います。個人的には部品になるようなUIコンポーネントは積極的に使う派です。&lt;/p&gt;
&lt;p&gt;ざっくり探すと2つのライブラリが見つかりました。&lt;/p&gt;
&lt;p&gt;1つ目が、&lt;code&gt;react-native-loading-spinner-overlay&lt;/code&gt;&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/ladjs/react-native-loading-spinner-overlay" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/4b3f5dfdcc56bc9f989525e3c99289edbb807f7740623de44bd9425b891802bb/ladjs/react-native-loading-spinner-overlay" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - ladjs/react-native-loading-spinner-overlay: :barber: React Native loading spinner overlay&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;:barber: React Native loading spinner overlay. Contribute to ladjs/react-native-loading-spinner-overlay development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;2つ目は、&lt;code&gt;react-native-busy-indicator&lt;/code&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/RealOrangeOne/react-native-busy-indicator" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/a76ede582a666914a5900872ecc3a57a0205ff887cf98072af4011d26497fc7e/RealOrangeOne/react-native-busy-indicator" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - RealOrangeOne/react-native-busy-indicator: A simple, event controlled, busy indicator for react-native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;A simple, event controlled, busy indicator for react-native - RealOrangeOne/react-native-busy-indicator&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;前者のほうが2018/04/09時点でスター数が700近くと、後者の8倍近くのスター数です。前者のほうが最終更新が古いもののスター数を考えるとこちらでいいかな。&lt;code&gt;react-native-loading-spinner-overlay&lt;/code&gt;を試します。&lt;/p&gt;
&lt;h1 id="コード"&gt;コード&lt;/h1&gt;
&lt;p&gt;GitHubのREADMEにあるアニメーション画像では、テキストが入っていないので雰囲気がわかりません。そこで文字ありの雰囲気がわかるようにしてみます。&lt;/p&gt;
&lt;p&gt;何はともあれインストールとインポート。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ npm install --save react-native-loading-spinner-overlay@latest
&lt;/code&gt;&lt;/pre&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Spinner&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react-native-loading-spinner-overlay&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そして、ひとまず常に表示する形でコンポーネントを追加してみましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyComponent&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;View&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ &lt;span style="color:#a6e22e"&gt;flex&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;justifyContent&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;space-around&amp;#39;&lt;/span&gt; }}&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Button&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ボタン&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onPress&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{() =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;ボタン&amp;#39;&lt;/span&gt;)} &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Spinner&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;visible&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;textContent&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;読み込み中&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;textStyle&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ &lt;span style="color:#a6e22e"&gt;color&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;white&amp;#39;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/View&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;すると、このように表示されます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/W1Neepo3dQZ8cAkijQfGChrhVaHReg8oKUmtD5mfJS4d_5SM5mIMHhd8pVsQ8wytHw3Fd4WCJYvxC6hvJAp5Ju8o-LMbql435sZpZSp_o9XuhcCg5zKlBRWZvumzKrzIOVYncXoGKNdhjk09xFqr1d__EmGtuiLJLdxfh8iwPaleCjIJ-WRiSToMfeffS1OCWzYtSpfO3uERZqmdwZLHz5BjFozkp0QIo4wZ8fPi7aRHFDwf5UbmgcN3xvwe1HF2tEKF0H8yaiQ5mi6KrAZp3JM-oLQhaaAfu-rV6tc_EEfUuel61Fyf2XbiaJLVDPqLTmGmntmwf89IoMHfifzD105NrndQMGAVDshbzwf8ASTSttYxjB3zhrjvGtNlnNz_RIDPjgEe6tpwMSLsu0P61aAyP0A-c_vkBYWZJ33THd_fUR9NI_N8mzL6tqpaTYVEnddmpMpRbhtw7K5hsxiUO1snmNaxjr-fjAQsIjOIr7OClfFM07dQoOjeNUkvqDVM9WoJWqW7nnKUqy4YbzK69__KoBwaqww8pEKsqVmyDrpxlh6amI9ctBBGvc--o2RTJGPyd_JgaWWX6vRZFaMPsf8Lci-yZrbFd1YpVnNRV0LaiCxyUGYW3iqhNc-4HcTL4xTJSLLyflslt28N5y9uCPF8XDLwbnehfg=w429-h927-no"&gt;&lt;img src="https://lh3.googleusercontent.com/W1Neepo3dQZ8cAkijQfGChrhVaHReg8oKUmtD5mfJS4d_5SM5mIMHhd8pVsQ8wytHw3Fd4WCJYvxC6hvJAp5Ju8o-LMbql435sZpZSp_o9XuhcCg5zKlBRWZvumzKrzIOVYncXoGKNdhjk09xFqr1d__EmGtuiLJLdxfh8iwPaleCjIJ-WRiSToMfeffS1OCWzYtSpfO3uERZqmdwZLHz5BjFozkp0QIo4wZ8fPi7aRHFDwf5UbmgcN3xvwe1HF2tEKF0H8yaiQ5mi6KrAZp3JM-oLQhaaAfu-rV6tc_EEfUuel61Fyf2XbiaJLVDPqLTmGmntmwf89IoMHfifzD105NrndQMGAVDshbzwf8ASTSttYxjB3zhrjvGtNlnNz_RIDPjgEe6tpwMSLsu0P61aAyP0A-c_vkBYWZJ33THd_fUR9NI_N8mzL6tqpaTYVEnddmpMpRbhtw7K5hsxiUO1snmNaxjr-fjAQsIjOIr7OClfFM07dQoOjeNUkvqDVM9WoJWqW7nnKUqy4YbzK69__KoBwaqww8pEKsqVmyDrpxlh6amI9ctBBGvc--o2RTJGPyd_JgaWWX6vRZFaMPsf8Lci-yZrbFd1YpVnNRV0LaiCxyUGYW3iqhNc-4HcTL4xTJSLLyflslt28N5y9uCPF8XDLwbnehfg=w429-h927-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;背後にボタンを置いていますが、ローディングインジケータのオーバーレイがあるためボタンをタップすることはできません。ユーザーに操作させずに待たせることができます。&lt;/p&gt;
&lt;p&gt;オーバーレイの色が薄いと白文字や白インジケータが見にくいかもしれません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;overlayColor&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rgba(0, 0, 0, 0.5)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// デフォルトは
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// overlayColor=&amp;#34;rgba(0, 0, 0, 0.25)&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちょっと暗くするといい感じです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/nNIfKOqeCFc_s8pzgPfVvxL-FpJ1oiqqFEYfxkwgSTjGGo0oX_0ESvzdQqAgQRoXkoTzNQZZOUKG4F5LB3T6FmUGD163zvpkuA48eVQqJrY2G3JZByXglw8lKwPvXyy4dzDb_VL6bI6YZoEgyAhIIw_zQ3xG3O1mSyRKAb5lseAMHyffJ3JdVbrBGS-dULlnkg1r4FojIgd2E_e2MGkF-1GH1e0U2dw20VrahEn8oqNX99yLjDnf40eCAY3ZV2GlEKbBQjdtZhYN-mnq-snPtoc2siDIRJz9fERKJPrVh8am1Rt60ejQzZzT0Z_6u38bt7jBbcpHK4wTlGNZPXsL_an_Ez6hAX8_gL4N8Fk4vxzeVVOExNylg3uQ9jn4QwUk96BWY2dRfK0OG2ORNnsfuhCvh_ma1O_Hd_TRnZGwbrRFzZRMuW3PWmPXBrG1XT-Dl6NQ2vp5XpTeuI5BNIlsKf7Mue0X_-kRnCstMVEh0ST7m9atgzIdyWcfLSJjM1LU4H0QjbAmUAKnHRbcuUrRjV6MudINa7CT67n_apdLa8HxTPLSUpIfvcYQ9S0pLt2KFeC0bYsVcgFRhwJPaDiz1IcS2oLWmlCHas1DzwNpr7O5dQvRtxUuM0dzy286pHuxvl_GtKtQn9Eq3J8BCh8F3ahtDeNhx6FlCQ=w429-h927-no"&gt;&lt;img src="https://lh3.googleusercontent.com/nNIfKOqeCFc_s8pzgPfVvxL-FpJ1oiqqFEYfxkwgSTjGGo0oX_0ESvzdQqAgQRoXkoTzNQZZOUKG4F5LB3T6FmUGD163zvpkuA48eVQqJrY2G3JZByXglw8lKwPvXyy4dzDb_VL6bI6YZoEgyAhIIw_zQ3xG3O1mSyRKAb5lseAMHyffJ3JdVbrBGS-dULlnkg1r4FojIgd2E_e2MGkF-1GH1e0U2dw20VrahEn8oqNX99yLjDnf40eCAY3ZV2GlEKbBQjdtZhYN-mnq-snPtoc2siDIRJz9fERKJPrVh8am1Rt60ejQzZzT0Z_6u38bt7jBbcpHK4wTlGNZPXsL_an_Ez6hAX8_gL4N8Fk4vxzeVVOExNylg3uQ9jn4QwUk96BWY2dRfK0OG2ORNnsfuhCvh_ma1O_Hd_TRnZGwbrRFzZRMuW3PWmPXBrG1XT-Dl6NQ2vp5XpTeuI5BNIlsKf7Mue0X_-kRnCstMVEh0ST7m9atgzIdyWcfLSJjM1LU4H0QjbAmUAKnHRbcuUrRjV6MudINa7CT67n_apdLa8HxTPLSUpIfvcYQ9S0pLt2KFeC0bYsVcgFRhwJPaDiz1IcS2oLWmlCHas1DzwNpr7O5dQvRtxUuM0dzy286pHuxvl_GtKtQn9Eq3J8BCh8F3ahtDeNhx6FlCQ=w429-h927-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;簡易に使うには便利です。&lt;/p&gt;
&lt;p&gt;（まあ、React NativeのUIライブラリ系は簡易に使うのは便利だけど、ちょっと凝りたくなると結局自前コンポーネントにせざるを得ないってことが多いんですけどね。）&lt;/p&gt;</description></item><item><title>React Nativeで自社サービスのiOS/Androidアプリをリプレイスした話</title><link>https://blog.piyo.tech/posts/2018-04-11-react-native/</link><pubDate>Wed, 11 Apr 2018 06:30:37 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-11-react-native/</guid><description>&lt;h1 id="前置き"&gt;前置き&lt;/h1&gt;
&lt;p&gt;僕が所属しているソニックガーデンではRemottyというツールを自社で開発し、普段の業務に使っています。リモートワークをするためにオフィスと言ってもいいような場所で、業務中は常にオンラインとなり、リアルタイムチャット（対面の会話の代替）とトピックベースの掲示板（メールなど非同期コミュニケーションの代替）の両方を備えたオフィスとなるようなツールです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://ja.remotty.net" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://ja.remotty.net/wp-content/uploads/2020/12/remotty_logo.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Remotty(リモティ) - リモートワークのための仮想オフィス&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://ja.remotty.net/wp-content/uploads/2020/05/cropped-favicon-32x32.png" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;www.remotty.net&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;オフィスにいられない間にもチャットや掲示板に反応できるように、iOSとandroidそれぞれにネイティブアプリのクライアントアプリがあり、それぞれを別の開発者が担当していました。iOS版はその当時新卒2年目だった若者が作ったものを僕が引き継ぐ形でメンテしていました。&lt;/p&gt;
&lt;p&gt;もともと自社向けに開発していたプロダクトではありますが、働き方改革の流れなどの関係もあってここ1年〜2年ぐらいの間に有償で使ってくださるお客さまが出てきました。&lt;/p&gt;
&lt;p&gt;そうなってくると自社では必要のない機能も、お客さんの組織体制によってはないと困るものがでてきます。オフィスを代替するようなツールなので働き方にモロに影響するんですよね。&lt;/p&gt;
&lt;p&gt;そういった経緯から本体であるWeb側に大きめの変更が入るようになります。アプリに影響のないように開発をするものの、全く新しい機能については流石に影響なしというわけにはいかなくなりました。&lt;/p&gt;
&lt;p&gt;とは言え、Remottyのスマホアプリはそれを主な業務として開発しているわけではなかったこともあって、iOS/android両方に大幅な変更をするのはとても時間がかかるだろうということがわかりました。&lt;/p&gt;
&lt;p&gt;そんなとき、React Nativeに興味を持ってアプリを書き始めていたCTOにそそのかされる形で、僕がReact Nativeを習得して一人で両対応版を開発していこうということになりました。&lt;/p&gt;
&lt;p&gt;前置き終わり。&lt;/p&gt;
&lt;h1 id="getting-started"&gt;Getting Started&lt;/h1&gt;
&lt;p&gt;ES5系しか知らないし、WebのReactならほんのちょっとわかるって状態だったので、ほんとにできるかなーという気持ちでした。&lt;/p&gt;
&lt;p&gt;というわけでいくつかチュートリアルを進めつつ、慣れていくことにしました。基本は公式ドキュメントのはずなので、このGetting Startedから進めていきました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://reactnative.dev/docs/getting-started" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://reactnative.dev/img/logo-share.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Introduction · React Native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;This helpful guide lays out the prerequisites for learning React Native, using these docs, and setting up your environment.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://facebook.github.io/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;facebook.github.io&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ここを一通りやる主な標準コンポーネントを使うとどんな画面になるのかイメージがわきます。画面単位では大体どんな風にすればいいのかはわかってくるようになりました。&lt;/p&gt;
&lt;p&gt;ここからアプリとして体をなすまでに乗り越えるべきハードルはまだ幾つかあります。その中で特に画面遷移やデータ管理が特に大きいものなんじゃないかと思います。&lt;/p&gt;
&lt;h1 id="画面遷移"&gt;画面遷移&lt;/h1&gt;
&lt;p&gt;今でこそReact Nativeのドキュメントに&lt;code&gt;Navigation Between Screens&lt;/code&gt;という項目があります、&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://reactnative.dev/docs/navigation" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://reactnative.dev/img/logo-share.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Navigating Between Screens · React Native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Mobile apps are rarely made up of a single screen. Managing the presentation of, and transition between, multiple screens is typically handled by what is known as a navigator.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://facebook.github.io/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;facebook.github.io&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;が、アプリを書き換え始める時期にはこのようなページはなかったと記憶しています。ここに登場する&lt;code&gt;react-navigation&lt;/code&gt;は当時ベータ版の初期でした。&lt;/p&gt;
&lt;p&gt;画面遷移系のライブラリとしては&lt;code&gt;react-native-router-flux&lt;/code&gt;がよく使われていた印象でした。他にもairbnbやwixのような企業のライブラリがありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/aksonov/react-native-router-flux"&gt;https://github.com/aksonov/react-native-router-flux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/airbnb/native-navigation"&gt;https://github.com/airbnb/native-navigation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/wix/react-native-navigation"&gt;https://github.com/wix/react-native-navigation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;それぞれどのような使い方ができるのかを知るためにスパイクを行うことにしました。スパイクはアジャイルの文脈に登場する言葉で、事前にリスクや仕様を把握したりする作業のことです。&lt;/p&gt;
&lt;p&gt;結果どれも使ってみてしっくりこず、ベータ版だった&lt;code&gt;react-navigation&lt;/code&gt;を使ってみました。そしたらこれがなぜか手に馴染む。使いたかったタブとスタックのナビゲーションがシンプルに書けたこと、遷移のコードがシンプルだったこと、などからベータだけどこれでいいんじゃね？となりました。&lt;/p&gt;
&lt;p&gt;結局&lt;code&gt;react-navigation&lt;/code&gt;が公式のようになっていることを考えると良い選択をしたなと思います。ただまだベータ版使ってるんだよなあ。更新に追随するのが少し大変です。&lt;/p&gt;
&lt;h1 id="データ管理"&gt;データ管理&lt;/h1&gt;
&lt;p&gt;次はデータ管理です。WebでReactを使ったちょっとしたサイトを作ったことがあり、パラメータの引き回しやデータ更新の反映が面倒なことはわかっていました。ですのでこのアプリを開発する前からReduxを使ってみようと考えていました。&lt;/p&gt;
&lt;p&gt;Reduxはその当時でもReactのプロダクトでよく使われているような雰囲気がありました。関連するQiita記事なども多くみられたため躓くことはないだろうと採用に至りました。&lt;/p&gt;
&lt;p&gt;こちらも最初は小さめのサンプルアプリを書くなどして手触りを知ってから使い始めました。素のReactでプロパティを引き回していたことを考えると劇的に簡単になったなぁと当時は思ったと記憶しています。&lt;/p&gt;
&lt;p&gt;しかし今思えばReduxは大きすぎるフレームワークだったなと思います。やりたかったのはデータを一元管理して更新があったら再描画することだけです。最近ではその役目にはMobXのほうが適しているだろうという声もあります。&lt;/p&gt;
&lt;p&gt;この辺。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://qiita.com/Apprentice_engineer/items/81ce1e9c3e78555db0f9" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRmxoMy5nb29nbGV1c2VyY29udGVudC5jb20lMkYtWGRVSXFkTWtDV0ElMkZBQUFBQUFBQUFBSSUyRkFBQUFBQUFBQUFBJTJGNDI1MnJzY2J2NU0lMkZwaG90by5qcGclM0ZzeiUzRDUwP2l4bGliPXJiLTQuMC4wJmFyPTElM0ExJmZpdD1jcm9wJm1hc2s9ZWxsaXBzZSZiZz1GRkZGRkYmZm09cG5nMzImcz1hNzMxNGNhM2ZlZmVkZjY2M2ExMmE0ZTgxNWUxMmE0Yg%26blend-x%3D120%26blend-y%3D467%26blend-w%3D82%26blend-h%3D82%26blend-mode%3Dnormal%26s%3D8fc36e6058605ebccf1c73f402f7f868?ixlib=rb-4.0.0&amp;amp;w=1200&amp;amp;fm=jpg&amp;amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9JUUzJTgwJThDRnJvbnQtZW5kJTIwRGV2ZWxvcGVyJTIwSGFuZGJvb2slMjAyMDE4JUUzJTgwJThEMjAxOCVFNSVCOSVCNCVFMyU4MSVBRSVFNCVCQSU4OCVFNiVCOCVBQyVFMyU4MSVBQiVFMyU4MSVBNCVFMyU4MSU4NCVFMyU4MSVBNiVFNyVCRiVCQiVFOCVBOCVCMyZ0eHQtYWxpZ249bGVmdCUyQ3RvcCZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTU2JnR4dC1wYWQ9MCZzPTZkYjIxMThmMzYyMTRlYmVmZGJmNjlmZWExMTdlMWZh&amp;amp;mark-x=120&amp;amp;mark-y=112&amp;amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDBBcHByZW50aWNlX2VuZ2luZWVyJnR4dC1jb2xvcj0lMjMxRTIxMjEmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9MzYmdHh0LXBhZD0wJnM9MjAzZGVjZTdlZjkzNjAyY2QyMWY0MTE5NzQ2Y2I2NzQ&amp;amp;blend-x=242&amp;amp;blend-y=480&amp;amp;blend-w=838&amp;amp;blend-h=46&amp;amp;blend-fit=crop&amp;amp;blend-crop=left%2Cbottom&amp;amp;blend-mode=normal&amp;amp;s=7e418a15d0b02568cf96858765ea91ff" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;「Front-end Developer Handbook 2018」2018年の予測について翻訳 - Qiita&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;そもそも「Front-end Developer Handbook」とは 概要 原文はこちら。 何が書いてあるの？ フロントエンドエンジニアに関わる技術やトレンドを幅広く記載している。各技術について深くは解説していないが、全体が1冊の本にまとまっている。 PDFでダウ...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;qiita.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="その他必要になった技術要素"&gt;その他必要になった技術要素&lt;/h1&gt;
&lt;p&gt;さて、ここからは個別の話なのでダイジェストでお送りし、気が向いたら個別に詳細を書いてみようと思います。&lt;/p&gt;
&lt;h2 id="apiリクエスト"&gt;APIリクエスト&lt;/h2&gt;
&lt;p&gt;Web版Remottyとやり取りをするためのアプリなので当然RemottyのWeb APIを叩きます。API呼び出しをまとめて&lt;code&gt;ApiClient&lt;/code&gt;を作って中で&lt;code&gt;fetch&lt;/code&gt;を呼ぶようにしました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ApiClient&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;getComment&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;args&lt;/span&gt;) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;postNewComment&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;args&lt;/span&gt;) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="oauth"&gt;OAuth&lt;/h2&gt;
&lt;p&gt;Web側のRemottyはOAuthに対応しています。過去のiOS/androidのアプリもそれぞれOAuthで認証してアクセストークンを取得していました。&lt;/p&gt;
&lt;p&gt;OAuthにはこちらのライブラリを利用しました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/fullstackreact/react-native-oauth" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/c41c7b3e189765256f64a826a363ce4175915ef09f29364c3b340d40a70fc60d/fullstackreact/react-native-oauth" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - fullstackreact/react-native-oauth: A react-native wrapper for social authentication login for both Android and iOS&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;A react-native wrapper for social authentication login for both Android and iOS - fullstackreact/react-native-oauth&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;2017年4月頃の時点ではiOSは動く状態だったものの、android側のネイティブ実装が不足している状態で、自前のOAuthプロバイダーでは認証できない状態でした。&lt;/p&gt;
&lt;p&gt;そこでこんなissueを立てて質問したところやりとりをしてくれて、無事対応したバージョンを使えるようになりました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/fullstackreact/react-native-oauth/issues/102" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/9249117eee004a62b89bd4f4dbdbd4dc95cb21cf3ea48b1518dea2bedb3588a9/fullstackreact/react-native-oauth/issues/102" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;[Question] Android: My own providers are not supported yet? · Issue #102 · fullstackreact/react-native-oauth&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;I&amp;#39;ve implemented iOS app for my own oauth provider with rn-oauth. It works as I expected. But on Android, it doesn&amp;#39;t. I got following error on OAuthManager#authorize(). 04-09 22:22:55.143 5149 5189...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="データ永続化"&gt;データ永続化&lt;/h2&gt;
&lt;p&gt;RemottyはWebが主体となるサービスであるため、端末に情報を保存しておく必要はほとんどありません。都度最新の情報をWeb APIで取得するのを基本としています。&lt;/p&gt;
&lt;p&gt;ただ、認証情報だけは別です。毎度ログインが必要なのでは使い物になりませんので、Remottyではアプリ内の領域にアクセストークンのようなものを保存しています。&lt;/p&gt;
&lt;p&gt;具体的にはRedux管理下にあるstoreを保存できる仕組みである、redux-persistを利用しました。redux-persistは環境に合ったストレージを指定することで色々な環境で使えます。React NativeではAsyncStorageが使われます。&lt;/p&gt;
&lt;h2 id="push通知"&gt;Push通知&lt;/h2&gt;
&lt;p&gt;Remottyではアプリを起動していない状態やバックグラウンドのときのプッシュ通知はもちろん、アプリがフォアグラウンドにいるときにコメントなどをリアルタイムに同期する仕組みにおいてもプッシュ通知の仕組みを使います。&lt;/p&gt;
&lt;p&gt;iOS、androidはそれぞれ異なる仕組みなのですが、JS層でうまいことラップしてくれるライブラリがあり、それを導入してアプリ側の処理を上手いこと一本化できました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/zo0r/react-native-push-notification" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/6d186915f39da5bb44171886f769b1b54264582c114fecb61e35fb1259d3582d/zo0r/react-native-push-notification" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - zo0r/react-native-push-notification: React Native Local and Remote Notifications&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;React Native Local and Remote Notifications. Contribute to zo0r/react-native-push-notification development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="リッチテキスト"&gt;リッチテキスト&lt;/h2&gt;
&lt;p&gt;Remottyはマークダウン形式に対応しています。また、本文中のURLはリンクになるなど、プレーンテキストよりはリッチな表現ができます。&lt;/p&gt;
&lt;p&gt;これをアプリで表現するには実はまだ課題があるものの、最低限のラインを満たすためにRemottyではWeb APIでHTMLに変換済みの文字列を返し、アプリ側ではHTMLとして描画するようにしました。&lt;/p&gt;
&lt;p&gt;その際こちらを使うようにしました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/jsdf/react-native-htmlview" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/9277b7af73827c06b6487ebf90ec7b87c8bfc3ff0596bf2acabe2073dcf840e3/jsdf/react-native-htmlview" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - jsdf/react-native-htmlview: A React Native component which renders HTML content as native views&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;A React Native component which renders HTML content as native views - jsdf/react-native-htmlview&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;最近また新しくなっていそうなので、アップデートしてみようかな、、。&lt;/p&gt;
&lt;h2 id="メンション"&gt;メンション&lt;/h2&gt;
&lt;p&gt;Remottyでは&lt;code&gt;@ユーザーid&lt;/code&gt;で宛先を指定すると通知を飛ばす機能があります。Slackにあるようなアレですね。&lt;/p&gt;
&lt;p&gt;アプリからもメンションする際にメンバーのidが補完されないと不便なので、テキスト入力欄にはメンション補完が欲しいなあと。ちょうどよさそうなライブラリがあったので入力に応じてインクリメンタルに絞り込んでいく機能をつけました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/harshq/react-native-mentions" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/6539bab3ab0c600b65af7110b41f58cd45ba031fc883af4f3b487753d71847f8/harshq/react-native-mentions" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - harshq/react-native-mentions: Mentions textbox for React Native. Works on both ios and android.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Mentions textbox for React Native. Works on both ios and android. :whale: - harshq/react-native-mentions&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;レイアウトを整えるために必要なプロパティを受け付けてくれないコンポーネントだったので、プルリクをなげて取り込んでもらいました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/harshq/react-native-mentions/pull/10"&gt;Add a prop for top View style by pi-chan · Pull Request #10 · harshq/react-native-mentions&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="画像添付"&gt;画像添付&lt;/h2&gt;
&lt;p&gt;Remottyのチャットや掲示板には画像を添付できます。アプリからは画像のみを許可しています。&lt;/p&gt;
&lt;p&gt;画像をアップロードするのはなかなか複雑で、色々なライブラリを組み合わせて実装しました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;画像選択&lt;/strong&gt;&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/react-native-image-picker/react-native-image-picker" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/42b634ec25a8d7297b0c6d2c6093bb8e2355226402e426aa9b2eb4f480994e5a/react-native-image-picker/react-native-image-picker" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - react-native-image-picker/react-native-image-picker: :sunrise_over_mountains: A React Native module that allows you to use native UI to select media from the device library or directly from the camera.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;:sunrise_over_mountains: A React Native module that allows you to use native UI to select media from the device library or directly from the camera. - react-native-image-picker/react-native-image-p...&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;リサイズ&lt;/strong&gt;&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/bamlab/react-native-image-resizer" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/74cf4eae6f88c00f700704c1131dcd77261c669659283a2a800bfd672f64b111/bamlab/react-native-image-resizer" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - bamlab/react-native-image-resizer: 🗻 Resize local images with React Native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;🗻 Resize local images with React Native. Contribute to bamlab/react-native-image-resizer development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;ファイルアクセス&lt;/strong&gt;&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/itinance/react-native-fs" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/344dc8f6ec58b5bf1dcd35d6871750f4771e43ad84e8a39d6b9c24235a00a172/itinance/react-native-fs" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - itinance/react-native-fs: Native filesystem access for react-native&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Native filesystem access for react-native. Contribute to itinance/react-native-fs development by creating an account on GitHub.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;アップロード&lt;/strong&gt;&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/wkh237/react-native-fetch-blob" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/b73180f677b2b13ee4a5b2d106269ccef30df30a60f4386eb171cdb76d1ac645/wkh237/react-native-fetch-blob" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - wkh237/react-native-fetch-blob: A project committed to making file access and data transfer easier, efficient for React Native developers.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;A project committed to making file access and data transfer easier, efficient for React Native developers. - wkh237/react-native-fetch-blob&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;流れとしては&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;react-native-image-pickerで画像選択&lt;/li&gt;
&lt;li&gt;リサイズするかしないからの選択シートを表示（リサイズする場合3へ、そうでなければ5へ）&lt;/li&gt;
&lt;li&gt;react-native-image-resizerでリサイズし、リサイズ済画像をアプリ領域に保存&lt;/li&gt;
&lt;li&gt;react-native-fsを使ってファイルからリサイズ済の画像をbase64として読み込む&lt;/li&gt;
&lt;li&gt;react-native-fetch-blobで&lt;code&gt;multipart/form-data&lt;/code&gt;としてAPIにPOST&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;としてます。アップロード範囲を切り取りできるようにもしたいなーと思いつつただでさえ複雑な処理がパンクしそうなので保留しています。&lt;/p&gt;
&lt;h2 id="codepush"&gt;CodePush&lt;/h2&gt;
&lt;p&gt;CodePushはMicrosoftが提供する&lt;code&gt;Visual Studio App Center&lt;/code&gt;の機能の一部で、React Nativeのアプリの中に埋め込まれているJS側のコードを置き換えられる仕組みを提供するものです。&lt;/p&gt;
&lt;p&gt;React Nativeアプリはネイティブコードからなる部分とその上で動くJSのコードがあり、CodePushにより後者のコードを置き換えられます。つまりネイティブコードを変更しない限りアプリストアに新しいバージョンをリリースせずにアプリを更新できるようになります。&lt;/p&gt;
&lt;p&gt;UIの微調整などはCodePushでとても簡単に修正できますし、リリース後に見つかった不具合を審査を待たずして修正することなんかもできます。&lt;/p&gt;
&lt;h1 id="個人的な課題感"&gt;個人的な課題感&lt;/h1&gt;
&lt;p&gt;さて最後に個人的に課題に思っていることがあるので、書いてみます。&lt;/p&gt;
&lt;h2 id="android版の苦労と課題"&gt;android版の苦労と課題&lt;/h2&gt;
&lt;p&gt;開発するうえでの苦労という観点と、ユーザー体験という意味での課題という観点があります。&lt;/p&gt;
&lt;p&gt;まず開発するうえでの苦労です。
僕個人がiPhoneユーザーということもあり、iOSファーストで開発していました。するといざandroidで動かそうにもなかなか動かなくて困ることがありました。起動しないとかビルド通らないとかね。
またReact Native自信が提供する機能や、各種ライブラリの対応状況などをみた限りでもiOSの対応状況のほうが充実していたように思えます。&lt;/p&gt;
&lt;p&gt;そのためandroid版の開発はハマりが発生することが多かったような気がします。android側に対応するためにプルリクを出す、forkして一時的にそちらを使う、そもそも動かないからライブラリを捨てる、などということをよくしました。&lt;/p&gt;
&lt;p&gt;もう1つのユーザー体験という意味では、これはまあほぼ僕の責任なんですが、androidを常用していないiPhoneユーザーが一人で作ったアプリなので、androidアプリっぽくありません。&lt;/p&gt;
&lt;p&gt;戻るボタンの挙動など、androidユーザーに指摘されるまで気づきもしませんでしたし、キーボードが出たときのアプリの表示なんかもiOSと違う癖もあったりして、androidらしくは全然できませんでした。&lt;/p&gt;
&lt;p&gt;かといってUIを分けきってしまうと両対応する旨味がなくなってしまうので悩ましいです。フロント側を特に凝りたい、こだわりたいようなアプリでは、ReactNativeに対応するにしても画面は別にしていくんでしょうね。と思っています。&lt;/p&gt;
&lt;h2 id="jsワカラン"&gt;JSワカラン&lt;/h2&gt;
&lt;p&gt;ES2015等新しい仕様への不慣れがありました。書きながらだんだん慣れていきましたが、ベストプラクティスから程遠いみたいなところもまだまだありそうです。&lt;/p&gt;
&lt;h2 id="reduxが"&gt;Reduxが、、&lt;/h2&gt;
&lt;p&gt;Remottyのアプリで使うにはReduxはオーバースペックでした。前述の通りMobXが適切だったかなと。これは時期的なものもあるとは思うので失敗とは思っていませんが、次に作るアプリはMobXにします。&lt;/p&gt;
&lt;h1 id="終わり"&gt;終わり&lt;/h1&gt;
&lt;p&gt;できあがったRemottyのアプリはこちらです。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://itunes.apple.com/jp/app/remotty/id979526900?mt=8" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;itunes.apple.com →&lt;/span&gt;&lt;span&gt;https://itunes.apple.com/jp/app/remotty/id979526900?mt=8&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://play.google.com/store/apps/details?id=net.remotty.android&amp;amp;hl=ja" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;play.google.com →&lt;/span&gt;&lt;span&gt;https://play.google.com/store/apps/details?id=net.remotty.android&amp;amp;hl=ja&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;弊社社長のリモートワークに関する書籍も出ていますよ。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4534053428/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/61d5QIQWc&amp;#43;L._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;リモートチームでうまくいく&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>forestry.ioでHugoブログにCMS機能を一瞬で追加した</title><link>https://blog.piyo.tech/posts/2018-04-10-forestry-cms/</link><pubDate>Tue, 10 Apr 2018 06:29:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-10-forestry-cms/</guid><description>&lt;p&gt;Hugoのブログを更新するときには基本的にはローカルPCを使っています。僕の場合はNetlifyを絡めて、&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;記事更新&lt;/li&gt;
&lt;li&gt;Gitへpush&lt;/li&gt;
&lt;li&gt;Netlifyでビルド&lt;/li&gt;
&lt;li&gt;Netlifyで最新バージョンが配信&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;という流れで配信まで行っています。&lt;/p&gt;
&lt;p&gt;記事の新規追加はこれで十分なのですが、タイポの修正のようなちょっとした修正までPCを使うのは非常に面倒だなと思っていました。&lt;/p&gt;
&lt;p&gt;NetlifyにはCMS機能を提供するような仕組みがあることは知っていました。しかし、2018/04/09現在Gitリポジトリとして使っているBitbucketには対応していません。&lt;/p&gt;
&lt;p&gt;このあたりでやりとりがあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/netlify/netlify-cms/issues/234"&gt;Netlify CMS on Bitbucket · Issue #234 · netlify/netlify-cms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/netlify/netlify-cms/pull/525"&gt;(WIP) Bitbucket integration by zanedev · Pull Request #525 · netlify/netlify-cms&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当初はこれを待ってからでいいなと思ってたんですが、検索機能を作るときに参考にしたブログがforestry.ioというサービスの記事で、よく見たらCMS機能があるじゃないですか。簡単に使えるならいいなと思い、早速使ってみました。&lt;/p&gt;
&lt;h1 id="ログインからサイト追加まで"&gt;ログインからサイト追加まで&lt;/h1&gt;
&lt;p&gt;こちらからサインアップしましょう。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://tina.io/forestry" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://tina.io/og/tina-og.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Forestry.io to TinaCMS Migration Guide&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;The Forestry.io team is now focused on building TinaCMS. Migrate your Forestry site to Tina with our step-by-step guide and enjoy enhanced visual editing features.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://forestry.io/favicon/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;forestry.io&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Bitbucketログインにも対応しています（最近はGitLab対応しているところが増えてきね）。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Q4Ve6i_98P3z7GiFs0BIz4fZk-TBE-yzw_9ivvEHc46KESpCrvpC8zzrtVEi0UAqLfzZJ5LZNEfcWmkHLANeeB-jMV73xXACgdBAr9EVTm18Ym3d7ZNb11V2B4CCwTqbMqBZ4TZy6w6OPnwHMT-lN_uBXiwoUYMeESBXAZrsGBWnPPhHpwVbwCqReFVuVtpSvAijALSI4C0pU0iEHVMzzL4mMwYr64AwR1xUAKUFcjc4c3jOBFEY-QHqWKsISIoFjJNBY6oFeDfH5SHBB_aVNSfRYDQJ4YBRMABSsn0CREn_18UYsRtIvF26icOO48jSpOdnoA7BEgtvXnBfhkx4O52EJ-AXi9uVlttZoaRRaP2w-lgsmyEWahxRZklK9PSi09jBlxaArxVUkAXEpY55n4dcsF1QE8U7rxpX8w6AXhjIEYAD-A84oK9lgOc3f2cMLTIctjXjDQreo080t3UQm8IxDQ7BGoVs5Nam7toXwHVR1nRCfy38HTRu6ozpilBfm9bf_wV4hZ2CXfRmxeDKZ5ZEb0Dho3-pvMR1HzmXnr2FE53YLkANzd9FINj3Dc-qP0f5eZ_xAITc1kIihXT1rl7fTWKkxKFfniSG1urUVezT0xWs_AnFYIhy0KOxOZUvem6hyLMqln7ZiTW8QOll13Aonth94G0OVQ=w451-h580-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Q4Ve6i_98P3z7GiFs0BIz4fZk-TBE-yzw_9ivvEHc46KESpCrvpC8zzrtVEi0UAqLfzZJ5LZNEfcWmkHLANeeB-jMV73xXACgdBAr9EVTm18Ym3d7ZNb11V2B4CCwTqbMqBZ4TZy6w6OPnwHMT-lN_uBXiwoUYMeESBXAZrsGBWnPPhHpwVbwCqReFVuVtpSvAijALSI4C0pU0iEHVMzzL4mMwYr64AwR1xUAKUFcjc4c3jOBFEY-QHqWKsISIoFjJNBY6oFeDfH5SHBB_aVNSfRYDQJ4YBRMABSsn0CREn_18UYsRtIvF26icOO48jSpOdnoA7BEgtvXnBfhkx4O52EJ-AXi9uVlttZoaRRaP2w-lgsmyEWahxRZklK9PSi09jBlxaArxVUkAXEpY55n4dcsF1QE8U7rxpX8w6AXhjIEYAD-A84oK9lgOc3f2cMLTIctjXjDQreo080t3UQm8IxDQ7BGoVs5Nam7toXwHVR1nRCfy38HTRu6ozpilBfm9bf_wV4hZ2CXfRmxeDKZ5ZEb0Dho3-pvMR1HzmXnr2FE53YLkANzd9FINj3Dc-qP0f5eZ_xAITc1kIihXT1rl7fTWKkxKFfniSG1urUVezT0xWs_AnFYIhy0KOxOZUvem6hyLMqln7ZiTW8QOll13Aonth94G0OVQ=w451-h580-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;ログインが終わると空のダッシュボードに来ます。Add Siteに進みます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/c8_tZ9XSXcWrC6oZDFVfki9jQ4Z1XzQrFR4nmCxu8iPPE10xRGHtQ0qqF-o72irBQNGIgVNgxXTiYfmAGqxipumHJKBoruDq_vDYo9IRqJ8cKqfMlzbsSXgojNPC5eqr8SJy_du9NXH6pBLLXgbbrKm3RtUP34rW6rA6G2SqqowUkG1DjzpHhZJTWF-N7U9YHfJhMKpQlnZgyyGtziAWeb6WE6gEMr3vI-CUcF2iVVpv_Xd7Wd8Z4mfG4ZdqyniruJDoryhOgOrm3hgFdBoQByUwap_zVXugGQUkTCOVQToPpx4CW6MwdZ9USMPVFUpGM3cLzxzyjorjeiN22EWcZWs2OvyZ66VieLLgcFYFyYk8N5DAjoVcj9Y_HaRVSSa1yRVsJhMld9W98qSYKhgkE2xPP0Jj9vU-VOPJQMLaVC0lxUSHLdhD88DBWPrZgfRdV2LB1PuajHw49ovuow83vnWU6NPFAgz-AYoSMen9gu9mynpN3A6XMUcRcemnve1LrvqZbhzhYES6WZVnJ5lC06QxMo8z-DnoIj4EwffXg2dkVBH7HQZ_8mMA6-2yZsoe6VY60a6DOw5O9zG46-boQJ-0TGmUfUCHyxohKwxH6a6xwtcwBRWMoROxIjxrN0a2cHgzQroHnUo4cBi_Bxtfi1i7Ll6z3pl9mw=w663-h424-no"&gt;&lt;img src="https://lh3.googleusercontent.com/c8_tZ9XSXcWrC6oZDFVfki9jQ4Z1XzQrFR4nmCxu8iPPE10xRGHtQ0qqF-o72irBQNGIgVNgxXTiYfmAGqxipumHJKBoruDq_vDYo9IRqJ8cKqfMlzbsSXgojNPC5eqr8SJy_du9NXH6pBLLXgbbrKm3RtUP34rW6rA6G2SqqowUkG1DjzpHhZJTWF-N7U9YHfJhMKpQlnZgyyGtziAWeb6WE6gEMr3vI-CUcF2iVVpv_Xd7Wd8Z4mfG4ZdqyniruJDoryhOgOrm3hgFdBoQByUwap_zVXugGQUkTCOVQToPpx4CW6MwdZ9USMPVFUpGM3cLzxzyjorjeiN22EWcZWs2OvyZ66VieLLgcFYFyYk8N5DAjoVcj9Y_HaRVSSa1yRVsJhMld9W98qSYKhgkE2xPP0Jj9vU-VOPJQMLaVC0lxUSHLdhD88DBWPrZgfRdV2LB1PuajHw49ovuow83vnWU6NPFAgz-AYoSMen9gu9mynpN3A6XMUcRcemnve1LrvqZbhzhYES6WZVnJ5lC06QxMo8z-DnoIj4EwffXg2dkVBH7HQZ_8mMA6-2yZsoe6VY60a6DOw5O9zG46-boQJ-0TGmUfUCHyxohKwxH6a6xwtcwBRWMoROxIjxrN0a2cHgzQroHnUo4cBi_Bxtfi1i7Ll6z3pl9mw=w663-h424-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;続いてサイトの種類を選びます。Hugoかjekyllが選択できるようですね。今回はHugoを選んでいます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/qp7xxsEfenzzUPtM4dNN6cOKY9wDusfyf2mu0-3VIND9O1O_jWZCcuUO5KMpCm7JwT5sQOtnJi9CBmysiCWKOt-K_URdN7iusmNyMyqmsy4WRYELN3epaR1l_Xc38l-M4o17VrO_G33CVaK03SwMb8HY2EKATJBe1UzUJP8Kyn4XtZsQjIjuj4b_6a8bRSJREqS1E7Kse5Wu8I3b_F5FhmW6yA52lX_mb_319Dl3nruiEgoTnY0WvU4BWaH9VfjSXYky_flYKdq3zwFrkaRC8to0ybL0hlDYfYny-SCDPuk8MYV5SaS10FrSIcVWJaXlX_VuxhUO0_MPIz89hinxrxAXEjKVhE5UG30AAK6t4N2jb5-Bg0J2siDxQryxoh426b5x6z6FC1fuHTU4TXhXDo3Dw8ugz3zDhlNj3ZcQzTDh0evJ4mory8F2dPlCJbN4ASm1Vct5lu2I_eL1pdzbzoknUShDA1QZCOElyQ0L69_IKlSRy186xyerN5c4vLUrR6jdSnDNK_xA9cTjakRQFs5PPvH36fwL2SA1nJF_xJYa3EbSN7fmrmaLdjROL3hO6HFePIyGA2Afu9hyK5nPeRXp_HaDjJQ43Chb-R91wZJ3sB01goCZeAHlLgN5GRP0T6XCLRq8Fzn7xDg-65fUZ-F1jQVe9csX5w=w478-h447-no"&gt;&lt;img src="https://lh3.googleusercontent.com/qp7xxsEfenzzUPtM4dNN6cOKY9wDusfyf2mu0-3VIND9O1O_jWZCcuUO5KMpCm7JwT5sQOtnJi9CBmysiCWKOt-K_URdN7iusmNyMyqmsy4WRYELN3epaR1l_Xc38l-M4o17VrO_G33CVaK03SwMb8HY2EKATJBe1UzUJP8Kyn4XtZsQjIjuj4b_6a8bRSJREqS1E7Kse5Wu8I3b_F5FhmW6yA52lX_mb_319Dl3nruiEgoTnY0WvU4BWaH9VfjSXYky_flYKdq3zwFrkaRC8to0ybL0hlDYfYny-SCDPuk8MYV5SaS10FrSIcVWJaXlX_VuxhUO0_MPIz89hinxrxAXEjKVhE5UG30AAK6t4N2jb5-Bg0J2siDxQryxoh426b5x6z6FC1fuHTU4TXhXDo3Dw8ugz3zDhlNj3ZcQzTDh0evJ4mory8F2dPlCJbN4ASm1Vct5lu2I_eL1pdzbzoknUShDA1QZCOElyQ0L69_IKlSRy186xyerN5c4vLUrR6jdSnDNK_xA9cTjakRQFs5PPvH36fwL2SA1nJF_xJYa3EbSN7fmrmaLdjROL3hO6HFePIyGA2Afu9hyK5nPeRXp_HaDjJQ43Chb-R91wZJ3sB01goCZeAHlLgN5GRP0T6XCLRq8Fzn7xDg-65fUZ-F1jQVe9csX5w=w478-h447-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;続いてソースを指定します。置き場所はBitbucketを選び、リポジトリとブランチを指定します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/hEliib99IE2o6UZ6asJ8AzLPqtpTNB_iEUksBUotpuyBiFpuk03TOjZd6iTNukjilS7bmiciq9iZvovizdOZgnK6SO5cD7pkZajVeJbsPENCogDdYM9-F51wpfngApDhNqC9-2URThEyELiC1zA4m-rgZA5IdklqBBduKeDVwBHQgmteoR4BwcVj1oX2nn0QNn2AYa9HbR_-yo5Z7mJu88FtkOXWH0sSEZZKl8d_GgoWa4jEXPh8mNQ0nsDi-GuqKcKvvNhAyMzE94Pt6HweIAiF8oAq3yf8M_I98CzLO8tAPFCx7XZtHC9XwEmsHYokPM6PTRoPnMpbFd0vGXOCmrq7FCzQeLh-pMGC4gkJTvLDRMcO8SGXeyxSrnGn8QM94A_bc1q-2h0CyohkGEt16vTDjw5zVmmna24ExkRfd7K5HUPDO_WLKTXjSaOWd3dzfTGMr0gnaq6AwlSxVazcCYZ2MeEmXTUDYWE_14eaLItS-SL4ynsdKExHj46Dm8G53hhNKH2l_U0i27tFAjC3BZJmTPi2tS9twjFnxih1_J0sEcqYj7n3YyKVTO-uiyjCIsOVyVZbgDG1hllJaXeBCAvtTFiX8UcOxWCwv5HX68J2f5WnyMxEBkauC6lss0nFposYeTzZXbiNbJkKI2nG62hzYUVGvr0Olw=w485-h376-no"&gt;&lt;img src="https://lh3.googleusercontent.com/hEliib99IE2o6UZ6asJ8AzLPqtpTNB_iEUksBUotpuyBiFpuk03TOjZd6iTNukjilS7bmiciq9iZvovizdOZgnK6SO5cD7pkZajVeJbsPENCogDdYM9-F51wpfngApDhNqC9-2URThEyELiC1zA4m-rgZA5IdklqBBduKeDVwBHQgmteoR4BwcVj1oX2nn0QNn2AYa9HbR_-yo5Z7mJu88FtkOXWH0sSEZZKl8d_GgoWa4jEXPh8mNQ0nsDi-GuqKcKvvNhAyMzE94Pt6HweIAiF8oAq3yf8M_I98CzLO8tAPFCx7XZtHC9XwEmsHYokPM6PTRoPnMpbFd0vGXOCmrq7FCzQeLh-pMGC4gkJTvLDRMcO8SGXeyxSrnGn8QM94A_bc1q-2h0CyohkGEt16vTDjw5zVmmna24ExkRfd7K5HUPDO_WLKTXjSaOWd3dzfTGMr0gnaq6AwlSxVazcCYZ2MeEmXTUDYWE_14eaLItS-SL4ynsdKExHj46Dm8G53hhNKH2l_U0i27tFAjC3BZJmTPi2tS9twjFnxih1_J0sEcqYj7n3YyKVTO-uiyjCIsOVyVZbgDG1hllJaXeBCAvtTFiX8UcOxWCwv5HX68J2f5WnyMxEBkauC6lss0nFposYeTzZXbiNbJkKI2nG62hzYUVGvr0Olw=w485-h376-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/CsfPJeE8vI22doGeB-RebGSWF7liIM29qJRzeR0kbffse1mZ0A3kGEx_7O980x1aiUqYkJ03l4Eq3cTQWzxg2T5-xteynT72Qb082oxZqUU80uCQTIaoFMlC3mEUgVNoKBS-QFjfb6XdiDl3bXnYUsZt7nkzvC5R7hBqtb5Sp32iYo8B6IaPaXI1577bq9NYZ25VelZjsNS4_XluWQ4bsgNpYTiNijkKtZAVgCfCXJdlmyNjPvd3V7Cy1GnChpkvmN41MQ8rzWwfA-K6NYC4zmVsUHuVuHjxEMw0I0v9lGlIeNQukXKEN1nNhj1qHixRya_UP01HzbAf6eeBtx2sqAgxK4qqIOwbhYEsEugSDt57o4eRycOb6jgnLReeLrrCJvdEcmNtXE9F5WUvWWGqvgr_6gp96GbyKAibIK_8UMbEhFVTSScEf5tJ8_fWCjzUeeSPF8e6SchBBE83BFB8E06bFY2WdIyG33E3a8HGgTqrrrFbTLeYuwKt2DkwpQ6YVVN9yRCJ7vkLGyyXJ-Pgc6NhS6KBla_5MR9Cd-VFr4QFiB_4hVE0U6plkfXhW6I6AhihEzqAJL04W8NBuEyBJh4iTL4OvkPw9-aT67NB2NoZNX_3hut9L0e0_M2K7OAIMdMXi6KDvRH9RD-LdokZy4qbYYPahx3EzQ=w485-h476-no"&gt;&lt;img src="https://lh3.googleusercontent.com/CsfPJeE8vI22doGeB-RebGSWF7liIM29qJRzeR0kbffse1mZ0A3kGEx_7O980x1aiUqYkJ03l4Eq3cTQWzxg2T5-xteynT72Qb082oxZqUU80uCQTIaoFMlC3mEUgVNoKBS-QFjfb6XdiDl3bXnYUsZt7nkzvC5R7hBqtb5Sp32iYo8B6IaPaXI1577bq9NYZ25VelZjsNS4_XluWQ4bsgNpYTiNijkKtZAVgCfCXJdlmyNjPvd3V7Cy1GnChpkvmN41MQ8rzWwfA-K6NYC4zmVsUHuVuHjxEMw0I0v9lGlIeNQukXKEN1nNhj1qHixRya_UP01HzbAf6eeBtx2sqAgxK4qqIOwbhYEsEugSDt57o4eRycOb6jgnLReeLrrCJvdEcmNtXE9F5WUvWWGqvgr_6gp96GbyKAibIK_8UMbEhFVTSScEf5tJ8_fWCjzUeeSPF8e6SchBBE83BFB8E06bFY2WdIyG33E3a8HGgTqrrrFbTLeYuwKt2DkwpQ6YVVN9yRCJ7vkLGyyXJ-Pgc6NhS6KBla_5MR9Cd-VFr4QFiB_4hVE0U6plkfXhW6I6AhihEzqAJL04W8NBuEyBJh4iTL4OvkPw9-aT67NB2NoZNX_3hut9L0e0_M2K7OAIMdMXi6KDvRH9RD-LdokZy4qbYYPahx3EzQ=w485-h476-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;これでしばらく待つとインポートが完了します。&lt;/p&gt;
&lt;h1 id="記事の登録や編集"&gt;記事の登録や編集&lt;/h1&gt;
&lt;p&gt;ダッシュボードにサイトが追加されました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/hY27hSDQbPRSPfMLoVf9MGTwStL1b4bo-ddKMp1LbwVVQzYhs0N9g0MytXxP36mnlQjTLF-6z96y4kLZeGx4YdsFhZX-hWBRD75aoOEZhh0Y842yTVvZEOQR9udty--yC3i42V3CLrSPu7vpAeDU0WKB8GBrFzjKblIJf78j2IsmrhwnYa97vt1nRChPdChTedg1yVa-FT0pOZ2mylPaHHhQbT2HmLhy8XD1HhbF8rnt4VPGz4HbXz1kd6kHbt33POGAnM4e8bfXslwmHlRpsWBH1or8OZR_l-bNJFIWC_5VyA8dNTdNRfXfvNatPzDEKC5c0LmWvmH8yL7lLT_zgZU5Wr0_NCYoh9GnYHuUGNcwcmjF1WU8r8BP4NP_csiBO9TDC7fZMcnMa8vdJzlpjQbQWFZF5IWv8o8HoECoTXlpUmQCCE2rPxp3PSh2TJr-aO6zwUaFlyFEto1WJCKu1N-F3JQJie7FirTIWRzbx7Odu9p3X9R1AWv0TSiXv687JG86xjeh1pmQ84cXiGSCyHwzBoZK41656XSVlZPsIVp8bpckrl24kvwlO7KaB2YNmY6piVsI-kftZtqLC6rM5-84fsq6USfsYiz6UvauLePdRlSuf8T2Rb7GU-tH16zD0VwjJxp-gXLSdcpNdqGqhuKL2WJ3zkm9WQ=w669-h227-no"&gt;&lt;img src="https://lh3.googleusercontent.com/hY27hSDQbPRSPfMLoVf9MGTwStL1b4bo-ddKMp1LbwVVQzYhs0N9g0MytXxP36mnlQjTLF-6z96y4kLZeGx4YdsFhZX-hWBRD75aoOEZhh0Y842yTVvZEOQR9udty--yC3i42V3CLrSPu7vpAeDU0WKB8GBrFzjKblIJf78j2IsmrhwnYa97vt1nRChPdChTedg1yVa-FT0pOZ2mylPaHHhQbT2HmLhy8XD1HhbF8rnt4VPGz4HbXz1kd6kHbt33POGAnM4e8bfXslwmHlRpsWBH1or8OZR_l-bNJFIWC_5VyA8dNTdNRfXfvNatPzDEKC5c0LmWvmH8yL7lLT_zgZU5Wr0_NCYoh9GnYHuUGNcwcmjF1WU8r8BP4NP_csiBO9TDC7fZMcnMa8vdJzlpjQbQWFZF5IWv8o8HoECoTXlpUmQCCE2rPxp3PSh2TJr-aO6zwUaFlyFEto1WJCKu1N-F3JQJie7FirTIWRzbx7Odu9p3X9R1AWv0TSiXv687JG86xjeh1pmQ84cXiGSCyHwzBoZK41656XSVlZPsIVp8bpckrl24kvwlO7KaB2YNmY6piVsI-kftZtqLC6rM5-84fsq6USfsYiz6UvauLePdRlSuf8T2Rb7GU-tH16zD0VwjJxp-gXLSdcpNdqGqhuKL2WJ3zkm9WQ=w669-h227-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;続いてサイトダッシュボードに入っていくと、こんな風になってます。記事の一覧がでていたり、&lt;code&gt;config.toml&lt;/code&gt;に書いているようなサイト設定を確認・変更できるようになっていたりします。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/aCxpXQJleT-MVnqAI9dh9JBl0nyF1ZUPKf42BTN1G18RuZ9-NXrxaIPo1UG_qAhOgYknXvVlVYJgPOd0uqW0BrWibUVLDntJXP5iVWfPZRUfJaJav2qRZqJyW_YlU1XurY0D1nJGmCPEZkTZzYJR6d3peRba18dgtH7w8U6HmWjNcsIZ3yvlYx1jM1N2r0EqOQInz_MP_zuMTw5NnoerNK1OIpp3cpzl2mc2wJ6i2WYjPI0kC3DCxpkjo9AjP1SM8sFkUSmWfUdCI2JVriYiGdr_oWc6iayjOYAFq1SzK30X04i1OhOtlpE1MAn_vMVk3hHi9_sCVvJvx2GwvNrlqNuQZkuL0mSJ66lkpo1F3CXl0oZi9u0QTFl6Qb4gYJF7D554396hYCfQoMBIAhWx7szeeo33k4eQA_DE7z3i07U5OAd_hOdog_CYtTHdPKM7xF3HQBRQPpUjMtiuW9cpmX2X9kPWpCMvV1DRC7SzV0JupqmJxZr2RjegFp1w4acOtW_8GcwVI2sdpHnuqrPg3Eclp0pcA1GxzC5gddy5UQ71mEydlWKR_jGNBMU9mZucOCYlQLNDrims_xfLXNA5GCkFy-pHo4d3_DjqgZG_5YoSni3hxaNt8r-4RUUzubQ4V-o-jCcJmPmtcrMHp4LIQHBkQaM-ecr2CQ=w665-h343-no"&gt;&lt;img src="https://lh3.googleusercontent.com/aCxpXQJleT-MVnqAI9dh9JBl0nyF1ZUPKf42BTN1G18RuZ9-NXrxaIPo1UG_qAhOgYknXvVlVYJgPOd0uqW0BrWibUVLDntJXP5iVWfPZRUfJaJav2qRZqJyW_YlU1XurY0D1nJGmCPEZkTZzYJR6d3peRba18dgtH7w8U6HmWjNcsIZ3yvlYx1jM1N2r0EqOQInz_MP_zuMTw5NnoerNK1OIpp3cpzl2mc2wJ6i2WYjPI0kC3DCxpkjo9AjP1SM8sFkUSmWfUdCI2JVriYiGdr_oWc6iayjOYAFq1SzK30X04i1OhOtlpE1MAn_vMVk3hHi9_sCVvJvx2GwvNrlqNuQZkuL0mSJ66lkpo1F3CXl0oZi9u0QTFl6Qb4gYJF7D554396hYCfQoMBIAhWx7szeeo33k4eQA_DE7z3i07U5OAd_hOdog_CYtTHdPKM7xF3HQBRQPpUjMtiuW9cpmX2X9kPWpCMvV1DRC7SzV0JupqmJxZr2RjegFp1w4acOtW_8GcwVI2sdpHnuqrPg3Eclp0pcA1GxzC5gddy5UQ71mEydlWKR_jGNBMU9mZucOCYlQLNDrims_xfLXNA5GCkFy-pHo4d3_DjqgZG_5YoSni3hxaNt8r-4RUUzubQ4V-o-jCcJmPmtcrMHp4LIQHBkQaM-ecr2CQ=w665-h343-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;では、&lt;code&gt;ADD NEW&lt;/code&gt;から記事を追加してみましょう。ADD NEWするとダイアログが出て、タイトルとPATHを決めろとなります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Wja_i-58MD3Xys0Pou59JVxut6rcmOPLL4bx1gwENfnJ2dqlp5ppCV___OJHExX9DPWFYlZZLuulRaIEljF-tmfj4Pe_7DZgHNZZYI4SVjZ-Xgop9a-9nplfQCNlLXyNrYz3r5-RNoaq77_xe0xOs-8aN22_zdwKPh_kirOtfIOpIndE9STFvl4szUfiFdfOk5LZA8V79hIwMsAb2PTx_pyYX7yCheZXsnb1VI8uQhnfesc6fqfMObAfFogFdgNZrsn_0n9vcZbuinj3pdrfmHwy8YwhlsSL7vkVbvigHBQPQ67KBFFi-gcqn4CjTNj8j7m0qO0Sc3TlzRYJgzT5ikX9Btl9SQkg1V9LYu9y5meJPnQvasmieGR-9Gl7S1eureOlNrpiJiQ28ttGJ4qGukatGpM_7VOx04r51F1aZOsnmTOWvDgjBQI7qQj-24B02fQxOFFZuOtUgIAcriwNu9XgD-t4lwgSaEIYCnRR8XYj44Q27agIhNb0emojVdbam1hbZW89RHjI_i0_4EJevz3Em7o3bKYWQHJSL4ajBtGrk6Bg1ylSNfQJIBd6JNgqy_s7i9cvsR0GLN-TDQQF1Iuu2atTvZPuRT0wpArAvPubppFUsdvOsUAYlgkDmBWzXsq0toIN4s8lElPn7_9DR3-Qe8Jkk_YK_g=w563-h469-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Wja_i-58MD3Xys0Pou59JVxut6rcmOPLL4bx1gwENfnJ2dqlp5ppCV___OJHExX9DPWFYlZZLuulRaIEljF-tmfj4Pe_7DZgHNZZYI4SVjZ-Xgop9a-9nplfQCNlLXyNrYz3r5-RNoaq77_xe0xOs-8aN22_zdwKPh_kirOtfIOpIndE9STFvl4szUfiFdfOk5LZA8V79hIwMsAb2PTx_pyYX7yCheZXsnb1VI8uQhnfesc6fqfMObAfFogFdgNZrsn_0n9vcZbuinj3pdrfmHwy8YwhlsSL7vkVbvigHBQPQ67KBFFi-gcqn4CjTNj8j7m0qO0Sc3TlzRYJgzT5ikX9Btl9SQkg1V9LYu9y5meJPnQvasmieGR-9Gl7S1eureOlNrpiJiQ28ttGJ4qGukatGpM_7VOx04r51F1aZOsnmTOWvDgjBQI7qQj-24B02fQxOFFZuOtUgIAcriwNu9XgD-t4lwgSaEIYCnRR8XYj44Q27agIhNb0emojVdbam1hbZW89RHjI_i0_4EJevz3Em7o3bKYWQHJSL4ajBtGrk6Bg1ylSNfQJIBd6JNgqy_s7i9cvsR0GLN-TDQQF1Iuu2atTvZPuRT0wpArAvPubppFUsdvOsUAYlgkDmBWzXsq0toIN4s8lElPn7_9DR3-Qe8Jkk_YK_g=w563-h469-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;また、ここでテンプレートを指定できます。記事のdescriptionやタグ、アイキャッチなどのメタデータを設定するのですが、これのフィールドを予めテンプレートとして追加しておくことができます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/Y4qC0z73W81YiVPU3rLxZX4gYcBtqj4uC6fPCY9aV5p3RQiKiWtQOaRda8wlvHU2iA2FFbv8t-5FuKGPr75kKsazaI1i1Q4t37G8vWIV7x6fjQ9hbyki5iPJ1YgD8oi4mh1foQJYELkNBGgJ7rBfJ-Txy6GkPmRHphRDWivtzyIwuFiVjysp860BPlHDlzEjQFy4OHxa3uUViUdZsW54yQhsdZkhxI6mr2GS_k7B4Zne_d9dPPfRCpM13euhUe6KQKz8WNv79l8TX7oRjooXXbel1uWJvLEnqEyh3o_bDMI0WnaLUDKZghUqUzcw4c5DV3XAwWowvcNiiRhY9iHpwtpDq1TUQBv4nMjPrwGAvG48rtN51LImvzrSSer4Bvtu4BERGCeH9dyWLvCp5v92DJ0vKKO2VLBN2PCvueindVQhSrFaKPoqBN7L6z81iCkkXL9hAvB3_BBmVldSlaRMu5lM5gMujc1Z-WaXhaeBf0pG71iLoYlsmu26fzgLMFh7n4m-UoBUzJhCbD3mQ8Bui9VJin2YeTTusFgPWTTPZmZHNB_aSbpArDLdVWD01PA5_XluU5y23Nd90n_eMaAj1iojaIt-d5Pe3qc0ttO2CEpH7df4T7l9m-aeDMd-5W8j71UUTFKwHaiH0D8AsDpXatrKWxhdZx-z5Q=w1549-h868-no"&gt;&lt;img src="https://lh3.googleusercontent.com/Y4qC0z73W81YiVPU3rLxZX4gYcBtqj4uC6fPCY9aV5p3RQiKiWtQOaRda8wlvHU2iA2FFbv8t-5FuKGPr75kKsazaI1i1Q4t37G8vWIV7x6fjQ9hbyki5iPJ1YgD8oi4mh1foQJYELkNBGgJ7rBfJ-Txy6GkPmRHphRDWivtzyIwuFiVjysp860BPlHDlzEjQFy4OHxa3uUViUdZsW54yQhsdZkhxI6mr2GS_k7B4Zne_d9dPPfRCpM13euhUe6KQKz8WNv79l8TX7oRjooXXbel1uWJvLEnqEyh3o_bDMI0WnaLUDKZghUqUzcw4c5DV3XAwWowvcNiiRhY9iHpwtpDq1TUQBv4nMjPrwGAvG48rtN51LImvzrSSer4Bvtu4BERGCeH9dyWLvCp5v92DJ0vKKO2VLBN2PCvueindVQhSrFaKPoqBN7L6z81iCkkXL9hAvB3_BBmVldSlaRMu5lM5gMujc1Z-WaXhaeBf0pG71iLoYlsmu26fzgLMFh7n4m-UoBUzJhCbD3mQ8Bui9VJin2YeTTusFgPWTTPZmZHNB_aSbpArDLdVWD01PA5_XluU5y23Nd90n_eMaAj1iojaIt-d5Pe3qc0ttO2CEpH7df4T7l9m-aeDMd-5W8j71UUTFKwHaiH0D8AsDpXatrKWxhdZx-z5Q=w1549-h868-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;元々入っていたタイトル、日付、下書きの3項目に加え、タグ、description、thumbnailの3項目を追加しておきました。&lt;/p&gt;
&lt;p&gt;最後に本文を書いて公開状態にしてPUBLISHすれば公開となります。少し時間がかかりますが、プレビューなんかもできてまずまずいい感じです。&lt;/p&gt;
&lt;p&gt;とは言えやはり本文を新たに書く場合にはローカルのエディタとローカルのサーバーのほうが確認の手間も含めて楽です。CMSは微修正を中心に活用します。&lt;/p&gt;</description></item><item><title>Algoliaを使ってブログに全文検索をつける（検索ページ編）</title><link>https://blog.piyo.tech/posts/2018-04-08-hugo-search-page/</link><pubDate>Sun, 08 Apr 2018 08:57:21 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-08-hugo-search-page/</guid><description>&lt;p&gt;前回の記事ではHugoのブログに全文検索機能をつけるために、検索インデックスとしてのJSONの出力方法や、Netlifyでのビルド時に自動的にインデックスが更新されるようなWebTaskの利用について書きました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-04-07-hugo-search-index/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/r0owED5cBmCrD0wSbGkZkndJpmBW1SzYJPnfeb4w6XtcRfmmAr7IEYeo2nsjt3cHb81HlpByTaF4-1_UIXqJrWCfj_m-EaPaoYEszOlNg5qSIgQPbKBiyLQVgylgohhqzlss39qtNC7C6PzmxN0t6i0tAlfN858y1NXR-p9zoGsNDD_ESSfy5xrMOqAyWcav-aqnKjggx4xOnbxK0zA7qw8zVdqztuAfysiwKZI1r39UZ13ina1SjA_TEeC3zdQ132HcK4UuGSyLFmB0W662oCOyZaCz4yaTVN4tcXQm8aGsNn1nyyp7S0MQiJk2Oy-zFHcwh4WAojtUMX9HJa9T_C34B6LNPrgoavxsVumFk76ZmCVguxzLstJ1GUg61u61j1f3g_Yd3f83cTz64mc5Tg3dn4EFrgrBRQ0ZudYx99jZDTC2vYPvlZBTxWzjkWNo0AFEwO2IcZtRf31y07Jqrp5LtXwAayPNEO138CoeS7Bhc88Llw3SM76R2KYu-gbVnbljhq1xYI_bgTT_zNNl561znfF96T9wX8bwfVYEziO8i5iVIK5vUl4l1d_JCi_9Ydy-bK8ooczLhq9hWaw0czTbT8X36HjU8NmfZLDrvZC7JaBhaki5JeMjvQEw0BlchpNVno0IHoZyEe2vv59ZJpu-_agRSarUKA=w1000-h667-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Algoliaを使ってブログに全文検索をつける（検索index作成編） - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Hugoに移行して以来かなり満足度が高いブログ活動ですが、記事機能がないのが惜しいなと思っています。検索の用途としては自分が昔書いたことを発掘するのがまず第一です。案外助けられることが多いんです。 もちろん、Google検索で site: オプションを使うなどしても実現できるのはわかっています。ただ、やはり自分でやってみたいという気持ちがあったので今回チャレンジしました。すでにファーストバージョンは完成していて、画面右上から検索用のページへ移動できます。リアルタイムな絞り込み検索を試せます。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;今回はインデックスを利用してページ上に検索ボックスや検索結果を表示するページを用意する手順について書いていきます。&lt;/p&gt;
&lt;h1 id="全体の流れ"&gt;全体の流れ&lt;/h1&gt;
&lt;p&gt;Algoliaの公式ドキュメントに沿ってinstantSearch.jsを使う形で進めていきます。概ね簡単なのですが、オプションが多くて迷う点がありました。僕はこうしたよ的な観点で書いていきます。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://community.algolia.com/instantsearch.js/v2/getting-started.html" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;community.algolia.com →&lt;/span&gt;&lt;span&gt;https://community.algolia.com/instantsearch.js/v2/getting-started.html&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;流れとしては、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;アセットの読み込み&lt;/li&gt;
&lt;li&gt;検索ページを作成&lt;/li&gt;
&lt;li&gt;JSで検索の設定を記述&lt;/li&gt;
&lt;li&gt;検索結果の調整&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という感じです。&lt;/p&gt;
&lt;h1 id="アセットの読み込み"&gt;アセットの読み込み&lt;/h1&gt;
&lt;p&gt;npmで導入する方法とCDNを指定する方法の2種類提供されています。今回は静的サイトのためCDNを利用しました。&lt;/p&gt;
&lt;p&gt;現在利用している、HugoのRobustというテンプレートではページ全体を&lt;code&gt;robust/layouts/_default/baseof.html&lt;/code&gt;に記述しています。これをオーバーライドするために、プロジェクトルートの&lt;code&gt;layouts/_default&lt;/code&gt;以下に&lt;code&gt;baseof.html&lt;/code&gt;を作成し元ファイルの中身をコピーした上で、CDNの記述を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;link&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rel&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/css&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://cdn.jsdelivr.net/npm/instantsearch.js@2.6.3/dist/instantsearch.min.css&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;link&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rel&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/css&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://cdn.jsdelivr.net/npm/instantsearch.js@2.6.3/dist/instantsearch-theme-algolia.min.css&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://cdn.jsdelivr.net/npm/instantsearch.js@2.6.3&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="検索ページを作成"&gt;検索ページを作成&lt;/h1&gt;
&lt;p&gt;検索をどこで実施できるようにするかというのはちゃんと考えるべきことなんですが、今回は簡単に実施するために検索用のページを用意することにしました。&lt;/p&gt;
&lt;p&gt;通常の投稿はposts以下に配置しています。検索ページ通常のブログ投稿とは異なりますので&lt;code&gt;pages&lt;/code&gt;以下に&lt;code&gt;search&lt;/code&gt;として作りました。&lt;/p&gt;
&lt;p&gt;ページのMarkdownに直接HTMLやJavascriptを書く形で検索ページを用意しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;title: xxx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;date: xxx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;tags: xxx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;search-box&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- 検索ボックス用の空DOM --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hits&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- 検索結果用のDOM、各結果をliで置くためulにしている --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;pagination&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- ページネーションがここに --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ここに検索用のJSを記述
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際に完成した画面との対応がこんな感じです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/LxnXggyTylUvdHQgLanzAdJZVun5rWS_4UMVaz6wZpP0u0JisfT7npSNi73crK4vNminYnUBCxgJ2W-Xxq53ypyuEDZU0c-sFl2a6N1sdVPe1qht9C1RaqPoGTC58vxEivAxsQso77B4zIyghVKg9U8rRhYhglggjy0LybRL4whbaZ5VXkID8ogAC_pu9NZmODZPXBqM3Q4eXBZollo8GFUrEyetzlj97vcLfMOy01YwiXrACXxK502otfWBgs_x7j49FrNxkKIPad3ecDjfNItpdp8Cr6nNDvV4z34ebSRYZxNzuktPr3a1bEyGLRNXHw8Jg7gNo90oJFT5kQvfq2tFYie77zA1BCNfbI1-fTVmFilmAtmGhLBhxLoYVYXfe9qwLZQL8w27ZDduYe5tFfegwyIo1VijFqe39BUwIVYKzyEBiQEuJ9eoKAPIFE99cpn5WMBE4nrvk7IIPYntMfP4qR6_rJG4Ee2WyZGaBevVxgp7TSL4B6UJxfIffCxyZaG7oJWOYgQ6y1fN-7-z0OPyGbEA3WcRpsJG8ebdA2JatA2yiX_nmGruoG481XefEsx10bfhd00U_P8L9dGo74SZSuiZBlZ15f8sPobANOwnTDvpgOiKkEqXk-H6I77PaFJCvD6sJhBMMmplu7X3IBSyV6r0EKXKsg=w801-h461-no"&gt;&lt;img src="https://lh3.googleusercontent.com/LxnXggyTylUvdHQgLanzAdJZVun5rWS_4UMVaz6wZpP0u0JisfT7npSNi73crK4vNminYnUBCxgJ2W-Xxq53ypyuEDZU0c-sFl2a6N1sdVPe1qht9C1RaqPoGTC58vxEivAxsQso77B4zIyghVKg9U8rRhYhglggjy0LybRL4whbaZ5VXkID8ogAC_pu9NZmODZPXBqM3Q4eXBZollo8GFUrEyetzlj97vcLfMOy01YwiXrACXxK502otfWBgs_x7j49FrNxkKIPad3ecDjfNItpdp8Cr6nNDvV4z34ebSRYZxNzuktPr3a1bEyGLRNXHw8Jg7gNo90oJFT5kQvfq2tFYie77zA1BCNfbI1-fTVmFilmAtmGhLBhxLoYVYXfe9qwLZQL8w27ZDduYe5tFfegwyIo1VijFqe39BUwIVYKzyEBiQEuJ9eoKAPIFE99cpn5WMBE4nrvk7IIPYntMfP4qR6_rJG4Ee2WyZGaBevVxgp7TSL4B6UJxfIffCxyZaG7oJWOYgQ6y1fN-7-z0OPyGbEA3WcRpsJG8ebdA2JatA2yiX_nmGruoG481XefEsx10bfhd00U_P8L9dGo74SZSuiZBlZ15f8sPobANOwnTDvpgOiKkEqXk-H6I77PaFJCvD6sJhBMMmplu7X3IBSyV6r0EKXKsg=w801-h461-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="jsで検索の設定を記述"&gt;JSで検索の設定を記述&lt;/h1&gt;
&lt;p&gt;先ほどのページ内、&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;タグの中にinstantSearch.jsの設定を書いていきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;検索ボックス&lt;/li&gt;
&lt;li&gt;検索結果&lt;/li&gt;
&lt;li&gt;ページネーション&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;の3要素のみのシンプルな形にしました。&lt;/p&gt;
&lt;p&gt;前述の公式ドキュメントに色々なパターンが載っていたり、リファレンスを見るとオプションがかなり豊富だったりとたくさんの設定がありそうです。&lt;/p&gt;
&lt;p&gt;ここで指定するapiKeyはAlgoliaダッシュボードのsearch-only API Keyを使います。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/NMOeUkYlEmfO_YqhN6BTJx8DYt7LQy6vYh16dyjrriOL0FzZ8lVynmktv2xZK8D9KtJzv9zCVXjcJqZA_XR4llEm-rgtC-szTIzOCrdulJM1gVtQbxEhQBE75EEppCYrOs0xmbEzMr9OQc9rwGC84YmCpbAeapQTY7oaeJZ4mTw09lvUrOIzqv2M2c1uJoZkZdyj46yrOEpNFFDGknXHbiUt9_os0GqYC_f3wDrvZfU-WAsum55cMVKjYMHNzeLrfWBN-qZLauO9dwmkDM_2vEEqoerQUS2ppvByPGWD87d5-T7-xlnxTNXf_7gFIEw37jQuaNg3-vKWyV4Ipw2pGXTQtY0746J0p0tW-ljDjvT1jVvjn-cKZf4p0FNLKHL5R6pvY-TB7TEIF1mqjqP0PSvWpgCRNXucA3vNpJAKm1fYTXph4CQrlprD8m--lhcektFbZNvlI_4GJbzquAZc7TTO2qKhkK16gcWzDnOsomvSVi8knaQ1-htKvvA5PKt16I0sRRiWBBxFCtE1v5oIjTRxlXvXeEL0mzwbBfX8LWu8eofPqqjkrH8xo2q7XI6qxoP2tENubOgTIefpWNgHmvAJB1JhX8_jT1W0vjOtyYXcr6iZWc0XkHGNsRId7HlOOo2zyRGNMC_-1K4lPpYlEJBJfA0_S2rB2w=w1762-h244-no"&gt;&lt;img src="https://lh3.googleusercontent.com/NMOeUkYlEmfO_YqhN6BTJx8DYt7LQy6vYh16dyjrriOL0FzZ8lVynmktv2xZK8D9KtJzv9zCVXjcJqZA_XR4llEm-rgtC-szTIzOCrdulJM1gVtQbxEhQBE75EEppCYrOs0xmbEzMr9OQc9rwGC84YmCpbAeapQTY7oaeJZ4mTw09lvUrOIzqv2M2c1uJoZkZdyj46yrOEpNFFDGknXHbiUt9_os0GqYC_f3wDrvZfU-WAsum55cMVKjYMHNzeLrfWBN-qZLauO9dwmkDM_2vEEqoerQUS2ppvByPGWD87d5-T7-xlnxTNXf_7gFIEw37jQuaNg3-vKWyV4Ipw2pGXTQtY0746J0p0tW-ljDjvT1jVvjn-cKZf4p0FNLKHL5R6pvY-TB7TEIF1mqjqP0PSvWpgCRNXucA3vNpJAKm1fYTXph4CQrlprD8m--lhcektFbZNvlI_4GJbzquAZc7TTO2qKhkK16gcWzDnOsomvSVi8knaQ1-htKvvA5PKt16I0sRRiWBBxFCtE1v5oIjTRxlXvXeEL0mzwbBfX8LWu8eofPqqjkrH8xo2q7XI6qxoP2tENubOgTIefpWNgHmvAJB1JhX8_jT1W0vjOtyYXcr6iZWc0XkHGNsRId7HlOOo2zyRGNMC_-1K4lPpYlEJBJfA0_S2rB2w=w1762-h244-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// instantSearchを初期化
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;search&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;instantsearch&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;appId&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;3BFGDTL653&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;apiKey&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;3f41e36d23c8180ba83e5157b43eb3cd&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;indexName&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;BlogPosts&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;urlSync&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 検索ボックスをDOMに設定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;search&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;addWidget&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;instantsearch&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;widgets&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;searchBox&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;container&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#search-box&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;placeholder&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;記事を検索&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;poweredBy&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 検索結果をDOMに設定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 結果には&amp;lt;li&amp;gt;を使うように
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;search&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;addWidget&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;instantsearch&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;widgets&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;hits&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;container&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#hits&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;templates&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;empty&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;見つかりませんでした。&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;item&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;{{ dateString }}&amp;lt;/code&amp;gt; &amp;lt;a href=&amp;#34;{{permalink}}&amp;#34;&amp;gt;{{ title }}&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 検索結果をページネーションするための設定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;search&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;addWidget&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;instantsearch&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;widgets&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;pagination&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;container&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#pagination&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;maxPages&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;scrollTo&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;search&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここまででサイト上で検索を実施できるようになりました。すごく簡単でした。&lt;/p&gt;
&lt;h1 id="検索結果の調整"&gt;検索結果の調整&lt;/h1&gt;
&lt;p&gt;最後は検索結果の調整です。&lt;/p&gt;
&lt;p&gt;先ほどまでの状態だと、結果の順序がバラバラだったり関係なさそうなものまでヒットしたり、なんか欲しい結果と違うなあという感じになってしまっていました。&lt;/p&gt;
&lt;p&gt;このあたりのロジックをAlgoliaのダッシュボードから変更できるので、ある程度納得できる状態になるまで調整を試みました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/00wn3JDeY38OZNNmF0Fxf4cxWS93-fd9Y7c94xDUjo0720ixQzTXbb1hGv8kZVbiq70rhFvU3ENjjWrn2CbnQD6vs054Olpox_vdWCxH5HRXb7yTgBskXLUN0lnhrliLz9MM3_GMRp87f79L-vf1_TC4H3RAGCHl0mxWuFceGoh8_iG781hkStretahu9RDvT15GMoQ-MGLcAfqzK2hUkZK6GH6TqDhJZiJdl7pQI8nf6fF8nWWiIbvPGYZMcai7yhX1hialrOV4clQa5MbaVedwiTv1axqi1MIt7sq6jlJ_uwjw-KO6zYnxcLzG0APUFw87BC5XxbVWL2IbqcDHthG1KcQSUpi0M0sAE37QMffEBALau0yTWox6NBWERBEHKJF5BKevsQPcTlTRb1HHXTIWplfjgZLedA0kEMqqyJHWQaIO25dymqmVm40K_ui4f412Vhk3qO0vxl-Dzt70PKPwlHDGAD03cclgYS1UxbaVJFYPM3CQlcBAV0-RTXlSStT8plknUhgvsIpfoFKyC6RNGVtFCjfM2Dgtpa9T31rZHPF-ZU5oyxne2xbZ0Y4q_8GkI15Y5hnoDwr57NItdkCTRkpY6gR1FhGVt_6Nja_tDGEEvUa5XWew0L1TlWYZN6_GdYkKqe7TiVTPuKvDxPtBqDGgcvs2Zg=w619-h367-no"&gt;&lt;img src="https://lh3.googleusercontent.com/00wn3JDeY38OZNNmF0Fxf4cxWS93-fd9Y7c94xDUjo0720ixQzTXbb1hGv8kZVbiq70rhFvU3ENjjWrn2CbnQD6vs054Olpox_vdWCxH5HRXb7yTgBskXLUN0lnhrliLz9MM3_GMRp87f79L-vf1_TC4H3RAGCHl0mxWuFceGoh8_iG781hkStretahu9RDvT15GMoQ-MGLcAfqzK2hUkZK6GH6TqDhJZiJdl7pQI8nf6fF8nWWiIbvPGYZMcai7yhX1hialrOV4clQa5MbaVedwiTv1axqi1MIt7sq6jlJ_uwjw-KO6zYnxcLzG0APUFw87BC5XxbVWL2IbqcDHthG1KcQSUpi0M0sAE37QMffEBALau0yTWox6NBWERBEHKJF5BKevsQPcTlTRb1HHXTIWplfjgZLedA0kEMqqyJHWQaIO25dymqmVm40K_ui4f412Vhk3qO0vxl-Dzt70PKPwlHDGAD03cclgYS1UxbaVJFYPM3CQlcBAV0-RTXlSStT8plknUhgvsIpfoFKyC6RNGVtFCjfM2Dgtpa9T31rZHPF-ZU5oyxne2xbZ0Y4q_8GkI15Y5hnoDwr57NItdkCTRkpY6gR1FhGVt_6Nja_tDGEEvUa5XWew0L1TlWYZN6_GdYkKqe7TiVTPuKvDxPtBqDGgcvs2Zg=w619-h367-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;対象のアプリのダッシュボードへ入り、左メニューのIndices、RANKINGタブ、と進みます。&lt;/p&gt;
&lt;h2 id="基本設定"&gt;基本設定&lt;/h2&gt;
&lt;p&gt;基本設定として、どの項目を検索対象とするのか、優先度はどの順番なのかという設定をします。インデックスをアップロード・登録した時点では特に何も入っていないので、この項目は100%設定すべきです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/SDFs5GfYG_AuFiL5g4VSxiF9GhL5aCRnYFuXOh8k2k0-ANZqLmGI93GJV0Q-MFIXA3XOOeRn5b4xoFSIdyXPs_KDJzEJ8LLNd7N1VDjtdr-IcoPuKLJaAHVTWIkP0ozz3pguK98eFpNqUoW-Y9GDt9MKEE8PHLSvzzOxFa_LBnQmZSbwtFx0bq4W_dgCPDfsEsYdIWSio9va790tKZsVHI7QdOGZ373jffta26YBCeI7QLOexSSiOo4g9aXHNhHbDQm84mEIqZOt_cOYUeIdXBlzSX7-UBPscFwGyhIZ2DxD5v8jWK6WMjMGY4c66FHW9DjVXq8TxPwkV21UpgLEBaXGJD_saZKNN_ua5iw2DrbmlwQzgIhoDaP8yezR_1g_iQgLicGoi5enpAH9Nn-sxjxpthy0Rfafd5CspWv_3haKMkbY0Ld8rx7ORo9KskopwyTGudfneRjRyuoHmxcjyMS7jGvwdoEYIkilpdVr5v5hnqa3gEmA2Nuqpr3Ltk8b_QCLgVdiPr7l7f61Xc1NvHMg7IfcIMEJIvUcmuSCblNijuhl6eg07_3BT3prz2uJxOoT-5OkT2V-gsXObaP0IKV6xIQldIbPTSIX-4psVEkxhhuEcpj6vkndo-7cFU2qnd3a8OdqA1vCQL_6-ReZzDJ4I8eALxy8_g=w472-h302-no"&gt;&lt;img src="https://lh3.googleusercontent.com/SDFs5GfYG_AuFiL5g4VSxiF9GhL5aCRnYFuXOh8k2k0-ANZqLmGI93GJV0Q-MFIXA3XOOeRn5b4xoFSIdyXPs_KDJzEJ8LLNd7N1VDjtdr-IcoPuKLJaAHVTWIkP0ozz3pguK98eFpNqUoW-Y9GDt9MKEE8PHLSvzzOxFa_LBnQmZSbwtFx0bq4W_dgCPDfsEsYdIWSio9va790tKZsVHI7QdOGZ373jffta26YBCeI7QLOexSSiOo4g9aXHNhHbDQm84mEIqZOt_cOYUeIdXBlzSX7-UBPscFwGyhIZ2DxD5v8jWK6WMjMGY4c66FHW9DjVXq8TxPwkV21UpgLEBaXGJD_saZKNN_ua5iw2DrbmlwQzgIhoDaP8yezR_1g_iQgLicGoi5enpAH9Nn-sxjxpthy0Rfafd5CspWv_3haKMkbY0Ld8rx7ORo9KskopwyTGudfneRjRyuoHmxcjyMS7jGvwdoEYIkilpdVr5v5hnqa3gEmA2Nuqpr3Ltk8b_QCLgVdiPr7l7f61Xc1NvHMg7IfcIMEJIvUcmuSCblNijuhl6eg07_3BT3prz2uJxOoT-5OkT2V-gsXObaP0IKV6xIQldIbPTSIX-4psVEkxhhuEcpj6vkndo-7cFU2qnd3a8OdqA1vCQL_6-ReZzDJ4I8eALxy8_g=w472-h302-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;本ブログの場合は、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;title&lt;/li&gt;
&lt;li&gt;tags&lt;/li&gt;
&lt;li&gt;content&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;を対象とし、この順に優先度が高い、としました。&lt;/p&gt;
&lt;h2 id="ランキング"&gt;ランキング&lt;/h2&gt;
&lt;p&gt;続いて検索順位を設定します。特定のフィールドでの並び替えもここで設定します。僕の場合はひとまず新しい順に並べたいと思い、投稿日が新しいものが順位が高くなるようにしました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/d3u7Bwrd1qYM6H12Rx7a0WPeeXanUfXB4XrKThpAS1lMg4CKigeZQsbBi8EMfodukbebDbF4YDh9LdHCoFmOuooM1acQqMOsVgfo_zFXq2NjA4J6Zjw1YWJO5VNCIS68NyCrtF0bU5fLqszHvcYCPFdMgYDo2zSrQ8xlu2FqFOAhuFI_SxLE2YHTJjLOdKb8MJoXZ_2-utnHO4PXnGaS256aiVUSHcjt_JlGZn9x1Q8SirUUraUKe4Tv7A-0FOuvNbhgpvVUndd9631_xOWcAXAF1AGOGPiqeA_R4aOmzkX5furKPgrr_YGCAVyijQLj7Psvn0Ekth2LuGG524Fez7ZF-d4wlS0Z2VXN4mVhdnB3zs4nlBuLn7QQXRDzxltqoj_yczK0pQjUzCV7cr0Cw6akf2aKgnUqzuXbl-tV2BvGoQSUAko53G2B3grhXWFEIcgYJLvnvQFDdKIAr7WmSu4Pb2gZ4lggLO9SKRaTzmFavB_b8vzxHu-Lr-khZz_DvugIn63JDHtUkgEIPgu84TXKzRVVfaLM8Osg1wnlLE2-9mACi51_yGTriICwd76RnJC1E5vIZsEVEbyYUb5kBmWJ4vxc5j5JnwLf3_9GJKHVWKob37Yob93-5j4RkPbniQRNw-OT8tXT2Ot6D5tCrYkKGaRCnQii0w=w844-h422-no"&gt;&lt;img src="https://lh3.googleusercontent.com/d3u7Bwrd1qYM6H12Rx7a0WPeeXanUfXB4XrKThpAS1lMg4CKigeZQsbBi8EMfodukbebDbF4YDh9LdHCoFmOuooM1acQqMOsVgfo_zFXq2NjA4J6Zjw1YWJO5VNCIS68NyCrtF0bU5fLqszHvcYCPFdMgYDo2zSrQ8xlu2FqFOAhuFI_SxLE2YHTJjLOdKb8MJoXZ_2-utnHO4PXnGaS256aiVUSHcjt_JlGZn9x1Q8SirUUraUKe4Tv7A-0FOuvNbhgpvVUndd9631_xOWcAXAF1AGOGPiqeA_R4aOmzkX5furKPgrr_YGCAVyijQLj7Psvn0Ekth2LuGG524Fez7ZF-d4wlS0Z2VXN4mVhdnB3zs4nlBuLn7QQXRDzxltqoj_yczK0pQjUzCV7cr0Cw6akf2aKgnUqzuXbl-tV2BvGoQSUAko53G2B3grhXWFEIcgYJLvnvQFDdKIAr7WmSu4Pb2gZ4lggLO9SKRaTzmFavB_b8vzxHu-Lr-khZz_DvugIn63JDHtUkgEIPgu84TXKzRVVfaLM8Osg1wnlLE2-9mACi51_yGTriICwd76RnJC1E5vIZsEVEbyYUb5kBmWJ4vxc5j5JnwLf3_9GJKHVWKob37Yob93-5j4RkPbniQRNw-OT8tXT2Ot6D5tCrYkKGaRCnQii0w=w844-h422-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;並び替えの場合、「ADD A SORT-BY ATTRIBUTE」から項目を追加します。投稿日で並び替えたいので、&lt;code&gt;date&lt;/code&gt;を&lt;code&gt;desc&lt;/code&gt;で並び替えさせるようにしました。&lt;/p&gt;
&lt;h2 id="詳細設定"&gt;詳細設定&lt;/h2&gt;
&lt;p&gt;最後にタイポの許容値などを少し厳し目に設定しました。検索結果がいまいち、というのはここの微調整で少し良くなったと感じます。&lt;/p&gt;
&lt;p&gt;僕が設定したのはTypo Torelanceの項目で、それ以外は既定のままにしました（項目が多くてよくわからん）。&lt;/p&gt;
&lt;p&gt;要は、タイポをどれだけ許容するかという話で、基本は&lt;code&gt;false&lt;/code&gt;にして無効としました。最初は、1タイポを許す文字数や2タイポを許す文字数を多めに設定してなどとやってましたが、まあタイポない前提でいいだろうということで&lt;code&gt;false&lt;/code&gt;としたわけです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/d74cQEWSWUGydxDobDbW25rd7-v7kSA5FA6pgMeDbRmYpw1f__woRYi0subAQn1KULi9dHONGJcdlZVvu-AAUNmSJdfHHm_sxoLnuuX0tHDcFmiXuwKbMLBUst-sZ-EeIYNOOWUCEKyMmirqGb2NRO5wqp3rcr6GXU9QK5GBLD2FQ3Foqz8-SR2Ej54BNYg4pqTeciWfWDtG8E6bD3gAOW6ph967E0tlXG4xN4ETe4oipFm6iaxKuJsno6vJFiC-1vNn247_p5YlxOHEw4Oh2DElIcVpSA4mIeZvXGYFir06VJCSdb4THJ73xq-8D_l20FPH9Ntz0G7smaNm-lOvwbmbuq-DIvm3K65iId1hfHxU6icXCzit1RBtRtupr1p6MSe3qfFmZgh6iwdgRFX1_8b_cQrhevC1_YE4HLzA07N3H3sUR9tw2I8QVBBMxiK7reOYbCAxNdz_tCOnVU7PnqZJnlazlfiqo_-sW7LP7IePcAH6-Vx6uYE-SxN53edNl-MLpQLYKUn_xZ5QN-_JjCALp95PikG-ZtDq23kSpujBmRk1pl4ItpPy454Oi3AbnAUS6Iv5SXzvDr0HO4VrP3KLW6xRgioLU-hRWXb0iSuOavAKslEUN4C-oY6MHrlkITzpYV5TPqHMDzdZWBrM2YXsCbXV8yycBg=w724-h486-no"&gt;&lt;img src="https://lh3.googleusercontent.com/d74cQEWSWUGydxDobDbW25rd7-v7kSA5FA6pgMeDbRmYpw1f__woRYi0subAQn1KULi9dHONGJcdlZVvu-AAUNmSJdfHHm_sxoLnuuX0tHDcFmiXuwKbMLBUst-sZ-EeIYNOOWUCEKyMmirqGb2NRO5wqp3rcr6GXU9QK5GBLD2FQ3Foqz8-SR2Ej54BNYg4pqTeciWfWDtG8E6bD3gAOW6ph967E0tlXG4xN4ETe4oipFm6iaxKuJsno6vJFiC-1vNn247_p5YlxOHEw4Oh2DElIcVpSA4mIeZvXGYFir06VJCSdb4THJ73xq-8D_l20FPH9Ntz0G7smaNm-lOvwbmbuq-DIvm3K65iId1hfHxU6icXCzit1RBtRtupr1p6MSe3qfFmZgh6iwdgRFX1_8b_cQrhevC1_YE4HLzA07N3H3sUR9tw2I8QVBBMxiK7reOYbCAxNdz_tCOnVU7PnqZJnlazlfiqo_-sW7LP7IePcAH6-Vx6uYE-SxN53edNl-MLpQLYKUn_xZ5QN-_JjCALp95PikG-ZtDq23kSpujBmRk1pl4ItpPy454Oi3AbnAUS6Iv5SXzvDr0HO4VrP3KLW6xRgioLU-hRWXb0iSuOavAKslEUN4C-oY6MHrlkITzpYV5TPqHMDzdZWBrM2YXsCbXV8yycBg=w724-h486-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;p&gt;というわけで完成！&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/pages/search/"&gt;記事検索 - ぴよログ&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Algoliaを使ってブログに全文検索をつける（検索index作成編）</title><link>https://blog.piyo.tech/posts/2018-04-07-hugo-search-index/</link><pubDate>Sat, 07 Apr 2018 08:28:22 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-07-hugo-search-index/</guid><description>&lt;p&gt;Hugoに移行して以来かなり満足度が高いブログ活動ですが、記事機能がないのが惜しいなと思っています。検索の用途としては自分が昔書いたことを発掘するのがまず第一です。案外助けられることが多いんです。&lt;/p&gt;
&lt;p&gt;もちろん、Google検索で&lt;code&gt;site:&lt;/code&gt;オプションを使うなどしても実現できるのはわかっています。ただ、やはり自分でやってみたいという気持ちがあったので今回チャレンジしました。すでにファーストバージョンは完成していて、画面右上から検索用のページへ移動できます。リアルタイムな絞り込み検索を試せます。&lt;/p&gt;
&lt;p&gt;Hugoは静的サイトなので、検索のような動的な処理はHugo単体ではできません。&lt;/p&gt;
&lt;p&gt;調べているとJSを使う方法や外部のサービスを使う方法など幾つかみつかりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/tools/search/"&gt;Search for your Hugo Website | Hugo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rs.luminousspice.com/hugo-site-search/"&gt;Hugo に全文検索を取り付けた | the right stuff&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ドキュメントにも挙がっていたAlgoliaというサービスが気になったのでさらに調べてみると、forestry.ioの記事で手順が紹介されていました。これを追体験してみることにしました。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://tina.io/forestry" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://tina.io/og/tina-og.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Forestry.io to TinaCMS Migration Guide&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;The Forestry.io team is now focused on building TinaCMS. Migrate your Forestry site to Tina with our step-by-step guide and enjoy enhanced visual editing features.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://forestry.io/favicon/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;forestry.io&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="検索インデックス用のjson"&gt;検索インデックス用のJSON&lt;/h1&gt;
&lt;p&gt;HugoのCustom Output Formatsの仕組みを用いて、サイトのビルド時にAlgoliaに登録するためのJSONを生成します。RSSを出力するときと同じような方法で比較的簡単に作ることができました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gohugo.io/templates/output-formats/"&gt;Custom Output Formats | Hugo&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="configtoml"&gt;config.toml&lt;/h2&gt;
&lt;p&gt;AlgoliaはJSON形式で検索インデックスを登録できます。なんとなく触った感じ指定のフォーマットがないので、記事タイトル、本文、タグ当たりを含めたらいいと思います。&lt;/p&gt;
&lt;p&gt;forestry.ioの設定をベースに、&lt;code&gt;config.toml&lt;/code&gt;に次のような設定を追加しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;outputFormats&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Algolia&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;baseName&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;algolia&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;isPlainText&lt;/span&gt; = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;mediaType&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;notAlternative&lt;/span&gt; = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;params&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;algolia&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;vars&lt;/span&gt; = [&lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;date&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;publishdate&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;permalink&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;thumbnail&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;params&lt;/span&gt; = [&lt;span style="color:#e6db74"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;元記事と異なるのは、&lt;code&gt;params&lt;/code&gt;から&lt;code&gt;category&lt;/code&gt;と&lt;code&gt;expiryDate&lt;/code&gt;を削除し&lt;code&gt;description&lt;/code&gt;を追加したことと、&lt;code&gt;vars&lt;/code&gt;の&lt;code&gt;summary&lt;/code&gt;を&lt;code&gt;content&lt;/code&gt;に変えたことです。&lt;/p&gt;
&lt;p&gt;最後にoutputsに&lt;code&gt;algoria&lt;/code&gt;を追加して完成です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;outputs&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;home&lt;/span&gt; = [ &lt;span style="color:#e6db74"&gt;&amp;#34;HTML&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;RSS&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;algolia&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="json用のテンプレート"&gt;JSON用のテンプレート&lt;/h2&gt;
&lt;p&gt;ファイルを生成するときに使うテンプレートが必要です。&lt;code&gt;layouts/_default/list.algolia.json&lt;/code&gt; としてファイルを作り、中身はこのようにしました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;{{/* Generates a valid Algolia search index */}}
{{- $hits := slice -}}
{{- $section := $.Site.GetPage &amp;#34;section&amp;#34; .Section }}
{{- $validVars := $.Param &amp;#34;algolia.vars&amp;#34; | default slice -}}
{{- $validParams := $.Param &amp;#34;algolia.params&amp;#34; | default slice -}}
{{- range $i, $hit := where .Data.Pages &amp;#34;Section&amp;#34; &amp;#34;posts&amp;#34; -}}
{{- $dot := . -}}
{{- if or (and ($hit.IsDescendant $section) (and (not $hit.Draft) (not $hit.Params.private))) $section.IsHome -}}
{{/* Set the hit&amp;#39;s objectID */}}
{{- .Scratch.SetInMap $hit.File.Path &amp;#34;objectID&amp;#34; $hit.UniqueID -}}
{{/* Store built-in page variables in iterable object */}}
{{- .Scratch.SetInMap &amp;#34;temp&amp;#34; &amp;#34;date&amp;#34; $hit.Date.UTC.Unix -}}
{{- .Scratch.SetInMap &amp;#34;temp&amp;#34; &amp;#34;publishdate&amp;#34; $hit.PublishDate -}}
{{- .Scratch.SetInMap &amp;#34;temp&amp;#34; &amp;#34;dateString&amp;#34; (substr $hit.PublishDate 0 10) -}}
{{- .Scratch.SetInMap &amp;#34;temp&amp;#34; &amp;#34;content&amp;#34; ($hit.Plain | truncate 2000) -}}
{{- .Scratch.SetInMap &amp;#34;temp&amp;#34; &amp;#34;title&amp;#34; $hit.Title -}}
{{- .Scratch.SetInMap &amp;#34;temp&amp;#34; &amp;#34;permalink&amp;#34; $hit.Permalink -}}
{{- .Scratch.SetInMap &amp;#34;temp&amp;#34; &amp;#34;description&amp;#34; $hit.Description -}}
{{- .Scratch.SetInMap &amp;#34;temp&amp;#34; &amp;#34;thumbnail&amp;#34; $hit.Params.thumbnail -}}
{{/* Include valid page vars */}}
{{- range $key, $param := (.Scratch.Get &amp;#34;temp&amp;#34;) -}}
{{- if in $validVars $key -}}
{{- $dot.Scratch.SetInMap $hit.File.Path $key $param -}}
{{- end -}}
{{- end -}}
{{/* Include valid page params */}}
{{- range $key, $param := $hit.Params -}}
{{- if in $validParams $key -}}
{{- $dot.Scratch.SetInMap $hit.File.Path $key $param -}}
{{- end -}}
{{- end -}}
{{- $.Scratch.SetInMap &amp;#34;hits&amp;#34; $hit.File.Path (.Scratch.Get $hit.File.Path) -}}
{{- end -}}
{{- end -}}
{{- jsonify ($.Scratch.GetSortedMapValues &amp;#34;hits&amp;#34;) -}}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ずらっと書いてもしょうがないのですが、いくつか元記事とは異なる箇所があります。&lt;/p&gt;
&lt;p&gt;本文を全部含めてしまうとAlgoliaの1データあたりのデータ上限を超えてしまうので、contentは&lt;code&gt;.Plain&lt;/code&gt;を2000文字で&lt;code&gt;truncate&lt;/code&gt;するようにしました。また、サムネイルもを含めるようにしました。&lt;/p&gt;
&lt;p&gt;また、tagのページなどが含まれてしまうので、&lt;code&gt;where&lt;/code&gt;をつかって&lt;code&gt;&amp;quot;Section&amp;quot;&lt;/code&gt;が&lt;code&gt;&amp;quot;posts&amp;quot;&lt;/code&gt;のものに絞り込んでループを回しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/variables/page/"&gt;.Plain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/functions/truncate/"&gt;truncate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/functions/where/"&gt;where&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これでビルドするとjsonが作られます。ローカルでは&lt;code&gt;http://localhost:1313/algolia.json&lt;/code&gt;にアクセスすると確認ができます。&lt;/p&gt;
&lt;h1 id="algoliaの準備"&gt;Algoliaの準備&lt;/h1&gt;
&lt;p&gt;続いてAlgoliaに登録しましょう。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/cms/render/live/en/sites/www/home.html" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://www.algolia.com/files/live/sites/algolia-assets/files/opengraph/algolia-opengraph-image.jpg" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Home&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;18,000&amp;#43; organizations trust Algolia to build intuitive, adaptive, high-performing experiences with a unified AI search &amp;amp; retrieval platform spanning agentic, generative, and search.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://www.algolia.com/files/live/sites/algolia-assets/files/icons/algolia-logo-for-favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;www.algolia.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Algoliaは&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Algolia is the most reliable platform for building search into your business.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ということで、検索機能を提供してくれるサービスです。ここに先ほどHugoで生成したJSONを元に検索対象のデータを登録していきましょう。&lt;/p&gt;
&lt;p&gt;なにはともあれユーザー登録を済ませます。無料で使えるライセンスがあるので僕はそれを選択しました。&lt;/p&gt;
&lt;p&gt;無料版の制約は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;登録可能なデータの上限&lt;/li&gt;
&lt;li&gt;データ操作回数の上限&lt;/li&gt;
&lt;li&gt;algoliaのロゴを表示&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;といったもので、ブログ用途には十分です。&lt;/p&gt;
&lt;p&gt;続いて、NEW APPLICATIONからアプリケーションを登録します。名前を適当にいれればOK。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/jQ0DcXDiFt4QnR_gaJtmhKcvJFr_mj4DXuOZ89GpDSHJiXoFtQ1J_cpE9aBMs14yJmC1vVoGfZIWAKzy_z748mCp9TrRlxc-6ax-YI_9EmfuFXXmHEbpTEjvlVq0XvJTe3EWCyp1yRkcHasz-61e7lYL14dhQtJkeka9EZTZEmpkP83bHWRDkY4Qv-PjbM80r8Rr3EbPdcvfsBUlxMjiEildsOrVrJHTc9qPQNF7FnOHAx1xSkWKJkQPAxI34MppL3C7Eas2bJmJW0Fw74LYe0DiVzJlAX5liGmWtLW9G4sMK8jlZM7AyhEAx8QiOh-HPd1xp4GjlDsjEVZPEpjkKtk2TezEURJqaPhXKVSslDmIn4Mr1fCJ_Y_8-NaeFtJuPp1VGH7X5rFsRekY1Kks3qmAhw9GXFwmO7ID04va3vX1PcXHjh4jUYS3g2CSSEUVH083yFEtAggljqvE4tPH9k8lsZxOtpz0C73i5AkZtO0yAIy6o6TR2dtYX-CLGwh-G_sI4s8jI6NVIVLF_KIzCvT6IYBzMSYJp5Nq6PmUbbS40HB1hhm7IxPnmzj6idyP2l8MPl0qjlvb_n4RS7QML9QEclln0_pNcnZ9pftn17ahwjvZEQRE0618FB6FlisVymLwQFwHZWAWeoh3URJJgrbyykXn4FUTRw=w583-h286-no"&gt;&lt;img src="https://lh3.googleusercontent.com/jQ0DcXDiFt4QnR_gaJtmhKcvJFr_mj4DXuOZ89GpDSHJiXoFtQ1J_cpE9aBMs14yJmC1vVoGfZIWAKzy_z748mCp9TrRlxc-6ax-YI_9EmfuFXXmHEbpTEjvlVq0XvJTe3EWCyp1yRkcHasz-61e7lYL14dhQtJkeka9EZTZEmpkP83bHWRDkY4Qv-PjbM80r8Rr3EbPdcvfsBUlxMjiEildsOrVrJHTc9qPQNF7FnOHAx1xSkWKJkQPAxI34MppL3C7Eas2bJmJW0Fw74LYe0DiVzJlAX5liGmWtLW9G4sMK8jlZM7AyhEAx8QiOh-HPd1xp4GjlDsjEVZPEpjkKtk2TezEURJqaPhXKVSslDmIn4Mr1fCJ_Y_8-NaeFtJuPp1VGH7X5rFsRekY1Kks3qmAhw9GXFwmO7ID04va3vX1PcXHjh4jUYS3g2CSSEUVH083yFEtAggljqvE4tPH9k8lsZxOtpz0C73i5AkZtO0yAIy6o6TR2dtYX-CLGwh-G_sI4s8jI6NVIVLF_KIzCvT6IYBzMSYJp5Nq6PmUbbS40HB1hhm7IxPnmzj6idyP2l8MPl0qjlvb_n4RS7QML9QEclln0_pNcnZ9pftn17ahwjvZEQRE0618FB6FlisVymLwQFwHZWAWeoh3URJJgrbyykXn4FUTRw=w583-h286-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;するとインデックスの登録や検索に使うためのAPI Keyが発行されます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/EoqiL6mWxSWvWw58IYwDzrwAYVFJl3KG9pchpbWd_7kjnPxuulrAnE44TtowbZKW32Nw5iH7TVCXY06jYrjRIvkXE_qhr5bW9WFv-P4uIqA6VbtfdGRDhlugCM0n70keVvElaCDs4nqagf6YF2WT_fMJ756XRE3NTbi_r4qunARuxlyf8kGSe-pdfwjB5CcgZzafLE9g_YXGVlMr3B17JR1W0nbfOpM-z4Thd-34s1IXewnsaHJhzhjwJ9a7-33ZoKrNkyb0hDpiLhIIj75UadBBY35INo4Kzc7eDBGvh2ZO2K-qCf6Ze_kggXezGKMxbq6p0vEGPgTdyaJfqh8xuFhJ2n9MNLzCnDN6JSeIkSzcPxf7cK3hB7lR7GSakN6LV-zG11iGUyx9xsnGAF9DKBGvgyYqMOTKArSZrSgmbFpfPKjQickgugoeBO2mkzk66tif9SPY0-9grtoiQMM5HaKXij8FQBlLPYbkU1v53KtHPMBtLqjOKJhl9hVkkYDv8SpXg9xyQKS8DSdwWy1ftcrI_G8FMgPKCxhLzaQYOe25ywh7aByYtuCHFTlAIeFBw2b6t3dcjobjPSWQ-Lqjcqs1Rkusqj-kow-iBlvaPyBesTrwLv91QwP4ZEhhZ0293rnm3zcLITeSFqpb_EFmlxnPicRoTUhH8A=w2020-h1316-no"&gt;&lt;img src="https://lh3.googleusercontent.com/EoqiL6mWxSWvWw58IYwDzrwAYVFJl3KG9pchpbWd_7kjnPxuulrAnE44TtowbZKW32Nw5iH7TVCXY06jYrjRIvkXE_qhr5bW9WFv-P4uIqA6VbtfdGRDhlugCM0n70keVvElaCDs4nqagf6YF2WT_fMJ756XRE3NTbi_r4qunARuxlyf8kGSe-pdfwjB5CcgZzafLE9g_YXGVlMr3B17JR1W0nbfOpM-z4Thd-34s1IXewnsaHJhzhjwJ9a7-33ZoKrNkyb0hDpiLhIIj75UadBBY35INo4Kzc7eDBGvh2ZO2K-qCf6Ze_kggXezGKMxbq6p0vEGPgTdyaJfqh8xuFhJ2n9MNLzCnDN6JSeIkSzcPxf7cK3hB7lR7GSakN6LV-zG11iGUyx9xsnGAF9DKBGvgyYqMOTKArSZrSgmbFpfPKjQickgugoeBO2mkzk66tif9SPY0-9grtoiQMM5HaKXij8FQBlLPYbkU1v53KtHPMBtLqjOKJhl9hVkkYDv8SpXg9xyQKS8DSdwWy1ftcrI_G8FMgPKCxhLzaQYOe25ywh7aByYtuCHFTlAIeFBw2b6t3dcjobjPSWQ-Lqjcqs1Rkusqj-kow-iBlvaPyBesTrwLv91QwP4ZEhhZ0293rnm3zcLITeSFqpb_EFmlxnPicRoTUhH8A=w2020-h1316-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;後ほどこれらを使用します。&lt;/p&gt;
&lt;h1 id="algoliaへインデックスを登録"&gt;Algoliaへインデックスを登録&lt;/h1&gt;
&lt;p&gt;Hugoを手元でビルドしてアップロードしている人の場合はAlgoliaへの登録も手元から行えばいいのですが、Netlifyのようにビルドお任せサービスを使っている場合にはそうはいきません。幸い、生成されたalgolia.jsonはどこからもアクセスできますので、ビルド後のWebhookでAlgoliaへアップロードする仕組みをトリガーしてあげなければいけません。&lt;/p&gt;
&lt;p&gt;やることはごくシンプルで、書き出されたJSONを読み取ってAlgoliaのAPIでデータを登録していくだけなので、自分で書くことは比較的容易です。各種言語に対応したクライアントライブラリも存在します。&lt;/p&gt;
&lt;p&gt;ですが、それをどこで実行するのか、それ用のサーバーを別途用意するのか。それとも自分用に動かしているGoのサーバーに機能を追加するのか。今回は元記事を参考に、サーバーレスでタスクを動かせる&lt;a href="https://webtask.io/"&gt;Webtask&lt;/a&gt;を利用して実施することにしました。&lt;/p&gt;
&lt;p&gt;元記事に詳細な手順があるので、ここでは手順を簡単に紹介しておきます。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;WebTaskでサインアップする&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ git clone https://github.com/forestryio-templates/serverless-atomic-algolia&lt;/code&gt; する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ npm install serverless -g &amp;amp;&amp;amp; npm install&lt;/code&gt; で必要なものをインストール&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ serverless config credentials --provider webtasks&lt;/code&gt; でログインする&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config/secrets.yml.stub&lt;/code&gt;ファイルを&lt;code&gt;config/secrets.yml&lt;/code&gt;としてコピーする&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config/secrets.yml&lt;/code&gt;をAlgoliaのダッシュボードの自分のアプリの設定に書き換える&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config/index.js&lt;/code&gt;の一部を書き換え。Algolia内のIndex名や、サイトのJSONのURLを記載。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ serverless deploy&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最後のデプロイでこんな感じの↓URLが発行されます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://wt-60952c750afexxxxxxxxxxxxxxxx-0.sandbox.auth0-extend.com/yyyyyyyyyyy"&gt;https://wt-60952c750afexxxxxxxxxxxxxxxx-0.sandbox.auth0-extend.com/yyyyyyyyyyy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここにアクセスすると実際にコードが動くわけですが、僕の場合は2つほど依存関係のエラーが起こりました。追加でライブラリを追加し再度デプロイすることでエラーが解消してAlgolia側にデータが登録されることを確認できました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$ npm install --save source-map-support&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ npm install --save babel-runtime&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Algoliaに登録されたデータの様子。340recordsと表示されています。管理ページ内で検索を試みることもできます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/pyahWDjlnvwHdT7vmZVHKHUIvhovtY8oIvggXsdSRjZBsQ6Su9vo4Yne9nW1fFpJFweL6S8QvGUkGsUmi5ygnDMSiAhd70InhMuk91kMg6qEQU0LrKTtPaoR01v4Nvz0ewzGjVseE8TPxW1mfE0aGJjd4ia1V38c4W5_ckPq1JtWn2sDYuaN-kFWpuYefivZ9QHNvlX8bIr_X2NkTPEGcFCVt2sHyLV93_5eZWYQBfEpvlsFsA2nDsjwwr48fTU7_NtQIWoU7xXbH74v466AzztaKJM5X5aYJAUFmcdPzSxWK_1jUym_QgFbOrpAfq4IddyFBC_HdiJ0EjM40fEf0zcIL-6bzz9p2AKQcjE6magHALhwMpp2DwKi5wYtaKea91HfFfy538BPK_1DqBI45X68XRyqdxLr3HwI7LMMzNVg4KjAhwIz-id-eP5FejC6g85FNP4ZuCRPcw0Eovf7g8m8-cajAIAO8x3qD58sECx4003HK5v7fwKr1INTR0JtmUhfyA5VBoE8vgmrA2GG21cisXMpwzaMAuZc2k7IqRewfum-LAdftRt0-IL6QBhgDMUATHBDuuX5zw8FeTAljH27AWQbSUVf9TiP2Ae8Zxcq3Sr_Lo2WW9NgnO-5XuLFwwS_EtvQExJ-jSIGzIPvwqq3RDFB2dHGPA=w776-h346-no"&gt;&lt;img src="https://lh3.googleusercontent.com/pyahWDjlnvwHdT7vmZVHKHUIvhovtY8oIvggXsdSRjZBsQ6Su9vo4Yne9nW1fFpJFweL6S8QvGUkGsUmi5ygnDMSiAhd70InhMuk91kMg6qEQU0LrKTtPaoR01v4Nvz0ewzGjVseE8TPxW1mfE0aGJjd4ia1V38c4W5_ckPq1JtWn2sDYuaN-kFWpuYefivZ9QHNvlX8bIr_X2NkTPEGcFCVt2sHyLV93_5eZWYQBfEpvlsFsA2nDsjwwr48fTU7_NtQIWoU7xXbH74v466AzztaKJM5X5aYJAUFmcdPzSxWK_1jUym_QgFbOrpAfq4IddyFBC_HdiJ0EjM40fEf0zcIL-6bzz9p2AKQcjE6magHALhwMpp2DwKi5wYtaKea91HfFfy538BPK_1DqBI45X68XRyqdxLr3HwI7LMMzNVg4KjAhwIz-id-eP5FejC6g85FNP4ZuCRPcw0Eovf7g8m8-cajAIAO8x3qD58sECx4003HK5v7fwKr1INTR0JtmUhfyA5VBoE8vgmrA2GG21cisXMpwzaMAuZc2k7IqRewfum-LAdftRt0-IL6QBhgDMUATHBDuuX5zw8FeTAljH27AWQbSUVf9TiP2Ae8Zxcq3Sr_Lo2WW9NgnO-5XuLFwwS_EtvQExJ-jSIGzIPvwqq3RDFB2dHGPA=w776-h346-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;あとはさきほどのWebTaskが定期的に実行されればOKですね。僕の場合はNetlifyのビルド後のWebhookに登録して自動で走るようにしています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/2VY_REDQfzA-BQ0kUPb3isccYPUiNIUrMbXWxT5bVQz4jfYp9bRDzBckJ1t2i89bYlne2GeeHMyxGu_Uj7dnePX6acw1vmIRFFQKIst1W3v4zkCOTPshLw0gub-CE9CqM5SRthXwOZNlnU5K75BD9PukXgVn9wls2An0RtMXWlUns-G4-TW6t822S-pBynXO6jRJlgsPImGv85d7InpWfdXepb63vUOjSRmToSfTIFvPIfeq0pXI2BcmJ-WcM5TPC8iLLkd-deJLBbcnBrz0MdqtHohzlSrIbiuVH0RvxhOoR2QZXDzotGSs70TJLienwAeXy1PYskLVOJ9Qz_AJO7uJVWaVQjf5dfONmj-OYlglsWOzWKn44eaN29E8P8ulDvpcTMKj3E5zUETdX_HP2LgYzhQ61OU9nV7iivsv4BJmGpvmbq82cxik_Q9lFsWMayIZSzz-j7GyRh87pk6m3eEAzJGTPA4kHrBIjHjYu6wOCNNX7oP33Ir6wSin-OSbXs0ifiO1gqXh7vM7ouATwr0lxPEWcpWjKI6PHtWphXJ7inITMwCULV6jlJ2_HHaeH7fUQVrySCBr3KrzjYhLaXbcSLbEJhedNBHUAXDDyV8hLQtwjLEUjm3nb-qJeg5dBFgmj09KYYpF_PQsJsulYXx7VTsoqIvImA=w1848-h620-no"&gt;&lt;img src="https://lh3.googleusercontent.com/2VY_REDQfzA-BQ0kUPb3isccYPUiNIUrMbXWxT5bVQz4jfYp9bRDzBckJ1t2i89bYlne2GeeHMyxGu_Uj7dnePX6acw1vmIRFFQKIst1W3v4zkCOTPshLw0gub-CE9CqM5SRthXwOZNlnU5K75BD9PukXgVn9wls2An0RtMXWlUns-G4-TW6t822S-pBynXO6jRJlgsPImGv85d7InpWfdXepb63vUOjSRmToSfTIFvPIfeq0pXI2BcmJ-WcM5TPC8iLLkd-deJLBbcnBrz0MdqtHohzlSrIbiuVH0RvxhOoR2QZXDzotGSs70TJLienwAeXy1PYskLVOJ9Qz_AJO7uJVWaVQjf5dfONmj-OYlglsWOzWKn44eaN29E8P8ulDvpcTMKj3E5zUETdX_HP2LgYzhQ61OU9nV7iivsv4BJmGpvmbq82cxik_Q9lFsWMayIZSzz-j7GyRh87pk6m3eEAzJGTPA4kHrBIjHjYu6wOCNNX7oP33Ir6wSin-OSbXs0ifiO1gqXh7vM7ouATwr0lxPEWcpWjKI6PHtWphXJ7inITMwCULV6jlJ2_HHaeH7fUQVrySCBr3KrzjYhLaXbcSLbEJhedNBHUAXDDyV8hLQtwjLEUjm3nb-qJeg5dBFgmj09KYYpF_PQsJsulYXx7VTsoqIvImA=w1848-h620-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これで検索インデックスの準備はOKです。次回はブログ上に検索ボックスを配置して検索するところを紹介したいと思います。&lt;/p&gt;</description></item><item><title>Rails周りで最近知ったこと 2018/04版</title><link>https://blog.piyo.tech/posts/2018-04-06-rails-memo/</link><pubDate>Fri, 06 Apr 2018 18:11:53 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-06-rails-memo/</guid><description>&lt;h1 id="stringsquish"&gt;String#squish&lt;/h1&gt;
&lt;p&gt;ActiveSupportで定義されているらしい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;squish&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; dup&lt;span style="color:#f92672"&gt;.&lt;/span&gt;squish!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;squish!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; gsub!(&lt;span style="color:#e6db74"&gt;/[[:space:]]+/&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34; &amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; strip!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; self
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;halt_callback_chains_on_return_false&lt;/code&gt; がDeprecatedになった件でプルリク見てたら書いてあってみつけた。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/rails/rails/commit/4e63ce53fc25c3bc15c5ebf54bab54fa847ee02a#diff-b7cfe363f52542625a68a042e68c9c85R83"&gt;deprecate &lt;code&gt;halt_callback_chains_on_return_false&lt;/code&gt; instead of `halt_and… · rails/rails@4e63ce5&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ActiveSupport&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Deprecation&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;warn(&lt;span style="color:#e6db74"&gt;&amp;lt;&amp;lt;-MSG.squish)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ActiveSupport&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;halt_callback_chains_on_return_false is deprecated &lt;span style="color:#f92672"&gt;and&lt;/span&gt; will be removed &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;MSG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ヒアドキュメントの余計な空白とか消すのに使うんだね。&lt;/p&gt;
&lt;h1 id="window_opened_by"&gt;window_opened_by&lt;/h1&gt;
&lt;p&gt;Capybaraでリンクをクリックしたときに別タブが開いて、みたいなときに使えるメソッドがあった。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.rubydoc.info/github/jnicklas/capybara/Capybara%2FSession%3Awindow_opened_by"&gt;Method: Capybara::Session#window_opened_by — Documentation for jnicklas/capybara (master)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;within_window&lt;/code&gt;と組み合わせて使える。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.rubydoc.info/github/jnicklas/capybara/Capybara/Session:within_window"&gt;Method: Capybara::Session#within_window — Documentation for jnicklas/capybara (master)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;こんな感じ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;scenario &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; visit root_path
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; window &lt;span style="color:#f92672"&gt;=&lt;/span&gt; window_opened_by { click_lick &lt;span style="color:#e6db74"&gt;&amp;#39;新しいタブで開く&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; within_window(window) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; expect(page)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to have_content &lt;span style="color:#e6db74"&gt;&amp;#39;新しいタブだよ&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="remote_ip"&gt;remote_ip&lt;/h1&gt;
&lt;p&gt;接続元のIPでアクセス制限するみたいなコードを書く時に、&lt;code&gt;request.remote_ip&lt;/code&gt;を使ってました。環境構成がシンプルなときはそれでいけてました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://apidock.com/rails/ActionController/Request/remote_ip"&gt;remote_ip (ActionController::Request) - APIdock&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;最近触ったアプリケーションが、CloudFrontを通ったりなんだりいろいろ経由してからRailsに到達する構成だったので接続元（ユーザーの環境）のIPがremote_ipで取れないことがありました。&lt;/p&gt;
&lt;p&gt;調べてみると、経由した順に&lt;code&gt;request.headers['X-Forwarded-For']&lt;/code&gt;にカンマ区切りで入っていることが判明。環境に合わせて取り出せるように、こんな風にしてIPを取り出せることがわかりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;client_ip&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; @client_ip &lt;span style="color:#f92672"&gt;||=&lt;/span&gt; (request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;headers&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;X-Forwarded-For&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;].&lt;/span&gt;to_s&lt;span style="color:#f92672"&gt;.&lt;/span&gt;gsub(&lt;span style="color:#e6db74"&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;split(&lt;span style="color:#e6db74"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;first &lt;span style="color:#f92672"&gt;||&lt;/span&gt; request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;remote_ip)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;HTTP_X_FORWARDED_FOR&lt;/code&gt;に入ってるんですねー。HTTPの仕様、一通り知らないといかんな。。。&lt;/p&gt;</description></item><item><title>ブログのビルド用にOGPの情報をJSONで返すサーバーも作った</title><link>https://blog.piyo.tech/posts/2018-04-04-ogp-json/</link><pubDate>Wed, 04 Apr 2018 19:41:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-04-ogp-json/</guid><description>&lt;p&gt;前回の続きです。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-04-02-blog-link/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://lh3.googleusercontent.com/r0owED5cBmCrD0wSbGkZkndJpmBW1SzYJPnfeb4w6XtcRfmmAr7IEYeo2nsjt3cHb81HlpByTaF4-1_UIXqJrWCfj_m-EaPaoYEszOlNg5qSIgQPbKBiyLQVgylgohhqzlss39qtNC7C6PzmxN0t6i0tAlfN858y1NXR-p9zoGsNDD_ESSfy5xrMOqAyWcav-aqnKjggx4xOnbxK0zA7qw8zVdqztuAfysiwKZI1r39UZ13ina1SjA_TEeC3zdQ132HcK4UuGSyLFmB0W662oCOyZaCz4yaTVN4tcXQm8aGsNn1nyyp7S0MQiJk2Oy-zFHcwh4WAojtUMX9HJa9T_C34B6LNPrgoavxsVumFk76ZmCVguxzLstJ1GUg61u61j1f3g_Yd3f83cTz64mc5Tg3dn4EFrgrBRQ0ZudYx99jZDTC2vYPvlZBTxWzjkWNo0AFEwO2IcZtRf31y07Jqrp5LtXwAayPNEO138CoeS7Bhc88Llw3SM76R2KYu-gbVnbljhq1xYI_bgTT_zNNl561znfF96T9wX8bwfVYEziO8i5iVIK5vUl4l1d_JCi_9Ydy-bK8ooczLhq9hWaw0czTbT8X36HjU8NmfZLDrvZC7JaBhaki5JeMjvQEw0BlchpNVno0IHoZyEe2vv59ZJpu-_agRSarUKA=w1000-h667-no" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Hugoでブログリンクの見た目をはてなブログっぽくする - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;これまで HeartRails Capture を使ってきたブログ内リンクを自前の実装とショートコードに置き換えました。 以前使っていたはてなブログのリンクの表示形式が気に入っていたので、それをリスペクトする形でほぼ同じような見た目で表示できるようにしました。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;リンクの見た目をいい感じにするためにOGPのJSONのサーバーを作って、Data-Driven Contentで表示するようにしたよ、というのが前回の話です。&lt;/p&gt;
&lt;h1 id="echoのサーバーに機能追加"&gt;echoのサーバーに機能追加&lt;/h1&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-03-27-deploy-go/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://goo.gl/NSXeuF" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;ブログのビルド用にGoのサーバーをVPS上で動かした話 - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;先日Hugo &amp;#43; Netlifyでブログを再構築したよという記事を書きました。Amazonのアフィリンクを簡単に置くためにショートコードを使っていて、記事のビルドの際にはAmazonの情報をを取ってくるサーバーが必要になります。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;すでに動かしているGoのサーバーに機能を追加しました。&lt;code&gt;/ogp?url=http://xxxxx&lt;/code&gt;とリクエストすると欲しいサイトのOGPをJSONで返してくれるようにします。&lt;/p&gt;
&lt;h2 id="依存ライブラリのインストール"&gt;依存ライブラリのインストール&lt;/h2&gt;
&lt;p&gt;Goはまだ触り始めたばかりでよくわからないんですが、元々参考にしてたコードがdepというもので依存ライブラリの管理をしていたので、そのまま踏襲して使いました。&lt;/p&gt;
&lt;p&gt;Go製でOGPを取得できるライブラリって探して見つけた↓を使いました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/otiai10/opengraph"&gt;otiai10/opengraph: Golang Open Graph Parser&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ dep ensure -add github.com/otiai10/opengraph
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;で、↑だとリリースが少し古くてDescriptionがうまく取れないことがあったのでmasterを参照すべく、&lt;code&gt;version = &amp;quot;1.0.0&amp;quot;&amp;quot;&lt;/code&gt;の行を削除し、&lt;code&gt;branch = &amp;quot;master&amp;quot;&lt;/code&gt;の行を追加し、再度 &lt;code&gt;$ dep ensure&lt;/code&gt;しました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[[constraint]]
name = &amp;#34;github.com/otiai10/opengraph&amp;#34;
branch = &amp;#34;master&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これで準備OKです。&lt;/p&gt;
&lt;h2 id="ルーティングとハンドラ"&gt;ルーティングとハンドラ&lt;/h2&gt;
&lt;p&gt;↑と呼ぶのが適切かどうかはさておき、次はURLと対応する処理を書きました。&lt;/p&gt;
&lt;p&gt;Go言語のechoについては以前ちょろっと書いたので省略しますが、とても簡単にかけました。&lt;/p&gt;
&lt;p&gt;まずはURLとその処理関数を追加する部分。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// importに追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/otiai10/opengraph&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;echo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;New&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;GET&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;/ogp&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;getOgp&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;処理の実装がこんな感じ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getOgp&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;echo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Context&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;url&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;QueryParam&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(&lt;span style="color:#a6e22e"&gt;url&lt;/span&gt;) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusBadRequest&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Url is empty&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;og&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;opengraph&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fetch&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;url&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusInternalServerError&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Error: %s&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Error&lt;/span&gt;()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;og&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;og&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ToAbsURL&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;JSON&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusOK&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;og&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;クエリパラメータで渡ってくるurlを取り出して、先ほどのライブラリに渡してOGPの情報を得ます。それをJSONとして返すだけです。&lt;/p&gt;
&lt;p&gt;例えばこちらの記事の情報を取得するには、&lt;code&gt;サーバー/ogp?url=https://blog.piyo.tech/posts/2018-03-27-deploy-go/&lt;/code&gt; とします。すると↓のようなJSONが得られます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Title&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;ブログのビルド用にGoのサーバーをVPS上で動かした話 - ぴよログ&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Type&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;article&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;URL&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Source&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.piyo.tech/posts/2018-03-27-deploy-go/&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Scheme&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;https&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Opaque&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;User&amp;#34;&lt;/span&gt;:&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Host&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;blog.piyo.tech&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Path&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;/posts/2018-03-27-deploy-go/&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;RawPath&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ForceQuery&amp;#34;&lt;/span&gt;:&lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;RawQuery&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Fragment&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;SiteName&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;ぴよログ&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Image&amp;#34;&lt;/span&gt;:[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;URL&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;https://goo.gl/NSXeuF&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;SURL&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Type&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Width&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Height&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Alt&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Video&amp;#34;&lt;/span&gt;:[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Audio&amp;#34;&lt;/span&gt;:[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Description&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;ブログのビルド用にGoのサーバーをVPS上で動かした話&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Determiner&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Locale&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;LocaleAlt&amp;#34;&lt;/span&gt;:[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Favicon&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.piyo.tech/images/favicon-16x16.png&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとは前回の記事のとおり、Data-Driven ContentでこのJSONを使うだけですね。&lt;/p&gt;
&lt;p&gt;簡単にAPIサーバーを作ることができたおかげで思ったとおりにブログいじりが進みました。&lt;/p&gt;</description></item><item><title>GoogleのURL短縮サービスで作ったURLはサービス終了後も生き続ける</title><link>https://blog.piyo.tech/posts/2018-04-03-googl/</link><pubDate>Tue, 03 Apr 2018 06:30:16 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-03-googl/</guid><description>&lt;p&gt;先日Google URL Shortenerのサービス終了が発表されました。今まで生成した大量のURLをどうしよう、戦慄している人も多いと思われます。&lt;/p&gt;
&lt;p&gt;ニュースの見出しだけ見て「サービス終了まじか！」とならないように、原典をあたりましょう。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://developers.googleblog.com/2018/03/transitioning-google-url-shortener.html" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://storage.googleapis.com/gweb-developer-goog-blog-assets/images/GfD-Project-GameFace-blue_1.2e16d0ba.fill-1200x600.png" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Google URL Shortener links will no longer be available [updated]&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;Understand how you will be impacted by our decision to turn off the serving portion of Google URL Shortener.&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://storage.googleapis.com/gweb-developer-goog-blog-assets/meta/favicon.ico" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;developers.googleblog.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;結論から言うと、既に作ったURLはサービス終了である2019年3月30日以降も従来通りリダイレクトされます。&lt;/p&gt;
&lt;p&gt;原典にもその旨きちんと記載があります。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;all existing links will continue to redirect to the intended destination.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;また、ログイン状態で作られたURLのリストやアナリティクスデータはCSVでダウンロードできます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/QESy66Yy7ze70tvOr3MjjsEbf_ZBHSUXxsi79IoGDOvWXKaC9BWJzjycLJXs77x6ODets_B2g689NY3NHqWh3EFkBk1Ie24Ap_QM4KoFhRAcg_hqEnozCQdani85RhorFu9ctCi2CxlIPiVvYmdRvnZE-PfXIcn_ALnYPE7icoYGIHUwHpbftlfCBBsTT_Ttp5WOxCcs3x1P89fQ8BAoT-uv6pEsaCR7ehHUpPpobW7fVGbnSi1d34EBER8ozhGgq2GWHj-_C0iX7BRbWFCTIg2nfN02joQYmZXdLVjeySJJKOi-U5X87hHvVC0x8Fs0mTdwiAOd0vvA2F2tvbhOvQ4kP6W8sFyik9QnLhMTg0nuw1thMDZzrcp4xKXUeApaK3fJgNuEdBqtspQ1RS9ksuANdVvzGJ4gWa3wnAMw6WfRPBAR3Jl0sjYdapiYQqDbCYHzZ9fa6Ko0fUYwuLsVKhYpT8CgoMrn1gaZrUCyb1-w91dn7ZgM3T_Hlx9DSqScI3NyKYceip_DOvEJReV-2bwU4YqTn4CQKDID1ceA-Xt8L5iCxmy3rAZF4C5R0wf4rqSrLh6V8bNzIRWPFlmFTcNndJOVq6m3py26wzWebSoGGYSNbbjD3bxdz3Zjdq7qP1s6gAQfMXW_FGs6aV8KwHa1a0VsjCYIEg=w2210-h610-no"&gt;&lt;img src="https://lh3.googleusercontent.com/QESy66Yy7ze70tvOr3MjjsEbf_ZBHSUXxsi79IoGDOvWXKaC9BWJzjycLJXs77x6ODets_B2g689NY3NHqWh3EFkBk1Ie24Ap_QM4KoFhRAcg_hqEnozCQdani85RhorFu9ctCi2CxlIPiVvYmdRvnZE-PfXIcn_ALnYPE7icoYGIHUwHpbftlfCBBsTT_Ttp5WOxCcs3x1P89fQ8BAoT-uv6pEsaCR7ehHUpPpobW7fVGbnSi1d34EBER8ozhGgq2GWHj-_C0iX7BRbWFCTIg2nfN02joQYmZXdLVjeySJJKOi-U5X87hHvVC0x8Fs0mTdwiAOd0vvA2F2tvbhOvQ4kP6W8sFyik9QnLhMTg0nuw1thMDZzrcp4xKXUeApaK3fJgNuEdBqtspQ1RS9ksuANdVvzGJ4gWa3wnAMw6WfRPBAR3Jl0sjYdapiYQqDbCYHzZ9fa6Ko0fUYwuLsVKhYpT8CgoMrn1gaZrUCyb1-w91dn7ZgM3T_Hlx9DSqScI3NyKYceip_DOvEJReV-2bwU4YqTn4CQKDID1ceA-Xt8L5iCxmy3rAZF4C5R0wf4rqSrLh6V8bNzIRWPFlmFTcNndJOVq6m3py26wzWebSoGGYSNbbjD3bxdz3Zjdq7qP1s6gAQfMXW_FGs6aV8KwHa1a0VsjCYIEg=w2210-h610-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;右上に「DOWNLOAD CSV」ボタンがありますね。サービス終了までの間はCSVフォーマットで↑の画像と同等の情報をダウンロードすることが可能です。&lt;/p&gt;
&lt;p&gt;とは言え、リダイレクトもいつまで続けてくれるか正直わからないと思うので、そもそも使わないでおいたほうが良いでしょう。&lt;/p&gt;</description></item><item><title>Hugoでブログリンクの見た目をはてなブログっぽくする</title><link>https://blog.piyo.tech/posts/2018-04-02-blog-link/</link><pubDate>Mon, 02 Apr 2018 19:41:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-02-blog-link/</guid><description>&lt;p&gt;これまで&lt;a href="https://capture.heartrails.com/"&gt;HeartRails Capture&lt;/a&gt;を使ってきたブログ内リンクを自前の実装とショートコードに置き換えました。&lt;/p&gt;
&lt;p&gt;以前使っていたはてなブログのリンクの表示形式が気に入っていたので、それをリスペクトする形でほぼ同じような見た目で表示できるようにしました。&lt;/p&gt;
&lt;p&gt;ある記事内のリンクの見た目はどうなったのか。BeforeとAfterで見比べてみましょう。&lt;/p&gt;
&lt;h2 id="before"&gt;Before&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://goo.gl/KnqNfg"&gt;&lt;img src="https://goo.gl/KnqNfg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="after"&gt;After&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://goo.gl/bkY6AR"&gt;&lt;img src="https://goo.gl/bkY6AR" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="新旧の違い"&gt;新旧の違い&lt;/h2&gt;
&lt;p&gt;新旧で見た目が異なるのはもちろんですが、より詳しい情報を得られるように仕組みも変更しました。&lt;/p&gt;
&lt;p&gt;Heartrails Captureを使ったリンクではブラウザで表示したときに見える画面のキャプチャを表示していましたが、今回のリンクではOGPを利用します。&lt;/p&gt;
&lt;p&gt;最近は多くのサイトでOGPの画像やDescriptionが設定されていることが多いです。Hugoに移行した時からOGPを使って表示したいなと思っていました。&lt;/p&gt;
&lt;h1 id="ショートコードとhtml"&gt;ショートコードとHTML&lt;/h1&gt;
&lt;p&gt;ショートコードは例えばこんな感じにしました。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;{{&amp;lt; link url=&amp;ldquo;&lt;a href="https://blog.piyo.tech/posts/2018-03-27-deploy-go/%22"&gt;https://blog.piyo.tech/posts/2018-03-27-deploy-go/&amp;quot;&lt;/a&gt; &amp;gt;}}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ショートコードに対応したHTMlは以下のようになってます。&lt;del&gt;（ほぼはてなブログと一緒）&lt;/del&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{{- $url := .Get &amp;#34;url&amp;#34; -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{{- $json := getJSON .Site.Params.OgpJsonBaseUrl $url -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;{{- $title := $json.Title -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;{{- $siteName := $json.SiteName -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;{{- $description := $json.Description -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;{{- $favicon := $json.Favicon -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;{{- $image := index $json.Image 0 -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;{{- $imageUrl := $image.URL -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;{{- $urlInfo := $json.URL -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;{{- $host := $urlInfo.Host -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;embed-wrapper&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;embed-wrapper-inner&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;embed-content with-thumb&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;thumb-wrapper&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $url }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;_blank&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;img&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $imageUrl }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;thumb&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;entry-body&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;entry-title&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $url }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;_blank&amp;#34;&lt;/span&gt;&amp;gt;{{ $title }}&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;entry-content&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; {{ $description }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;embed-footer&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $url }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;_blank&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;img&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $favicon }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;alt&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $host }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;favicon&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; {{ $host }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://b.hatena.ne.jp/entry/{{ $url | safeURL }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;_blank&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style="color:#f92672"&gt;img&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://b.hatena.ne.jp/entry/image/{{ $url | safeURL }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;bookmark-count&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;HugoにはData Driven Contentの仕組みがあります。これはAmazonのAdvertising APIのときにも利用したのですが、JSON APIから戻ってきた値をベースにしてHTMLを組み立てられるというものです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gohugo.io/templates/data-templates/#data-driven-content"&gt;Data Templates | Hugo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;コードのこの部分で、JSON APIを呼び出してOGPをJSONで取得します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{{&lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;json&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getJSON&lt;/span&gt; .&lt;span style="color:#a6e22e"&gt;Site&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Params&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;OgpJsonBaseUrl&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;url&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;OgpJsonBaseUrlについては、Hugoの&lt;code&gt;config.toml&lt;/code&gt;にこのように書いておきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;params&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;OgpJsonBaseURL&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;https://myapi.xxxxx.yyy/ogp?url=&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今回はURLに対応するOGPをJSONで返すサーバーを自前で用意しました。
&lt;code&gt;config.toml&lt;/code&gt;にはその自前サーバーのパスを書いておき、ショートコードの中でURLを渡してAPI呼び出します。そして得られたJSONの中身をもってHTMLを組み立てるということを行いました。&lt;/p&gt;
&lt;p&gt;ちなみに、OGPをJSONで取得する方法は、最初FacebookのかOpen Graphオブジェクトデバッガーあたりからできるのではないかと考えていました。ですがどうもそんなものがないのか探し方が悪いのか、見つかりませんでした。&lt;/p&gt;
&lt;p&gt;次回はOGPのJSONを返すサーバーについて書きまーす。&lt;/p&gt;</description></item><item><title>echoで書いてるブログの用サーバーにベーシック認証をかけた</title><link>https://blog.piyo.tech/posts/2018-04-01-echo-basic-auth/</link><pubDate>Sun, 01 Apr 2018 19:41:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-04-01-echo-basic-auth/</guid><description>&lt;p&gt;VPSでビルド用のサーバーを動かしているという話を書いたかと思います。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-03-27-deploy-go/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://goo.gl/NSXeuF" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;ブログのビルド用にGoのサーバーをVPS上で動かした話 - PIYO Notes&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;先日Hugo &amp;#43; Netlifyでブログを再構築したよという記事を書きました。Amazonのアフィリンクを簡単に置くためにショートコードを使っていて、記事のビルドの際にはAmazonの情報をを取ってくるサーバーが必要になります。&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://blog.piyo.tech/images/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;blog.piyo.tech&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;自分しか使わないのでベーシック認証を書ける形に変更しています。&lt;/p&gt;
&lt;h1 id="その前にechoについてちょっと"&gt;その前に：echoについてちょっと&lt;/h1&gt;
&lt;p&gt;雑にいうと、expressとかsinatraとかっぽい書き方でサーバーを書けるGoのライブラリっぽいです。&lt;/p&gt;
&lt;p&gt;最小に近いサンプルはこんな感じで、&lt;code&gt;e.GET&lt;/code&gt;にパスとリクエストハンドラみたいなのを書いてあげればOKというシンプルな感じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;echo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;New&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;GET&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;/hello&amp;#34;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;echo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Context&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusOK&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;GET&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;/world&amp;#34;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;echo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Context&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusOK&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;World&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Logger&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Start&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;:1323&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際、Advertising API用のコードもかなりシンプルです。&lt;/p&gt;
&lt;p&gt;↓は参考にさせてもらった元のコードです。この部分でasinを受け取るリクエストを処理してます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gitlab.com/longkey1/amazon-product-json/blob/master/main.go#L40"&gt;main.go · master · longkey1 / amazon-product-json · GitLab&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="ベーシック認証"&gt;ベーシック認証&lt;/h1&gt;
&lt;p&gt;公式にドキュメントにちゃんと書いてあります。めちゃくちゃシンプル。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://echo.labstack.com/middleware/basic-auth"&gt;Basic Auth Middleware | Echo - High performance, minimalist Go web framework&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;まず、importにmiddlewareを使うべく一行追加。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/labstack/echo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/labstack/echo/middleware&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// この行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;続いてmainでmiddlewareを使う旨と、usernameやパスワードを書いておいてあげます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;echo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;New&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Use&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;middleware&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;BasicAuth&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;username&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;password&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;echo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Context&lt;/span&gt;) (&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;username&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;joe&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;password&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;secret&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;という感じで設定できましたー。&lt;/p&gt;
&lt;p&gt;あとは使う側が&lt;code&gt;username:password@hostname&lt;/code&gt;でアクセスすれば良いです。&lt;/p&gt;</description></item><item><title>Railsのroutes.rbでconstraintsを使う</title><link>https://blog.piyo.tech/posts/2018-03-31-routes-constraints/</link><pubDate>Sat, 31 Mar 2018 18:27:30 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-03-31-routes-constraints/</guid><description>&lt;p&gt;ルーティングのマッチングの優先順位のせいか期待通りのコントローラーで処理できないことがあります。そんなときにconstraintsオプションでroutesのパラメータのフォーマットを制限できます。たまーに使います。&lt;/p&gt;
&lt;p&gt;たまーにしか使わなくて、なんで書いてあるんだっけ？と忘れていたので、思い出せた今回メモがてらに書いておきますよ。&lt;/p&gt;
&lt;h1 id="例だよ"&gt;例だよ&lt;/h1&gt;
&lt;p&gt;例えばこんな感じの&lt;code&gt;routes.rb&lt;/code&gt;になっているとします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt; resources &lt;span style="color:#e6db74"&gt;:messages&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;only&lt;/span&gt;: &lt;span style="color:#f92672"&gt;%&lt;/span&gt;i(index show)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; namespace &lt;span style="color:#e6db74"&gt;:messages&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; resources &lt;span style="color:#e6db74"&gt;:unreads&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;only&lt;/span&gt;: &lt;span style="color:#f92672"&gt;%&lt;/span&gt;i(index)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://postd.cc/how-dhh-organizes-his-rails-controllers/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;postd.cc →&lt;/span&gt;&lt;span&gt;https://postd.cc/how-dhh-organizes-his-rails-controllers/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;↑の例のようにnamespaceを切ると登場しうる書き方かなと思います。&lt;/p&gt;
&lt;p&gt;で、3つのルーティングができます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;messages_path GET /messages(.:format) messages#index
message_path GET /messages/:id(.:format) messages#show
messages_unreads_path GET /messages/unreads(.:format) messages/unreads#index
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;1個めと2個めは割と問題ないのですが、3個目が曲者です。↑のルーティングの意図としては&lt;code&gt;http://localhost:3000/messages/unreads&lt;/code&gt;などとアクセスした場合には&lt;code&gt;unreads#index&lt;/code&gt;側にいってほしいはずです。&lt;/p&gt;
&lt;p&gt;ですが、&lt;code&gt;/messages/unreads&lt;/code&gt;の&lt;code&gt;unreads&lt;/code&gt;の部分が、&amp;rsquo;/messages/:id&amp;rsquo;の&lt;code&gt;:id&lt;/code&gt;の部分とマッチしてしまい、&lt;code&gt;messages#show&lt;/code&gt;側で処理しようとしてしまいます。デフォルトでは&lt;code&gt;:id&lt;/code&gt;の箇所は数値でも文字列でもなんでもいいことになっているので、&lt;code&gt;unreads&lt;/code&gt;という文字列のパラメータが渡ってきたとして判断しちゃうんですね。&lt;/p&gt;
&lt;h1 id="こうするよ"&gt;こうするよ&lt;/h1&gt;
&lt;p&gt;これを想定通りに動かすために&lt;code&gt;constraints&lt;/code&gt;を使います。今回は&lt;code&gt;:id&lt;/code&gt;の部分が数値である場合に&lt;code&gt;messages#show&lt;/code&gt;にいってほしいので、その条件を書きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt; resources &lt;span style="color:#e6db74"&gt;:messages&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;only&lt;/span&gt;: &lt;span style="color:#f92672"&gt;%&lt;/span&gt;i(index show), &lt;span style="color:#e6db74"&gt;constraints&lt;/span&gt;: {id: &lt;span style="color:#e6db74"&gt;/\d+/&lt;/span&gt;} &lt;span style="color:#75715e"&gt;# &amp;lt;= この部分&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; namespace &lt;span style="color:#e6db74"&gt;:messages&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; resources &lt;span style="color:#e6db74"&gt;:unreads&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;only&lt;/span&gt;: &lt;span style="color:#f92672"&gt;%&lt;/span&gt;i(index)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;constraints&lt;/code&gt;には正規表現でパターンを指定できます。今回は数値にマッチする場合、としました。これ以外の&lt;code&gt;/messages/hogehoge&lt;/code&gt;は他で処理しますので、今回のルーティングだと&lt;code&gt;/messages/数値&lt;/code&gt;と&lt;code&gt;/messages/unreads&lt;/code&gt;以外はNo Routeになるわけですね。&lt;/p&gt;
&lt;p&gt;constraintsについて詳しくは &lt;a href="https://railsguides.jp/routing.html#%E3%82%BB%E3%82%B0%E3%83%A1%E3%83%B3%E3%83%88%E3%82%92%E5%88%B6%E9%99%90%E3%81%99%E3%82%8B"&gt;Rails のルーティング | Rails ガイド&lt;/a&gt; に記載があります。&lt;/p&gt;</description></item><item><title>Headless ChromeのテストがCircleCI上で動かなかった</title><link>https://blog.piyo.tech/posts/2018-03-30-chrome-on-circleci/</link><pubDate>Fri, 30 Mar 2018 18:27:30 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-03-30-chrome-on-circleci/</guid><description>&lt;p&gt;おとといの記事でHeadlessChromeを使ってテストするようにしたよ、と書きました。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-03-28-headless-chrome/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;blog.piyo.tech →&lt;/span&gt;&lt;span&gt;https://blog.piyo.tech/posts/2018-03-28-headless-chrome/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ですが、CircleCIではこんな感じのエラーを吐いて動きませんでした。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Selenium::WebDriver::Error::SessionNotCreatedError:
session not created exception: Chrome version must be &amp;gt;= 64.0.3282.0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;どうやら、circleciのイメージに元々入っているchromedriverと、gemとしてインストールしている&lt;code&gt;chromedriver-helper&lt;/code&gt;が衝突することによって起こるらしいということがわかりました。&lt;/p&gt;
&lt;h1 id="chromedriver-helper-を消す"&gt;chromedriver-helper を消す&lt;/h1&gt;
&lt;p&gt;となるとGemfileの&lt;code&gt;:test&lt;/code&gt;のブロックから&lt;code&gt;chromedriver-helper&lt;/code&gt;を消せばいいじゃないと思ったのですが、そうすると今度はローカルでのテストが困ります。&lt;/p&gt;
&lt;p&gt;Macではhomebrewを使ってchromedriverをインストールすることが可能ですが、僕の場合はうまくテストから接続できず断念しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ brew install chromedriver
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ brew services start chromedriver &lt;span style="color:#75715e"&gt;# サービスとして起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="gemfile書き換え"&gt;Gemfile書き換え&lt;/h1&gt;
&lt;p&gt;さらに調べてみるとGemfileを条件付きにしてしまうという方法を見つけました。ローカルでは&lt;code&gt;chromedriver-helper&lt;/code&gt;を使うが、CircleCIでは使わないようにします。確かにこの方法を取ることができればCircleCI上でchromedriverがコンフリクトすることはありません。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://discuss.circleci.com/t/has-chromedriver-been-updated-on-the-ubuntu-14-04-trusty-image/10941/6"&gt;Has ChromeDriver been updated on the Ubuntu 14.04 (Trusty) image?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;↓このように&lt;code&gt;ENV['CIRCLECI']&lt;/code&gt;がないときだけ&lt;code&gt;chromedriver-helper&lt;/code&gt;をインストールするようにします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;group &lt;span style="color:#e6db74"&gt;:test&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;chromedriver-helper&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;key?(&lt;span style="color:#e6db74"&gt;&amp;#39;CIRCLECI&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、この変更をpushしたあとはCI上のキャッシュを破棄する必要があるので「Rebuild without Cache」を実行しましょう&lt;/p&gt;
&lt;h1 id="ある程度動くようになったでも"&gt;ある程度動くようになった、でも…&lt;/h1&gt;
&lt;p&gt;軒並み失敗していたテストのうち、ほとんどが通るようになりました。ですが、一部のテストはまたドライバー周りで失敗していそうでした。エラーは大体こんな感じです。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Failure/Error: accept_confirm { click_link &amp;#39;削除&amp;#39; }
Capybara::ModalNotFound:
Unable to find modal dialog
# ./spec/features/hogehoge.rb:39:in `block (5 levels) in &amp;lt;top (required)&amp;gt;&amp;#39;
# ./spec/features/hogehoge.rb:38:in `block (4 levels) in &amp;lt;top (required)&amp;gt;&amp;#39;
# ./spec/rails_helper.rb:106:in `block (2 levels) in &amp;lt;top (required)&amp;gt;&amp;#39;
# ------------------
# --- Caused by: ---
# Selenium::WebDriver::Error::TimeOutError:
# timed out after 2 seconds (no alert open
# (Session info: headless chrome=61.0.3163.91)
# (Driver info: chromedriver=2.32.498513 (2c63aa53b2c658de596ed550eb5267ec5967b351),platform=Linux 4.4.0-116-generic x86_64))
# ./spec/features/hogehoge.rb:39:in `block (5 levels) in &amp;lt;top (required)&amp;gt;&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;どうやら、ブラウザのconfirmダイアログを確認するところでエラーになっているようです。2秒待ったけどダイアログ出ないよ、という感じかな。&lt;/p&gt;
&lt;p&gt;ローカルではこれらのテストはパスしているので、driverのバージョン違いがありそうです。&lt;/p&gt;
&lt;p&gt;ちなみにchromedriveのバージョンは次の通り。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ローカル→2.37.544337&lt;/li&gt;
&lt;li&gt;CircleCI→2.32.498513&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;バージョンが古いのが怪しいなと思ったのでまずはDockerイメージを変えてみることに。元々2.4系にあげるところだったのもあって、2.3.4→2.4.3とイメージを変更しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;docker&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# before&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# - image: circleci/ruby:2.3.4-node-browsers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# after&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;circleci/ruby:2.4.3-node-browsers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そしたらなんかうまくいくじゃないですか。ということでイメージに入っているchromedriverのバージョンが古そうだという当たりがつきました。&lt;/p&gt;
&lt;p&gt;ですがCIのためだけににRubyのバージョンもあげるのはプロジェクトによっては困るかもしれません。&lt;/p&gt;
&lt;p&gt;chromedriverだけを上げる方法はないものか。CircleCIの設定ファイルでアップデートする方法を探してみます。&lt;/p&gt;
&lt;p&gt;（Dockerのイメージを専用に作れば何にでも対応できるはずなんですが、ちょっと手間がかかりすぎるのでそこまではやめておく方針です。Dockerから調べないといけないので）&lt;/p&gt;
&lt;h2 id="イメージを変えたらgemfileの分岐は不要に"&gt;イメージを変えたらGemfileの分岐は不要に&lt;/h2&gt;
&lt;p&gt;ちなみ、イメージ変更後にGemfileの&lt;code&gt;unless ENV.key?('CIRCLECI')&lt;/code&gt;を外して動かしたら全部通っちゃいました。&lt;/p&gt;
&lt;p&gt;これはたまたまgemのchromedriverとDockerイメージのchromedriverが一致しているだけかもしれませんが、ひとまず不要となりました。&lt;/p&gt;
&lt;h1 id="なんとか234のイメージで動かしたい"&gt;なんとか2.3.4のイメージで動かしたい&lt;/h1&gt;
&lt;h2 id="ローカルで試す"&gt;ローカルで試す&lt;/h2&gt;
&lt;p&gt;CircleCI 2.0からはDockerに対応しているので、わざわざCircleCIにコードをPushしなくてもローカルで動作を確認できます。DockerとCircleCI CLIを入れれば割と簡単に使えるので、設定を色々いじるときはローカルを使うのがいいです。&lt;/p&gt;
&lt;p&gt;手順は公式のこれ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://circleci.com/docs/2.0/local-cli/"&gt;Using the CircleCI Local CLI - CircleCI&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="結果は不発に"&gt;結果は不発に&lt;/h2&gt;
&lt;p&gt;CircleCIのフォーラムとかstackexchangeとかを色々あさってChromeをアップデートする方法を色々試してみました。configを変えては&lt;code&gt;$ circleci build .circleci/config.yml&lt;/code&gt;を何度も走らせる。。。1回15分20分かかるので結構な時間がかかりました。&lt;/p&gt;
&lt;p&gt;で、結局はどれもchromeがcrashするからテストできないというエラーで不発に終わりました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;unknown error: Chrome failed to start: crashed
(Driver info: chromedriver=2.32.498513 (2c63aa53b2c658de596ed550eb5267ec5967b351),platform=Linux 4.9.87-linuxkit-aufs x86_64)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;エラーを見るにchromedriverのバージョンは変わらないですね。なので実は更新ができていないんだと思われます。深追いするには利用しているDockerイメージをローカルで動かして調べてみたりするのかなー。&lt;/p&gt;
&lt;p&gt;僕個人的には2.4.3のイメージを使えば大丈夫だったので深追いはせず一旦は諦めました。&lt;/p&gt;
&lt;p&gt;以下、やってみてだめだったことを一応書いておきます（すべて&lt;code&gt;.circleci/config.yml&lt;/code&gt;に書いて試した内容です）。&lt;/p&gt;
&lt;p&gt;参考にした情報とのセットで記載します。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href="https://superuser.com/questions/130260/how-to-update-google-chrome-in-ubuntu"&gt;https://superuser.com/questions/130260/how-to-update-google-chrome-in-ubuntu&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- &lt;span style="color:#f92672"&gt;run&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Chrome&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;command&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sudo sh -c &amp;#39;echo &amp;#34;deb http://dl.google.com/linux/chrome/deb/ stable main&amp;#34; &amp;gt;&amp;gt; /etc/apt/sources.list.d/google-chrome.list&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sudo apt-get update
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sudo apt-get --only-upgrade install google-chrome-stable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;p&gt;&lt;a href="https://discuss.circleci.com/t/session-not-created-exception-chrome-version-must-be-62-0-3202-0/19258/8"&gt;https://discuss.circleci.com/t/session-not-created-exception-chrome-version-must-be-62-0-3202-0/19258/8
&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- &lt;span style="color:#f92672"&gt;run&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Install Chrome&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;command&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sudo apt-get update
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sudo apt-get install google-chrome-stable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;p&gt;&lt;a href="https://discuss.circleci.com/t/session-not-created-exception-chrome-version-must-be-62-0-3202-0/19258/10"&gt;https://discuss.circleci.com/t/session-not-created-exception-chrome-version-must-be-62-0-3202-0/19258/10&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- &lt;span style="color:#f92672"&gt;run&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Install Chrome&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;command&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sudo dpkg -i google-chrome.deb
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sudo sed -i &amp;#39;s|HERE/chrome\&amp;#34;|HERE/chrome\&amp;#34; --disable-setuid-sandbox|g&amp;#39; /opt/google/chrome/google-chrome
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; rm google-chrome.deb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Hugoで記事内のリンクを新しいタブで開く方法</title><link>https://blog.piyo.tech/posts/2018-03-29-hugo-blackfriday/</link><pubDate>Thu, 29 Mar 2018 19:21:13 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-03-29-hugo-blackfriday/</guid><description>&lt;p&gt;HugoではMarkdownで記事を書いていますが、そのままだと記事内のリンクをクリックしたときに現在のタブで移動してしまいます。&lt;/p&gt;
&lt;p&gt;離脱が！！&lt;/p&gt;
&lt;p&gt;かといってマークダウンの記法にはtarget blankする記法がありませんよね？なのでHugoのドキュメントを当たってみました。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://gohugo.io/getting-started/configuration/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;gohugo.io →&lt;/span&gt;&lt;span&gt;https://gohugo.io/getting-started/configuration/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;調べてみてわかったんですが、Hugoでは内部でGo製の「Blackfriday」というライブラリが使われているみたいです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/russross/blackfriday"&gt;russross/blackfriday: Blackfriday: a markdown processor for Go&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ドキュメントにもConfigure Blackfridayという見出しがあるのでそこに言ってみるといろいろな設定があります。&lt;/p&gt;
&lt;p&gt;その中に&lt;code&gt;hrefTargetBlank&lt;/code&gt;という項目がありました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;default: false
Blackfriday flag: HTML_HREF_TARGET_BLANK
Purpose: true opens external links in a new window or tab.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;まさに欲しかったオプションです。これをHugoのconfig.tomlでtrueにしてあげることでリンクが新しいタブで開くようになりました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[blackfriday]
hrefTargetBlank = true
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;このページのリンクもちゃんと新しいタブで開きますよ。&lt;/p&gt;</description></item><item><title>RailsのFeatureテスト環境をHeadless Chromeに変更した</title><link>https://blog.piyo.tech/posts/2018-03-28-headless-chrome/</link><pubDate>Wed, 28 Mar 2018 18:30:12 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-03-28-headless-chrome/</guid><description>&lt;p&gt;&lt;code&gt;Poltergeist detected another element ...&lt;/code&gt;に対応するために RailsのFeatureテスト環境をHeadless Chromeに置き換えました。&lt;/p&gt;
&lt;p&gt;Capybara + PhantomJSのフィーチャテストでドロップダウンメニューがクリックできないので色々調べてみると、ドロップダウンメニューが画面外に描画されちえるらしいことが判明。&lt;/p&gt;
&lt;p&gt;うろ覚えだけど、ウィンドウサイズを1920x1080とかにして実行してたら、↓のようなクリックできなかったよ、といエラーが出てました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Firing a click at co-ordinates [21xx, 40] failed. Poltergeist detected another element with CSS selector &amp;#39;&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;x座標が画面幅越えてるっていうね。このレイアウト崩れのようなものはPhantomJSに起因するらしいので重い腰をあげてHeadless Chromeに乗り換えました。&lt;/p&gt;
&lt;p&gt;最初に参考にしたのはこちらのSpeeeさんの記事。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="http://tech.speee.jp/entry/2017/06/15/135636" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;tech.speee.jp →&lt;/span&gt;&lt;span&gt;http://tech.speee.jp/entry/2017/06/15/135636&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;さらに細かい点で対応を調べたかったのでさらに詳しいGitLabの記事も見ながら進めました。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://about.gitlab.com/2017/12/19/moving-to-headless-chrome/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;about.gitlab.com →&lt;/span&gt;&lt;span&gt;https://about.gitlab.com/2017/12/19/moving-to-headless-chrome/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="変えてみてどうだったか"&gt;変えてみてどうだったか&lt;/h1&gt;
&lt;p&gt;PhantomJSとHeadless ChromeではCapybaraのドライバーで提供される機能が違うのでそのままでは動かない箇所がある、というのは↑の記事でも書いてある通りです。特にGitLabさんはいろんな工夫をしててすごい。けど僕の場合はそこまですることもないなーということで、同等のテストをするような別の方法に置き換えて回避する作戦でいきました。&lt;/p&gt;
&lt;p&gt;削除ボタンなんかで、「削除してもいいですか？」みたいなconfirmを出している箇所はテストコード側に対応が必要なので面倒でした。一度テストを流してみないと気づかないし。&lt;/p&gt;
&lt;p&gt;ただ、レイアウトがおかしくてクリックできないみたいなことはなくなりました。変なことにはまらなくてよくなったのは快適です！！&lt;/p&gt;</description></item><item><title>ブログのビルド用にGoのサーバーをVPS上で動かした話</title><link>https://blog.piyo.tech/posts/2018-03-27-deploy-go/</link><pubDate>Tue, 27 Mar 2018 18:50:47 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-03-27-deploy-go/</guid><description>&lt;p&gt;先日Hugo + Netlifyでブログを再構築したよという記事を書きました。Amazonのアフィリンクを簡単に置くためにショートコードを使っていて、記事のビルドの際にはAmazonの情報をを取ってくるサーバーが必要になります。&lt;/p&gt;
&lt;p&gt;そのサーバーをインターネットからアクセスできるところに動かしていると書きました。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://blog.piyo.tech/posts/2018-03-20-renewal/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;blog.piyo.tech →&lt;/span&gt;&lt;span&gt;https://blog.piyo.tech/posts/2018-03-20-renewal/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;ローカルで動かしていたWebサーバーをインターネット上に公開する必要がありました&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;のところ。&lt;/p&gt;
&lt;h1 id="サーバー"&gt;サーバー&lt;/h1&gt;
&lt;p&gt;以前もリンクを貼ったこちらのコードを使わせてもらいました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gitlab.com/longkey1/amazon-product-json"&gt;longkey1 / amazon-product-json · GitLab&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Go言語のechoというWebフレームワークが使われていて、URLにASINを含めてリクエストするとAdvertising APIの結果がJSONとして返ってきます。&lt;/p&gt;
&lt;p&gt;ショートコードが生成するHTMLはこのJSONに合わせて作っています。&lt;/p&gt;
&lt;h1 id="デプロイ"&gt;デプロイ&lt;/h1&gt;
&lt;p&gt;Goはほとんど使ったことがないのでよくわかっていないのですが、サーバー上にバイナリを置いてデーモンぽく起動させておいて、元々動いてるNginxで外からのリクエストをこのGoのサーバーに振ってあげればいいだろうなーと想像して適当にデプロイしました。デプロイ先は普段から使っているConohaのVPSです。&lt;/p&gt;
&lt;p&gt;環境構築にはAnsibleを使っています。秘伝のPlaybookに今回のサーバー用の設定を追記してプロビジョニングしました。&lt;/p&gt;
&lt;p&gt;実施したのは&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ファイルの置き場所を作る&lt;/li&gt;
&lt;li&gt;ビルド済のサーバーバイナリをコピーする&lt;/li&gt;
&lt;li&gt;サーバーのconfig.tomlをコピーする（APIキーなどを記載）&lt;/li&gt;
&lt;li&gt;systemd用の定義ファイルを配置&lt;/li&gt;
&lt;li&gt;起動スクリプトを配置&lt;/li&gt;
&lt;li&gt;停止スクリプトを配置&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;です。&lt;/p&gt;
&lt;p&gt;後半3つを軽く説明します。&lt;/p&gt;
&lt;h2 id="systemd-定義ファイル"&gt;systemd 定義ファイル&lt;/h2&gt;
&lt;p&gt;バイナリのコマンドをサービス化するためにsystemdの仕組みを使いました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://ja.wikipedia.org/wiki/Systemd"&gt;Wikipedia&lt;/a&gt;によると、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;systemdはシステム管理デーモン、ライブラリおよびユーティリティの一式であり、管理および設定における中心的プラットフォームとしてLinuxコンピュータオペレーティングシステム用に設計されている。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;だそうです。&lt;/p&gt;
&lt;p&gt;コマンドをサービス化する件に関してはこのリンクが一通り網羅しているので細かいことは省略します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://qiita.com/DQNEO/items/0b5d0bc5d3cf407cb7ff"&gt;Systemdを使ってさくっと自作コマンドをサービス化してみる - Qiita&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今回は起動スクリプト、停止スクリプトをも別途用意したのでその部分に関して書きます。&lt;/p&gt;
&lt;p&gt;まず作った定義ファイルはこちら。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[Unit]
Description=hugoapi
After=syslog.target network.target
[Service]
Type=forking
EnvironmentFile=-/etc/default/hugoapi
WorkingDirectory=/home/user_name/hugoapi
ExecStart=/usr/local/bin/hugoapi-server-start.sh # 起動スクリプト
ExecStop=/usr/local/bin/hugoapi-server-stop.sh # 停止スクリプト
User=root
Group=root
KillMode=none
Restart = always
[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;色々設定がありますが、どうせ自分用だし細かいことは気にせずに動かしてます。&lt;code&gt;ExecStart&lt;/code&gt;や&lt;code&gt;ExecStop&lt;/code&gt;にシェルスクリプトを指定しています。&lt;/p&gt;
&lt;h2 id="起動停止スクリプト"&gt;起動・停止スクリプト&lt;/h2&gt;
&lt;p&gt;↑の定義ファイルに指定しておいたスクリプトはこんな感じになってます。&lt;/p&gt;
&lt;p&gt;まずは起動スクリプト。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt; -d $RUN_DIR &lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; mkdir -p &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;RUN_DIR&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;cd $RUN_DIR
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;./hugoapi_linux_amd64 -c ./config.toml &amp;gt; $LOG 2&amp;gt;$ERROR_LOG &amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;echo $! &amp;gt; &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;PID_FILE&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ワーキングディレクトリに移動してコマンドを起動し、pidファイルをつくります。&lt;/p&gt;
&lt;p&gt;続いて停止スクリプト。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt; -f &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;PID_FILE&lt;span style="color:#e6db74"&gt;}&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; kill -9 &lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;cat &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;PID_FILE&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt; -f &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;PID_FILE&lt;span style="color:#e6db74"&gt;}&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;PID_FILE&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;pidファイルに書いてある番号のプロセスを停止し、pidファイルを削除します。&lt;/p&gt;
&lt;p&gt;これだけなんだけど、systemdの定義ファイルに書くには長いのでスクリプトに分離しました。これを適当な場所に置いて定義ファイルにパスを書いておいたというわけです。&lt;/p&gt;
&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;p&gt;これで無事GoのサーバーをVPS上で動かすことができました。&lt;/p&gt;
&lt;p&gt;Go、なかなかサクッとデプロイできてよかったです。&lt;/p&gt;</description></item><item><title>O/RマッパーからDB触り始めた人にSQL書き方ドリルがおすすめ</title><link>https://blog.piyo.tech/posts/2018-03-25-sql/</link><pubDate>Sun, 25 Mar 2018 22:25:22 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-03-25-sql/</guid><description>&lt;h1 id="tldr"&gt;tl;dr&lt;/h1&gt;
&lt;p&gt;SQL苦手な人にこの本めちゃくちゃオススメです。特に手を動かさないと頭に入らない人向け。
すごく凝ったことはできるようにならないかもしれないけど、少なくともSQLへの苦手意識は払拭されます。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4774180661/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/71krcGTLsKL._SL1000_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;改訂第3版 すらすらと手が動くようになる SQL書き方ドリル (WEB&amp;#43;DB PRESS plus)&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="僕とrdbmsとの関わり"&gt;僕とRDBMSとの関わり&lt;/h1&gt;
&lt;p&gt;↓のような感じの仕事歴で、前半はRDBMSにほとんど接する機会がありませんでした。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;CADっぽいデータを扱うWindows上でMFCアプリケーション（4年）&lt;/li&gt;
&lt;li&gt;簡易なiOSアプリやらWin上の変換プログラムやら、一部Railsやら（3年）&lt;/li&gt;
&lt;li&gt;Rails中心（3年）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Winアプリケーションの頃はデータの保存はバイナリをシリアライズしたりXMLっぽいテキスト形式だったり。基本ファイルへの保存。&lt;/p&gt;
&lt;p&gt;後半になってからRailsを触りだしたのでそこで初めてDBと関わることになりました。Railsには通常ActiveRecordがいるのであまり意識することなくDBを扱えてしまいます。&lt;/p&gt;
&lt;p&gt;サービスの立ち上げがメインの仕事なので、複雑なデータや大量のデータは現れにくいというのがこれまでの個人的な感覚です。大体はActiveRecordの範囲で割となんとかなってしまいます。SQLを学ぼうとしても実感が沸かないという壁があって、なかなか学習を進められませんでした。&lt;/p&gt;
&lt;p&gt;ここが難しいのは、割となんとかなっているという感覚は&lt;strong&gt;知らないからなんとかなっていると思っていただけかもしれない&lt;/strong&gt;ということ。実はもっと効率の良いクエリが書けるとか、そもそももっと良い設計があったとか、そんな場面は多々あったのだと思います。&lt;/p&gt;
&lt;p&gt;最近は開発しているアプリケーションで扱うデータ複雑になってきたこともあり、SQLに苦手意識があることをなんとかしたいなと課題に思っていました。&lt;/p&gt;
&lt;p&gt;ちなみにDB関連ではだいぶ易しいと思われる、&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4798144452/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/71wBt9D4wIL._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;SQL 第2版 ゼロからはじめるデータベース操作 (プログラミング学習シリーズ)&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;を読んだこともありましたが、「うんうんわかったそれで？」という感じで実感は相変わらず伴いません。読めないこともないけど、書けないという感じ。&lt;/p&gt;
&lt;p&gt;という流れから冒頭の本に出会ったわけです。&lt;/p&gt;
&lt;h1 id="どんな本か"&gt;どんな本か&lt;/h1&gt;
&lt;h2 id="ドリル形式"&gt;ドリル形式&lt;/h2&gt;
&lt;p&gt;ドリルと名がつくだけあって、例題に沿って進む形式です。回答用のJAVAアプリケーションが入っていて、問題の解になるSQLを書いてポチッとすると正誤判定をしてくれます。採点が自動なのは便利です。&lt;/p&gt;
&lt;p&gt;逆に言うと、SELECTとは何で〜、みたいな細かい説明はありません。とりあえず書こうぜという感じです。人によりますが、僕はこちらの形式がとても好きです。&lt;/p&gt;
&lt;p&gt;全編を通して共通のデータベースを利用していて、「上司」から降ってくる様々な要望を満たすデータを提出するという仕事を課せられているという設定です。あれこれテーブルをJOINしてGROUP BYして欲しいデータを返してあげるみたいなことを繰り返すので、データの集計に慣れます。&lt;/p&gt;
&lt;h2 id="書き方重視"&gt;書き方重視&lt;/h2&gt;
&lt;p&gt;クエリの書き順を重視しています。書き順を重視することは、イコール、クエリがどのように実行されていくのか、データの固まりがどうなっているかを意識することにつながります。ここを徹底させられるので知らず知らずのうちに書けるようになります。&lt;/p&gt;
&lt;h2 id="脱力系の猫がかわいい"&gt;脱力系の猫がかわいい&lt;/h2&gt;
&lt;p&gt;かわいいです。&lt;/p&gt;
&lt;h1 id="一通り終えて"&gt;一通り終えて&lt;/h1&gt;
&lt;p&gt;多段JOINのあるクエリなどをスラスラ書けるようになったという実感があり、苦手意識は払拭されました。少なくとも読んで理解しようという気が起きるように（ｗ）なりました。&lt;/p&gt;
&lt;p&gt;また、↑にも書きましたが、データの集計に慣れるっていう感覚はSQLを直接書いてみたいとわからない感覚だったな、と思っています。ドリル前は元データと欲しいデータがうまく繋がっていなかったです。&lt;/p&gt;
&lt;p&gt;今後のモデリングやデータベースの設計に明らかに役に立ちそうなので、やってよかったです。3〜4時間もあれば終わるはずなので、時間もかからないし超オススメです。&lt;/p&gt;</description></item><item><title>ブラウザからPATCHメソッドのリクエストが飛ばないときは</title><link>https://blog.piyo.tech/posts/2018-03-24-http-patch/</link><pubDate>Sat, 24 Mar 2018 23:03:19 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-03-24-http-patch/</guid><description>&lt;h1 id="tldr"&gt;tl;dr&lt;/h1&gt;
&lt;p&gt;プロキシサーバーでPATCHがブロックされているかもしれないから、PUTに切り替えたら動いたよ。&lt;/p&gt;
&lt;h1 id="経緯"&gt;経緯&lt;/h1&gt;
&lt;p&gt;仕事で開発しているRailsアプリケーションでのできごとです。あるお客さんの社内のPCのIEから、あるデータを一部修正するするためのボタンが動かない、という連絡をもらいました。ユーザーのステータスを更新する機能のようなものというイメージを持ってもらえたらいいです。&lt;/p&gt;
&lt;p&gt;この機能はボタンを押したらAjax的にリクエストを投げて戻ってきたら画面を更新するということをやっていました。最初はIEを疑いましたが、同様にAjaxな削除ボタンは動くらしくIEのせいではないことがわかりました&lt;/p&gt;
&lt;p&gt;次に調べたのはRails側のログですが、該当のリクエストに相当するログが一切なかったのでサーバーにリクエストが到達していないことがわかりました。&lt;/p&gt;
&lt;p&gt;いくつか似たような機能のうち動かないものを列挙してもらったところ、それらの共通点として全てがPATCHメソッドのリクエストを投げていることがわかりました。&lt;/p&gt;
&lt;p&gt;Railsではリソースのupdateアクションに対応するメソッドはPUTまたはPATCHです。一部更新というような機能の際はPATCHを使うようにしていました。&lt;/p&gt;
&lt;p&gt;この辺の話題は同僚の&lt;a href="https://twitter.com/tkawa"&gt;@tkawaさん&lt;/a&gt;がだいぶ前に書いてくれてます。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="http://d.hatena.ne.jp/tkawa/20120325/p1" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;d.hatena.ne.jp →&lt;/span&gt;&lt;span&gt;http://d.hatena.ne.jp/tkawa/20120325/p1&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;まずは一箇所だけPATCH→PUTと変更してみたところ、該当部分が動くようになったことがわかり、やはりPATCHが原因だったことがわかりました。&lt;/p&gt;
&lt;p&gt;どうやらそのPCは外部へのアクセスが厳し目の設定になっているらしいです。原因が完全にはわかっていないものの、プロキシサーバーあたりが怪しいと推測するに至りました。&lt;/p&gt;
&lt;h1 id="結論"&gt;結論&lt;/h1&gt;
&lt;p&gt;環境によってはPATCHを使わないほうが良い。&lt;/p&gt;</description></item><item><title>Macの文字ビューア（絵文字と記号）を事実上無効にする</title><link>https://blog.piyo.tech/posts/2018-03-23-emoji-symbols/</link><pubDate>Fri, 23 Mar 2018 15:46:13 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-03-23-emoji-symbols/</guid><description>&lt;p&gt;Macでコード書いたりアプリ切り替えたり色々してると、こいつが出る時ないですか？&lt;/p&gt;
&lt;p&gt;&lt;a href="https://goo.gl/WTdB3T"&gt;&lt;img src="https://goo.gl/WTdB3T" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このウィンドウは「Control ＋ Command ＋スペースバー」の同時に押すことで表示されます。
色んなショートカットを駆使している関係で時折誤爆して表示されてしまっているようです。&lt;/p&gt;
&lt;p&gt;表示時にはフォーカスがないため「Command + w」や「Esc」で消すことができず、大変鬱陶しく思っていました。今日いよいよ対策を打ちました。&lt;/p&gt;
&lt;h1 id="そして事実上無効に"&gt;そして事実上無効に&lt;/h1&gt;
&lt;p&gt;このウィンドウの正体は「編集」メニューにある「絵文字と記号」というもので、ほとんどのアプリのメニューにあります。&lt;/p&gt;
&lt;p&gt;これの一番下。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://goo.gl/gDFekh"&gt;&lt;img src="https://goo.gl/gDFekh" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ところでMacには各アプリのメニューにある項目に対してメニュー名とキーの組み合わせでショートカットを指定できる機能があります。&lt;/p&gt;
&lt;p&gt;この「絵文字と記号」メニューに対してもっと別の、頑張らないと押せない組み合わせのショートカットキーを変更することで事実上無効にしてやりました。&lt;/p&gt;
&lt;p&gt;Macの「システム環境設定」から「キーボード」の設定へ移動しショートカットを選びます。続いて左側からアプリケーションを選び、下部の+ボタンを押します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://goo.gl/eVQgKK"&gt;&lt;img src="https://goo.gl/eVQgKK" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;すると次のような入力欄が出るので、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;アプリケーション：全アプリケーション&lt;/li&gt;
&lt;li&gt;メニュータイトル：絵文字と記号&lt;/li&gt;
&lt;li&gt;キーボードショートカット：（押すのが難しい組み合わせ）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;として追加します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://goo.gl/rUhehy"&gt;&lt;img src="https://goo.gl/rUhehy" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これだけだとメニューが英語のアプリケーションに対応できないので、もう1つ設定を追加してメニュータイトルを&lt;code&gt;Emoji &amp;amp; Symbols&lt;/code&gt;としたものも追加しておくとよいです。&lt;/p&gt;
&lt;p&gt;僕は「Control + Shift + F12(fn + 音量↑)」にしました。ファンクションキー系は普段使わないので誤爆することはないだろうなと思います。&lt;/p&gt;</description></item><item><title>GitHub用ブラウザ拡張のOctotreeがプルリク確認にも便利</title><link>https://blog.piyo.tech/posts/2018-03-22-octotree/</link><pubDate>Thu, 22 Mar 2018 15:53:22 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-03-22-octotree/</guid><description>&lt;p&gt;OctotreeはGitHubでソースコードのツリーを表示してくれるブラウザ拡張です。便利ですよね。
ChromeだけじゃなくてFirefox、Safari、なんとOperaにも対応。GitHubだけじゃなくBitbucketも実験的に対応しているらしい。すごい。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/buunguyen/octotree"&gt;buunguyen/octotree: Code tree for GitHub&lt;/a&gt;
&lt;a href="https://chrome.google.com/webstore/detail/octotree/bkhaagjahfmjljalopjnoealnfndnagc?hl=ja"&gt;Octotree - Chrome ウェブストア&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;しばらく気が付かなかったんですが、プルリクの画面だと変更されたファイルがツリーで表示されてるじゃないですか。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/buunguyen/octotree/commit/ef12824860a5672670695edb774e434bdd6fb6a8"&gt;Change option verbiage · buunguyen/octotree@ef12824&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;どうやら半年ちょい前にREADMEが更新されてるので、そのあたりに機能追加されたんだな。&lt;/p&gt;
&lt;h1 id="どんな感じ"&gt;どんな感じ？&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/buunguyen/octotree/pull/488"&gt;Port to Microsoft Edge by Jack-Q · Pull Request #488 · buunguyen/octotree&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;例えば↑のリンクのページを開くとこんな風に追加削除の行数も含めて出てます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lh3.googleusercontent.com/6wwiBL6Y6j0JFNq94RmdnNuHj3XuC_F4ZH5ClJsbHk4xhpN9MIzEDgY_W_l7NQwWtoR4NWp97IaaMA9-QAnqi3sT9E2N82ZzXEiYHvmP-ehQOjMHyEDaB-y5ACKLJTJTP8m1lSGGSftkKMWy1cMnRLO_lBgwSQ_JMg3wdtMHiB8tOY4f4EwbysBTZN2RvxKzTqhxy6wNcg3XlYXuFoq6vy3UKSDLZGMaWS3GBWklxomKD84Ob1N6n-rR1OC0AVKulhqQeM-VLQ7OrnVxwybqaxDQiFDP37eOPufrVotjzaUqQxWdDlMrOJRgljIzZB9JLyTHZhCokyFGBIN_yIuNlYfMg7EMi7Nd7E9rYOkiFjtKVI_XCxHMTMTVZG7dJtz7pDME2iguVoed3U00B2v23RVcu4C8thLVSJpxVHElBcUcuz0GPYHPlG2luk_Ok_tj9Sf5iZSHmdPv36uCAI3M9uVuMm09O0OBb0cawC8sL5OnwCfBuGvEysUwl18blO30oVktTPPZbslUpb3iFptyWO3O8ZqN00lhspddywuFEQJLaMUxcBPktK4PCgvJqbYXNLy5Ca4qtgt1-PH2GVNgMdzcyZdPgsrsdIR2hdr5O1X-t9Lrc9T9ZHZ6dl8V5UXSbCdpln4cqzg7vdLwvmavZ43mkc3Hh-EHDw=w491-h361-no"&gt;&lt;img src="https://lh3.googleusercontent.com/6wwiBL6Y6j0JFNq94RmdnNuHj3XuC_F4ZH5ClJsbHk4xhpN9MIzEDgY_W_l7NQwWtoR4NWp97IaaMA9-QAnqi3sT9E2N82ZzXEiYHvmP-ehQOjMHyEDaB-y5ACKLJTJTP8m1lSGGSftkKMWy1cMnRLO_lBgwSQ_JMg3wdtMHiB8tOY4f4EwbysBTZN2RvxKzTqhxy6wNcg3XlYXuFoq6vy3UKSDLZGMaWS3GBWklxomKD84Ob1N6n-rR1OC0AVKulhqQeM-VLQ7OrnVxwybqaxDQiFDP37eOPufrVotjzaUqQxWdDlMrOJRgljIzZB9JLyTHZhCokyFGBIN_yIuNlYfMg7EMi7Nd7E9rYOkiFjtKVI_XCxHMTMTVZG7dJtz7pDME2iguVoed3U00B2v23RVcu4C8thLVSJpxVHElBcUcuz0GPYHPlG2luk_Ok_tj9Sf5iZSHmdPv36uCAI3M9uVuMm09O0OBb0cawC8sL5OnwCfBuGvEysUwl18blO30oVktTPPZbslUpb3iFptyWO3O8ZqN00lhspddywuFEQJLaMUxcBPktK4PCgvJqbYXNLy5Ca4qtgt1-PH2GVNgMdzcyZdPgsrsdIR2hdr5O1X-t9Lrc9T9ZHZ6dl8V5UXSbCdpln4cqzg7vdLwvmavZ43mkc3Hh-EHDw=w491-h361-no" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これに気がついてからは、個人的にはめちゃくちゃ便利に使っています。&lt;/p&gt;
&lt;p&gt;業務でコードレビューするときに、複数のファイルを追いかけながら詳細を確認したいとき、Octotreeがないと上下にスクロールしなきゃいけません。Octotreeを入れておくと見たい箇所に的確に飛べて、元の場所にも戻りやすくて快適になりました。&lt;/p&gt;</description></item><item><title>Hugo + Netlifyでブログを再構築</title><link>https://blog.piyo.tech/posts/2018-03-20-renewal/</link><pubDate>Wed, 21 Mar 2018 00:37:25 +0900</pubDate><guid>https://blog.piyo.tech/posts/2018-03-20-renewal/</guid><description>&lt;p&gt;2つほど前の記事でRailsで作ったよと書いて早1年。Railsで作った時点で満足し、その間ほとんど新しい投稿をすることもなく過ぎてしまった。心機一転ブログを再開する気持ちになったものの、なんか盛り上がらないなーということでまずは引っ越しからはじめました。&lt;/p&gt;
&lt;p&gt;今までWordpressを自分でホストしたり、ブログサービスを使ってみたり、CMSごと作ったりと色々やってきて、次も違うやり方をしたいなと思いスタティックサイトジェネレータとNetlifyを使うことにします。&lt;/p&gt;
&lt;p&gt;スタティックサイトジェネレータにはGo言語製のHugoを選びました。Rubyのより早そうだし。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gohugo.io/"&gt;The world’s fastest framework for building websites | Hugo&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="データエクスポート"&gt;データエクスポート&lt;/h1&gt;
&lt;h2 id="各記法への対応"&gt;各記法への対応&lt;/h2&gt;
&lt;p&gt;引っ越しということで、過去データがあるのでそれを移行しなきゃいけません。はてなブログ時代のはてな記法が残っているのをなんとかする必要があります。&lt;/p&gt;
&lt;p&gt;例えばこのへん。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Amazonアソシエイト&lt;/li&gt;
&lt;li&gt;Twitter&lt;/li&gt;
&lt;li&gt;ブログカード&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;はてなの記法はすごく便利なんだけど、独自だから移行のときにめんどくさいんですよね。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[asin:XXXXXXXXXXXX:detail]
[https://twitter.com/pi_cha_n/status/835146845626118146:embed]
[http://hogehogehoge.com/:embed:cite]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Rails製のブログでは画面出力のときにマークダウンの本文の中からこの手の記法を正規表現で見つけてはHTMLに置換するというのをやっていました。&lt;/p&gt;
&lt;p&gt;Hugoのマークダウンには素のHTMLを書くこともできます。Railsブログから移行用のデータを出力する際、上の記法をHTMLに変換したうえで出力するというスクリプトを書きました。&lt;/p&gt;
&lt;h2 id="urlが変わらないように"&gt;URLが変わらないように&lt;/h2&gt;
&lt;p&gt;元のRailsブログのURLは&lt;code&gt;host名/posts/{slug}&lt;/code&gt;となっていました。Hugoでもその構造にできそうだったので、pathを維持したまま移行することにできました。&lt;/p&gt;
&lt;p&gt;幸い元の記事のPathには、各記事ごとに持つ文字列（=slug）を使うようにしていたので、それをそのまま記事のファイル名とすることで対応できました。&lt;/p&gt;
&lt;h2 id="スクリプトはこんな感じ"&gt;スクリプトはこんな感じ&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Post&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;all&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;post&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;open(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;post&lt;span style="color:#f92672"&gt;.&lt;/span&gt;slug&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.md&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;f&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; title &lt;span style="color:#f92672"&gt;=&lt;/span&gt; post&lt;span style="color:#f92672"&gt;.&lt;/span&gt;title&lt;span style="color:#f92672"&gt;.&lt;/span&gt;gsub(&lt;span style="color:#e6db74"&gt;/@|:/&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;puts(&lt;span style="color:#e6db74"&gt;&amp;#39;---&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;puts(&lt;span style="color:#e6db74"&gt;&amp;#34;title: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;title&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;puts(&lt;span style="color:#e6db74"&gt;&amp;#34;description: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;title&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;puts(&lt;span style="color:#e6db74"&gt;&amp;#34;tags: [&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;post&lt;span style="color:#f92672"&gt;.&lt;/span&gt;tag_list&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(&lt;span style="color:#e6db74"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;]&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;puts(&lt;span style="color:#e6db74"&gt;&amp;#34;date: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;post&lt;span style="color:#f92672"&gt;.&lt;/span&gt;published_at&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;puts(&lt;span style="color:#e6db74"&gt;&amp;#39;---&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;puts
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 各記法をよしなに変換する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;puts convert(post&lt;span style="color:#f92672"&gt;.&lt;/span&gt;content)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そうするとメタデータ（？）の部分がこのようになります（例）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;title: 快適な目覚めのため、カーテンを自動で開閉する
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;description: 快適な目覚めのため、カーテンを自動で開閉する
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;tags: [生活]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;date: 2017-03-03 22:18:00 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;（あとは内容が続く）
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="続いてコンテンツの変換部分"&gt;続いてコンテンツの変換部分&lt;/h1&gt;
&lt;h2 id="twitter"&gt;Twitter&lt;/h2&gt;
&lt;p&gt;Hugoにはショートコードという仕組みがあります。大体はてな記法のようなものですが、自分で新しくつくることができ、出力されるHTMLも自由に書けるため自由度が高いです。&lt;/p&gt;
&lt;p&gt;この先また移行、となると面倒なんだけどひとまずおいておきましょう。&lt;/p&gt;
&lt;p&gt;例えばTwitterの場合はTweetのIDがあればこんな風に&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;{{&amp;lt; tweet 877500564405444608 &amp;gt;}}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;書くことでHugoのデフォルトの状態でもTweetが展開されます。&lt;/p&gt;
&lt;p&gt;（これ、コードブロックの中に書くと展開されちゃうのが不便だ。。。）&lt;/p&gt;
&lt;h2 id="ブログカード"&gt;ブログカード&lt;/h2&gt;
&lt;p&gt;はてなブログカードはリンクを貼るときにただの文字だけじゃなくて、メタデータや画像込みで表示してくれる機能です。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://lh3.googleusercontent.com/xnyMFO8btwTLFLDN22ub49xbx_kaWryy3tB34d-Ndn3PNvqYGe5R6zwB8pOIq9kgEgLN1y3xggmCv1yXq5XQQYMuYZ-6soK42Jqq71jbK0qtbwfRJRLqKB-NlfSXgXAw-UDtxdxfyUmwTbx4s2Bmnq59-wfniGHs7dziEMIYouTOAZfkHtw12zNRTPnMH3ve6r2CI7ybscp9qeEfFPRtdmBcLnTy6fbBbaoJkrF5kCIcN1x7EEAKXJv3NZSMfVSDhpoeaZuPa0qDAmaLe0fubUzoNIcqJhdgGEft_pDzKWUNHn0CIV1H3O6d-uDawTwxXjrOfh2uBH4mhIj_EplNc9E79wORTGTfm0IIcs3Io2OO_oUcUyigPvWcCsUdbCjwONxolyAiWqpDTJnSxtA-bnOpmzlAT_Fvt8UA9qMAl2GuumMbFIo2l-ksW74l3H7iaV1YHBR2JCKdiOP8-2G4oRTpLnzDtOzqMvOaYf-B6mkG8hO2-ZZGwfjGJ93t3gCSBsh7jxIWFJ1PJdIJsLAcgLGEKQzGZ6H-v6imG2QrFQVz5FYnNoeisdTp8Pu1XeISuBg7KD8btLjNXjfpP8dm-YWMmFOIjR4gLXFM-ay7b9k0SEO-7ZPzrQGh2itSUEsfxiwc3rX7ZNZ6dsjalZkTT6jWkLuNT2Py9w=w882-h337-no"&gt;&lt;figcaption&gt;
&lt;h4&gt;はてなのブログカード&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;画像付、いいですよね。簡易でもいいのでなんとか実現したい。Rails製ブログのときにも使っていたHeartRailsのサービスを使って実現します。↓こんなのですね。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://blog.piyo.tech/posts/blog-with-rails5/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;blog.piyo.tech →&lt;/span&gt;&lt;span&gt;https://blog.piyo.tech/posts/blog-with-rails5/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;ざっくりいうとこんな感じで変換できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;convert&lt;/span&gt;(content)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; screenshot &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;[![](https://capture.heartrails.com/200x150/shadow/border?&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt;&lt;span style="color:#e6db74"&gt;1)](&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt;&lt;span style="color:#e6db74"&gt;1)&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt;&lt;span style="color:#e6db74"&gt;1](&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt;&lt;span style="color:#e6db74"&gt;1)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; content &lt;span style="color:#f92672"&gt;=&lt;/span&gt; content
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;gsub(&lt;span style="color:#e6db74"&gt;/\[(.+):embed:cite\]/&lt;/span&gt;, screenshot)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;gsub(&lt;span style="color:#e6db74"&gt;/\[(.+):embed\]/&lt;/span&gt;, screenshot)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;gsub(&lt;span style="color:#e6db74"&gt;/\[(.+):title\]/&lt;/span&gt;, screenshot)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="amazonアソシエイト"&gt;Amazonアソシエイト&lt;/h2&gt;
&lt;p&gt;Amazonは難しかったです。はてなの場合はasinを書くだけで商品情報を貼り付けることができましたが、あれははてなブログ側でProduct Advertising APIを使って情報を取得してくれているのだと思います。asinだけではAmazonへのリンクを作るのは難しかったはず。&lt;/p&gt;
&lt;p&gt;ということでググってみると、同様の仕組みを実現している方がいました。&lt;/p&gt;
&lt;div class="my-4 border border-dashed border-gray-300 rounded p-3 text-sm"&gt;
&lt;a href="https://blog.longkey1.net/2017/10/01/hugo-amazon-shortcode/" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline break-all"&gt;
&lt;span class="text-gray-500 mr-1"&gt;blog.longkey1.net →&lt;/span&gt;&lt;span&gt;https://blog.longkey1.net/2017/10/01/hugo-amazon-shortcode/&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;簡単にいうと、、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Advertising APIのXMLをJSONに変換して返すWebサーバーをローカルに立てる&lt;/li&gt;
&lt;li&gt;Amazonアソシエイト用のショートコードを用意して、asinを渡す&lt;/li&gt;
&lt;li&gt;ショートコードのHTMLでWebサーバーにリクエストを送る&lt;/li&gt;
&lt;li&gt;戻ってきたJSONの情報を用いてHTMLを組み立てる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;というようなことを行っているようでした。HugoはJSON APIの戻り値をそのまま画面に出せるような仕組みがあります。&lt;/p&gt;
&lt;p&gt;ショートコードやHTMLは自分用に少しいじりましたが、概ねこの方法でやってみました。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;{{&amp;lt; amazon asin=&amp;ldquo;B01ERLNK72&amp;rdquo; &amp;gt;}}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;と書いておくと、↓のように展開されます。すごく良いですね。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B01ERLNK72/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/71R3JmWMAzL._AC_SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;【新しいモデルがあります】めざましカーテン mornin’ (モーニン) 太陽の光でスッキリ目覚める MN-C01 2017年度グッドデザイン賞受賞&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;ですが、このままではNetlifyでデプロイできません&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;JSONのサーバーをローカルで動かしているので、ローカルでビルド→ファイルをそのままコピーという形でのデプロイではうまくいきます。&lt;/p&gt;
&lt;p&gt;しかし、Netlify上でビルドする場合にはNetlify上のビルドプロセスがアクセスできるところにAdvertising APIのJSONを返すサーバーが必要です。&lt;/p&gt;
&lt;p&gt;なのでローカルで動かしていたWebサーバーをインターネット上に公開する必要がありました。この部分を話すと長くなりそうなので後日に回しますが、なんとかWeb上で動かすことができた結果、Netlifyでのビルドも通りました。&lt;/p&gt;
&lt;h3 id="終わりに"&gt;終わりに&lt;/h3&gt;
&lt;p&gt;静的サイトにしたことで閲覧が速くなりました。記事を書くときはローカルのエディタが使えるので、それも便利になった気がします。&lt;/p&gt;
&lt;p&gt;復帰第一弾は引っ越し記事でした。&lt;/p&gt;</description></item><item><title>Rails5で自作したブログに移行しました</title><link>https://blog.piyo.tech/posts/blog-with-rails5/</link><pubDate>Sun, 26 Feb 2017 05:55:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/blog-with-rails5/</guid><description>&lt;p&gt;これまではてなブログに投稿していましたが、最近Rails5で自分用にブログサイトを作って移植しました。なんとなくはてなブログの記事投稿画面の動作がもっさりしていて気に入らなかったとか、たまたま新しいVPSを借りたとか、ドメイン変えてみたかったとかいくつかの複合的な理由があります。&lt;/p&gt;
&lt;p&gt;基本方針としては過去の記事をはてなブログからなんとかMarkdownで出力して（標準ではMovableType形式しかありません）、こちらに移植。それ以降はこちらをメインに運用するイメージです。&lt;/p&gt;
&lt;p&gt;Markdown出力は無理やりコードから行ったのですが、それについてはまたどこかで書きます。&lt;/p&gt;
&lt;h1 id="インフラ"&gt;インフラ&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.conoha.jp/"&gt;Conoha&lt;/a&gt;の一番安いVPSで動かしています。Nginxが動いてて、裏でUnicornが待っています。Conohaを選定した理由は特にないですが、これまで使っていたさくらVPSをセットアップし直したいときに、旧環境を残しつつやりたかったのでこの際違うところを使ってみるかという程度の理由で選びました。&lt;/p&gt;
&lt;p&gt;VPSではこのブログ以外にも個人用の日記や家族用の家計簿などが同時に動いています。メモリが足りなくなる気がします。&lt;/p&gt;
&lt;h1 id="今できていること"&gt;今できていること&lt;/h1&gt;
&lt;p&gt;やりたいと思っていることが残りつつもひとまずブログとしての体をなしたので公開しました。今できているのはこんなところ。&lt;/p&gt;
&lt;h2 id="記事登録更新"&gt;記事登録、更新&lt;/h2&gt;
&lt;p&gt;当たり前ですが、管理画面からできるようになっています。&lt;/p&gt;
&lt;h2 id="メタデータ系の設定"&gt;メタデータ系の設定&lt;/h2&gt;
&lt;p&gt;タイトルやディスクリプションなどは管理画面から変更できるようにしています。&lt;/p&gt;
&lt;h2 id="markdown"&gt;Markdown&lt;/h2&gt;
&lt;p&gt;本文はMarkdown記法に対応しました。&lt;/p&gt;
&lt;p&gt;ソースコードのシンタックスハイライトも使えるし、他にも、持ってくる予定のはてなブログの記事中には通常のMarkdownだけではなくはてなブログの一部の記法が残っていたので、それらがきちんとHTMLになるような対応などもしてあります。&lt;/p&gt;
&lt;p&gt;また、こんな風にプレビューしつつ投稿できるような工夫をしています。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://gyazo.com/296d0f6b6ad53152944799cccaa762ce.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Markdown対応の部分は長くなるので別記事にでもしようかな。&lt;/p&gt;
&lt;h2 id="記事のタグ付け"&gt;記事のタグ付け&lt;/h2&gt;
&lt;p&gt;はてなブログで使っていたカテゴリをそのまま活かすために &lt;a href="https://github.com/mbleigh/acts-as-taggable-on"&gt;mbleigh/acts-as-taggable-on&lt;/a&gt; gemを使ってタグ機能を用意しました。&lt;/p&gt;
&lt;p&gt;タグの入力部分は &lt;a href="https://select2.github.io/"&gt;Select2&lt;/a&gt; を使用していい感じにしています。&lt;/p&gt;
&lt;h2 id="sitemapxml"&gt;sitemap.xml&lt;/h2&gt;
&lt;p&gt;検索エンジンに登録するsitemap.xmlは &lt;a href="https://github.com/kjvarga/sitemap_generator"&gt;kjvarga/sitemap_generator&lt;/a&gt; gemを使用してアップデートするようにしています。&lt;/p&gt;
&lt;h2 id="snsボタン"&gt;SNSボタン&lt;/h2&gt;
&lt;p&gt;この辺のボタンです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://gyazo.com/222c991a03ebb5b1668dcd415404ef47.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;各サービス側で用意されているボタンはTurbolinks5のせいかjavascriptがうまく読まれずきちんと出せませんでした。ちゃんと解決したいところですが、ひとまず各機能を満たすURLがそれぞれ用意されていたので、そちらへのリンクで済ませるというサボりにしました。&lt;/p&gt;
&lt;p&gt;それぞれこんな感じのURLでいけます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;はてなブックマーク &lt;a href="http://b.hatena.ne.jp/entry/s/#%7B"&gt;http://b.hatena.ne.jp/entry/s/#{&lt;/a&gt;記事host_name}/#{記事path}&lt;/li&gt;
&lt;li&gt;Facebook &lt;a href="https://facebook.com/sharer/sharer.php?u=#%7B"&gt;https://facebook.com/sharer/sharer.php?u=#{&lt;/a&gt;記事URL}&lt;/li&gt;
&lt;li&gt;Twitter &lt;a href="https://twitter.com/intent/tweet/?text=#%7B"&gt;https://twitter.com/intent/tweet/?text=#{&lt;/a&gt;記事タイトル}&amp;amp;url=#{記事URL}&amp;amp;via=pi_cha_n&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="リンクの埋め込み"&gt;リンクの埋め込み&lt;/h2&gt;
&lt;p&gt;Markdownのところでもちらっと書いた、はてな記法に対応したうちの1つがリンクの埋め込みです。はてなブログではURLを貼り付けるとカード形式で埋め込むことができます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[![](https://capture.heartrails.com/200x150/shadow/border?記事URL)](記事URL) [記事URL](記事URL)&lt;/code&gt;などと書くとこんな感じになる機能です。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://gyazo.com/3b10684872e94d5e1c07eab16b9601f5.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;これをそのまま再現するのは難しかったのでスクリーンショットとURLを載せることでひとまずよしとしました。&lt;/p&gt;
&lt;p&gt;スクリーンショットはHeartRailsさんのこちらを使用しています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://capture.heartrails.com/"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?https://capture.heartrails.com/" alt=""&gt;&lt;/a&gt;
&lt;a href="http://capture.heartrails.com/"&gt;http://capture.heartrails.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ほら、こんな感じにキャプチャが出てまずまずな感じになるかと。&lt;/p&gt;
&lt;h2 id="twitterの埋め込み"&gt;Twitterの埋め込み&lt;/h2&gt;
&lt;p&gt;Twitterの埋め込みもはてなブログで対応されていたものです。この記法も過去の記事で使っていたので対応しておきました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/pi_cha_n/status/835146845626118146"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?https://twitter.com/pi_cha_n/status/835146845626118146" alt=""&gt;&lt;/a&gt;
&lt;a href="https://twitter.com/pi_cha_n/status/835146845626118146"&gt;https://twitter.com/pi_cha_n/status/835146845626118146&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="まだできていないこと"&gt;まだできていないこと&lt;/h1&gt;
&lt;h2 id="タグごとのページ"&gt;タグごとのページ&lt;/h2&gt;
&lt;p&gt;タグを押したらそのタグに関する一覧記事に飛べるといいのですが、まだできていません。&lt;/p&gt;
&lt;p&gt;タグ周りでいうと、タグクラウド的なものもおいてみてもいいかな？どうかな。と思っています。&lt;/p&gt;
&lt;h2 id="rssフィード"&gt;RSSフィード&lt;/h2&gt;
&lt;p&gt;一応需要がありそうなので生成できるようにしておくつもりです。&lt;/p&gt;
&lt;h2 id="下書き機能"&gt;下書き機能&lt;/h2&gt;
&lt;p&gt;はてなブログの投稿周りに不満があって作った、という背景もあるので、下書きがないと結構不便な気がしています。今は別のMarkdownエディターで書いてから貼り付けています。&lt;/p&gt;
&lt;h2 id="amp対応"&gt;AMP対応&lt;/h2&gt;
&lt;p&gt;そろそろ触っておこうかなという程度の理由ですが、対応しようと思っています。&lt;/p&gt;
&lt;h2 id="デザイン"&gt;デザイン&lt;/h2&gt;
&lt;p&gt;かっちょよくしたいです。今はbootstrap4を使ってあとはそれなりにしか整えていません。&lt;/p&gt;
&lt;h2 id="関連記事"&gt;関連記事&lt;/h2&gt;
&lt;p&gt;いい感じに自動で出せたらいいな。&lt;/p&gt;
&lt;p&gt;それではー &lt;a href="https://twitter.com/pi_cha_n"&gt;@pi_cha_n&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Rails5でnamespace以下のxxx_root_pathヘルパーが定義されなかったので回避した</title><link>https://blog.piyo.tech/posts/2016-09-27-203000/</link><pubDate>Tue, 27 Sep 2016 20:30:08 +0900</pubDate><guid>https://blog.piyo.tech/posts/2016-09-27-203000/</guid><description>&lt;p&gt;Rails 5.0.0.1を使って開発中、Rails4のころのように&lt;code&gt;routes.rb&lt;/code&gt;に書いたものが思ったように動かなかったのでメモしておきます。&lt;/p&gt;
&lt;p&gt;以下のような&lt;code&gt;routes.rb&lt;/code&gt;を書いて、ただのルート（&lt;code&gt;/&lt;/code&gt;）とadmin配下のルート（&lt;code&gt;/admin/&lt;/code&gt;）を定義します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;.&lt;/span&gt;routes&lt;span style="color:#f92672"&gt;.&lt;/span&gt;draw &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; root &lt;span style="color:#e6db74"&gt;&amp;#39;home#index&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; namespace &lt;span style="color:#e6db74"&gt;:admin&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; root &lt;span style="color:#e6db74"&gt;&amp;#39;home#index&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そうするとViewではroot_pathやadmin_root_pathといったヘルパーメソッドが使えるはずですが、rake routesなり、Routing Errorのページなりで定義済のURLを一覧してみると、、&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/x/xoyip/20160927/20160927140002.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;このように admin_root_pathがありません。Viewで呼ぶとエラーとなります。&lt;/p&gt;
&lt;p&gt;この辺の処理をしているのはactionpack内のActionDispatchあたりです。少し中を追いかけてみたのですが、admin_root_pathのときに想定しているところを通っていないことはわかったものの、根本的な原因を突き止めるには時間がかかりそうだったのでやめて回避策に逃げました。&lt;/p&gt;
&lt;p&gt;要はそのrouteの名前が付けばいいので、admin配下のrootところに&lt;code&gt;as: :root&lt;/code&gt;と書いてあげればOK。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;namespace &lt;span style="color:#e6db74"&gt;:admin&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; root &lt;span style="color:#e6db74"&gt;&amp;#39;home#index&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;as&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:root&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでadmin_root_pathが使えるようになりました。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/x/xoyip/20160927/20160927140016.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>Hello, RxSwift</title><link>https://blog.piyo.tech/posts/2016-08-22-232902/</link><pubDate>Mon, 22 Aug 2016 23:29:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2016-08-22-232902/</guid><description>&lt;p&gt;2016/08/20に開催されたiOSDCに参加してきた。浜松市からの移動なので前日はソニックガーデンの自由が丘ワークプレイスに宿泊しての参加。自由が丘→練馬は乗り換え無しで行ける奇跡の立地。楽しく参加できた。スタッフも大勢いた。開催ありがとうございました。&lt;/p&gt;
&lt;p&gt;色々感想があるのでそれは別途書くかもしれない。今日は色々聞いた中でもishkawaさんのRxSwiftの発表を見てRxSwiftに興味を持ったことと、会場で質問もさせてもらったのでその部分を試しがてらちょっと検証してみようと思ったので半年ぶりぐらいに投稿する。&lt;/p&gt;
&lt;p&gt;今回は発表スライドにもあった例を使ってみることにする。複数のテキストフィールドとボタンがあって、ボタンを押したら2つのフィールドの値を結合してラベルに表示するというもの。&lt;/p&gt;
&lt;p&gt;[http://blog.ishkawa.org/talks/2016-08-20-iosdc/#/19]&lt;/p&gt;
&lt;p&gt;まずはこの例をそのまま実装することにした。なお、今回はRxSwift 2.6.0を使用した。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UIKit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RxSwift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RxCocoa&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ViewController&lt;/span&gt;: UIViewController {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBOutlet&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; textField1: UITextField!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBOutlet&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; textField2: UITextField!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBOutlet&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; label: UILabel!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBOutlet&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; button: UIButton!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; disposeBag = DisposeBag()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.viewDidLoad()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; Observable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; .combineLatest(textField1.rx_text, textField2.rx_text) { &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;$0&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;$1&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; .sample(button.rx_tap)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; .bindTo(label.rx_text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; .addDisposableTo(disposeBag)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;動かしてみるともちろん想定した通りに動く。&lt;/p&gt;
&lt;p&gt;このようなコードのときに、「combineLatestに渡すclosureはUITextFiledのテキストが変わる度に毎に呼ばれてしまうのでパフォーマンス的によろしくないこともありますよね？」という点を質問した。それに対するishkawaさんの回答はざっくり要約すると「多分毎回呼ばれるのでそういうこともあるでしょう、でもRxSwiftで制限する仕組みもあるはずです」という感じだった。&lt;/p&gt;
&lt;p&gt;ということで2点を試してみようと思う。&lt;/p&gt;
&lt;p&gt;まずはクロージャはテキスト変更の度に毎回呼ばれるか、という点。適当にprintして試したところ、次のようになった。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gyazo.com/b7a0dafa9b66392e3c62fb589d4a560c"&gt;&lt;img src="https://i.gyazo.com/b7a0dafa9b66392e3c62fb589d4a560c.gif" alt="https://gyazo.com/b7a0dafa9b66392e3c62fb589d4a560c"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;やはりクロージャは都度呼ばれているようだ。なのでこの部分で少々重たい処理をしてしまうと操作する人にはもたつくような印象を与えてしまうことになる。&lt;/p&gt;
&lt;p&gt;なので次にここを改善する方法を考えてみる。&lt;code&gt;combineLatest&lt;/code&gt;したストリームを&lt;code&gt;sample&lt;/code&gt;することで最新の1つを使うことにしているところの順序を逆にすることで、テキスト変更の度に&lt;code&gt;combineLatest&lt;/code&gt;のクロージャが呼ばれることがないので、もう少しマシなのかもしれない。つまり、テキストフィールドの更新を&lt;code&gt;sample&lt;/code&gt;して、それらを&lt;code&gt;combineLatest&lt;/code&gt;するといった感じか。&lt;/p&gt;
&lt;p&gt;コードにすると、こう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; field1 = textField1.rx_text.sample(button.rx_tap)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; field2 = textField2.rx_text.sample(button.rx_tap)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;Observable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; .combineLatest(field1, field2) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;called&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;$0&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;$1&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; .bindTo(label.rx_text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt; .addDisposableTo(disposeBag)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これなら&lt;code&gt;print(&amp;quot;called&amp;quot;)&lt;/code&gt;のところはボタンをタップしたときにしか呼ばれない。あまり意味のあるサンプルコードではないので適切かどうかもよくわからないが、一応呼ばれる回数は減らせた。&lt;/p&gt;
&lt;p&gt;他にも&lt;code&gt;throttle&lt;/code&gt;や&lt;code&gt;debounce（throttleの別名）&lt;/code&gt;など一定時間内のものを無視するようなオペレーターも存在するけど、今回の例はボタンをタップするその直前に届いているイベントが欲しいので時間で制御するのは適さない。他の要件なら時間制御も良さそうだ。&lt;/p&gt;
&lt;p&gt;こういったオペレーターには色々あって、↓のドキュメントに一覧があるので困ったときは読んでみたいと思っている。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://reactivex.io/documentation/operators.html"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?http://reactivex.io/documentation/operators.html" alt=""&gt;&lt;/a&gt;
&lt;a href="http://reactivex.io/documentation/operators.html"&gt;http://reactivex.io/documentation/operators.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;というわけで、RxSwiftの世界へ一歩足を踏み入れた話でした。&lt;/p&gt;</description></item><item><title>Macでアプリが起動しないときはコンソール.appを見るとわかるかも</title><link>https://blog.piyo.tech/posts/2016-02-19-085950/</link><pubDate>Fri, 19 Feb 2016 08:59:50 +0900</pubDate><guid>https://blog.piyo.tech/posts/2016-02-19-085950/</guid><description>&lt;p&gt;先日、仕事中ヘビーに使っている常駐アプリ達が立ち上がらない現象に遭遇した。とても困ったので一旦仕事の手を止めて復旧努めることにした。&lt;/p&gt;
&lt;p&gt;といっても起動時に何かエラーがでるわけでもなんでもなくて、普段使っているランチャーAlfredから起動しようとしても何の音沙汰もなく、最初は途方にくれていた。
一旦落ち着いて、じゃあログでも見るかと思い立ったがログを見る方法がわからない。&lt;/p&gt;
&lt;p&gt;しばらく調べてコンソール.appで見られるよという記述にあたったことでコンソールの存在を思い出し、ログを確認できた。&lt;/p&gt;
&lt;p&gt;コンソール.appはアプリケーション→ユーティリティの中にある。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA_e5tw4_uJMlpwpxYBSTT4YwnukLEXZUZoB/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;コンソールを起動すると色々なシステムログが流れていることがわかる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA9mkKAacFtL26c0sg-1vJNhwScVXxLAx_wB/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;僕の場合は起動しないアプリを起動しようとしたときに右側のエリアに新しいログが現れた。
どのアプリで試しても同じようなエラー &lt;code&gt;Service exited with abnormal code: 173&lt;/code&gt; が出るのできっと同じ理由なんだろうなということがわかった。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA99VwKTentLJKK3Af4szxnpSlld9RvSZQEB/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;では、ということでこのエラーメッセージで検索して調べてみたものの、これといった答えがない。
クリーンインストールで直ったよ！っていう人もいたけれど、それはちょっとね。&lt;/p&gt;
&lt;p&gt;いろいろ探す中で「AppStoreの何かが期限切れでうんぬん」と言っている人がいた（英語だったし、サイトを忘れたのでうろ覚えです）。&lt;/p&gt;
&lt;p&gt;起動しないアプリたちをよく見てみると、こいつらもAppStore経由でインストールしているアプリ達だということがわかったので
とりあえず再インストールだろ、とやってみたら見事解決。&lt;/p&gt;
&lt;p&gt;ということでした。&lt;/p&gt;
&lt;p&gt;一応コンソール.appに助けられたというわけ。何もエラーが出てなかったらコンソールを使ってみたらどうでしょうか。&lt;/p&gt;</description></item><item><title>Railsなどで無料から使えるエラー通知サービス Rollbar</title><link>https://blog.piyo.tech/posts/2016-02-03-210000/</link><pubDate>Wed, 03 Feb 2016 21:00:42 +0900</pubDate><guid>https://blog.piyo.tech/posts/2016-02-03-210000/</guid><description>&lt;p&gt;Railsなりスマホなりでアプリケーション作ったらAirbrakeとかBugsnagとかのエラーハンドリング用のサービスを使って不具合を検知できるようにするよね。&lt;/p&gt;
&lt;p&gt;この手のサービスはやはり有料のところが多くて、個人用のアプリケーションとしてはコスト的に使いにくい。無料で使えるものでerrbitというairbrakeクローンみたいなものもあるんだけれど、自分でホストするのはそれはそれで面倒なので敬遠してました。&lt;/p&gt;
&lt;p&gt;でも先日、自分のRailsアプリでエラーがでてついにログを見るのが面倒になって本気出して探したら無料で使えるのがありました。&lt;/p&gt;
&lt;p&gt;それがこのサービス、Rollbar。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://rollbar.com/"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?https://rollbar.com/" alt=""&gt;&lt;/a&gt;
&lt;a href="https://rollbar.com/"&gt;https://rollbar.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ざっと導入した感じ、十分使えるなという感じがしています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GitHubログインができる&lt;/li&gt;
&lt;li&gt;主要なプラットフォームに対応（RailsとかiOSとか、色々ある）&lt;/li&gt;
&lt;li&gt;deployやslack連携とかもできる（らしい）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA_nOIZsKzRCNb_bFXqrFGV_jloiU0PxW7gB/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ユーザー登録やプロジェクト作成、Railsへの導入とかは書くまでもないぐらいめちゃくちゃ簡単だったので省略します。&lt;/p&gt;
&lt;p&gt;ダッシュボードはこんな感じ。洗練されているとは言えないけど、十分！&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA_df3YxcLtBtr2sPqA7B7d3GjTaq5Ipu6cB/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;無料版の制約は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;月5000イベント&lt;/li&gt;
&lt;li&gt;データ保存は30日間&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;なので、個人使用なら全然問題なさそう。&lt;/p&gt;
&lt;p&gt;お試しください。&lt;/p&gt;</description></item><item><title>RailsアプリにiOSクライアントをサッと作る</title><link>https://blog.piyo.tech/posts/2015-12-06-000000/</link><pubDate>Sun, 06 Dec 2015 09:13:22 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-12-06-000000/</guid><description>&lt;p&gt;&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/x/xoyip/20151205/20151205223720.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;この記事は&lt;a href="http://www.adventar.org/calendars/855"&gt;ソニックガーデン Advent Calendar 2015 &lt;/a&gt;、6日目の記事です。&lt;/p&gt;
&lt;p&gt;どうも大野（@pi_cha_n）です。3日目に続いて登場させてもらいます。今日は5日目までとは少し変わって技術的なHow Toの話で、自分用の覚書でもあります。&lt;/p&gt;
&lt;p&gt;ちなみに3日目のはこれ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2015-12-03-083000"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?https://blog.piyo.tech/posts/2015-12-03-083000" alt=""&gt;&lt;/a&gt;
&lt;a href="https://blog.piyo.tech/posts/2015-12-03-083000"&gt;https://blog.piyo.tech/posts/2015-12-03-083000&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ソニックガーデンではお客さまが実現したいサービスを開発するのにRuby on Railsを使っています。PCやスマートフォンのブラウザから利用されるようなサービスを作ってきました。&lt;/p&gt;
&lt;p&gt;ところが最近のスマートフォン普及率などから、スマートフォンのネイティブアプリケーションを用意してユーザーに使ってもらいたいというお客さまのご要望も増えてきています。社内でも開発や運用についてどうしていくかの議論が盛んになってきています。&lt;/p&gt;
&lt;p&gt;そういう流れから今日はすでに運用しているRailsアプリケーションにiOSクライアントを作るには、という話をサンプルコードで簡単に紹介できればと思います。&lt;/p&gt;
&lt;h1 id="今回の事例"&gt;今回の事例&lt;/h1&gt;
&lt;p&gt;「Facebookログインを利用した既存のWebサイト（Rails）用のiOSクライアントを作りたい」というケースを考えてみます。&lt;/p&gt;
&lt;p&gt;やらなければならないことは&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Railsにスマートフォン用の認証口を用意すること&lt;/li&gt;
&lt;li&gt;Railsと連携するiOSクライアントを作ること&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;この2つです。&lt;/p&gt;
&lt;p&gt;またサンプルコードをGitHubに用意したので、RubyやXcodeがあれば実際に動かすことができます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/integration-sample-rails"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?https://github.com/pi-chan/integration-sample-rails" alt=""&gt;&lt;/a&gt;
&lt;a href="https://github.com/pi-chan/integration-sample-rails"&gt;https://github.com/pi-chan/integration-sample-rails&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/integration-sample-ios"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?https://github.com/pi-chan/integration-sample-ios" alt=""&gt;&lt;/a&gt;
&lt;a href="https://github.com/pi-chan/integration-sample-ios"&gt;https://github.com/pi-chan/integration-sample-ios&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="railsにスマートフォン用の認証口を用意する"&gt;Railsにスマートフォン用の認証口を用意する&lt;/h1&gt;
&lt;h2 id="doorkeeperの導入"&gt;doorkeeperの導入&lt;/h2&gt;
&lt;p&gt;まずは外部のクライアントが認証できる仕組みをRails側に用意します。doorkeeperというgemを使うと、超簡単にOAuthプロバイダーの機能をRailsアプリケーションに追加できます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/doorkeeper-gem/doorkeeper"&gt;https://github.com/doorkeeper-gem/doorkeeper&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;既存のRailsアプリケーションに対して次のステップを実施すれば簡単に導入可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ gem &lt;span style="color:#e6db74"&gt;&amp;#39;doorkeeper&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ bundle
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ rails generate doorkeeper:install
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;$ rails generate doorkeeper:migration
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;$ rake db:migrate
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとは&lt;code&gt;routes.rb&lt;/code&gt;に追記すれば大体おわり。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# config/routes.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;.&lt;/span&gt;routes&lt;span style="color:#f92672"&gt;.&lt;/span&gt;draw &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 他のroutes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; use_doorkeeper
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;※設定は上のステップで生成された&lt;code&gt;config/initializers/doorkeeper.rb&lt;/code&gt;で。色々あるので説明は省略！&lt;/p&gt;
&lt;h2 id="oauth-applicationの作成"&gt;OAuth Applicationの作成&lt;/h2&gt;
&lt;p&gt;先ほどのセットアップがうまくいっていれば&lt;code&gt;/oauth/applications&lt;/code&gt;にアクセスして次のような画面を開くことができるようになります。この画面から新しいアプリケーションを作成していきます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/x/xoyip/20151205/20151205223259.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;必要なパラメータを入れます。名前は識別できればなんでもよくて、&lt;code&gt;リダイレクトURI&lt;/code&gt;にはiOS側で設定するものと同じものを入れます。今回は&lt;code&gt;integration-sample-ios://oauth-callback/ios&lt;/code&gt;を使うことにしました（スキーマ以外が合っていれば、path
などは必要に応じて変えればよいです）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;追記&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;development環境以外ではURLスキームがhttpsでないとエラーとなります。それを回避するためには&lt;code&gt;config/initializers/doorkeeper.rb&lt;/code&gt;で&lt;code&gt;force_ssl_in_redirect_uri false&lt;/code&gt;としておけば良いです。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;追記おわり&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/x/xoyip/20151205/20151205223308.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;作成するとアプリケーションIDやトークンが発行されます。iOS側で使うので控えておきます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/x/xoyip/20151205/20151205223320.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="apiを用意する"&gt;APIを用意する&lt;/h2&gt;
&lt;p&gt;Railsアプリケーション側にJSON APIがなければ作っておきます。今回はiOSからログインできていることを確認するために、ログインしているユーザーの名前やメールアドレスを返すAPIを用意します。&lt;/p&gt;
&lt;p&gt;まずAPI用の&lt;code&gt;ApplicationController&lt;/code&gt;的なものを用意します。&lt;/p&gt;
&lt;p&gt;API用のコントローラの全てのアクションで&lt;code&gt;doorkeeper_authorize!&lt;/code&gt;で認証をかけて、ヘルパーメソッド&lt;code&gt;current_user&lt;/code&gt;で認証したユーザーを得られるようにしておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# app/controllers/api/api_controller.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Api&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;ApiController&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ApplicationController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; before_action &lt;span style="color:#e6db74"&gt;:doorkeeper_authorize!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; helper_method &lt;span style="color:#e6db74"&gt;:current_user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;current_user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;User&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find(doorkeeper_token&lt;span style="color:#f92672"&gt;.&lt;/span&gt;resource_owner_id) &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; doorkeeper_token
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最後に、名前とメールアドレスを返すAPIを定義します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# app/controllers/api/users_controller.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Api&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;UsersController&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Api&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;ApiController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;show&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; @user &lt;span style="color:#f92672"&gt;=&lt;/span&gt; current_user
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# app/views/api/users/show.json.jbuilder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;json&lt;span style="color:#f92672"&gt;.&lt;/span&gt;extract!(@user, &lt;span style="color:#e6db74"&gt;:id&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:name&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:email&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これをiOSから呼び出せれば連携成功！となるわけです。&lt;/p&gt;
&lt;h1 id="iosクライアントを作る"&gt;iOSクライアントを作る&lt;/h1&gt;
&lt;p&gt;iOSアプリでは起動時にログイン済みかどうかを判定し、ログイン済みであればAPIを叩いて自分の情報を表示、そうでなければログイン画面を表示という流れになるようなものを作ります。&lt;/p&gt;
&lt;h2 id="pod-install"&gt;pod install&lt;/h2&gt;
&lt;p&gt;ライブラリをいくつか使うのでそれらをインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Podfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;source &lt;span style="color:#e6db74"&gt;&amp;#39;https://github.com/CocoaPods/Specs.git&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;platform &lt;span style="color:#e6db74"&gt;:ios&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;9.0&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;use_frameworks!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;Alamofire&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;gt;= 2.0&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# APIを呼ぶときに&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;SwiftyJSON&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;gt;= 2.3&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# APIのレスポンスの処理に&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;p2.OAuth2&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;~&amp;gt; 2.0.0&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# OAuth2の認証に&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;KeychainAccess&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# トークンの保存に&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;※iOS9からhttpの通信で叱られるようになります。それだと開発中に困るのでApp Transport Securityの設定でhttpを許すドメインを指定してあげたほうが便利です。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://mushikago.com/i/?p=6150"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?http://mushikago.com/i/?p=6150" alt=""&gt;&lt;/a&gt;
&lt;a href="http://mushikago.com/i/?p=6150"&gt;http://mushikago.com/i/?p=6150&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;※p2.OAuth2ライブラリ内のコードに、開こうとしているURLがhttpのときはassertで止まるような記述があります。あまりよろしくないですが開発中はコメントアウトしています。&lt;/p&gt;
&lt;h2 id="urlスキームを設定する"&gt;URLスキームを設定する&lt;/h2&gt;
&lt;p&gt;p2.OAuth2を使った認証の流れですが、&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;doorkeeperで取得したIDやトークンを設定する&lt;/li&gt;
&lt;li&gt;SafariまたはSafariViewを開いてログインを求める&lt;/li&gt;
&lt;li&gt;URLスキームを使ってアプリに戻る&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;といった感じになっています。doorkeeperで設定したリダイレクトURIは認証後にアプリに戻るために使われます。&lt;/p&gt;
&lt;p&gt;URLスキームの設定方法はこんな感じ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/x/xoyip/20151205/20151205223345.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="認証する"&gt;認証する&lt;/h2&gt;
&lt;p&gt;認証のところのコード（全体像はサンプルコードを見てもらったほうがよいと思います）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; oauth2 : OAuth2CodeGrant?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; settings = [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;client_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;YOUR_APP_ID&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;client_secret&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;YOUR_APP_SECRET&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;authorize_uri&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;YOUR_SERVER_URL&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/oauth/authorize&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;token_uri&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;YOUR_SERVER_URL&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/oauth/token&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;scope&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;redirect_uris&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;integration-sample-ios://oauth-callback/ios&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;keychain&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;] &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; OAuth2JSON
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// OAuthアプリケーションのトークンなどを使って認証用のオブジェクトを生成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;oauth2 = OAuth2CodeGrant(settings: settings)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// アプリ内に埋め込みでSafariViewを出す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;oauth2?.authConfig.authorizeEmbedded = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 成功時&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;oauth2?.onAuthorize = { parameters &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; json = JSON(parameters)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// トークンを保存&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; keychain = KeychainAccess.Keychain(service: &lt;span style="color:#e6db74"&gt;&amp;#34;YOUR_BUNDLE_ID&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt;! keychain.&lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;(json[&lt;span style="color:#e6db74"&gt;&amp;#34;access_token&amp;#34;&lt;/span&gt;].stringValue, key: &lt;span style="color:#e6db74"&gt;&amp;#34;access_token&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 失敗時&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;oauth2?.onFailure = { error &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; print(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そして最初のビューが表示されたタイミングで、ここで生成した&lt;code&gt;oauth2&lt;/code&gt;オブジェクトを使ってログイン画面を表示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;viewDidAppear&lt;/span&gt;(animated: Bool) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.viewDidAppear(animated)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; keychain = KeychainAccess.Keychain(service: &lt;span style="color:#e6db74"&gt;&amp;#34;YOUR_BUNDLE_ID&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// トークンが保存されているかどうかでログイン済みかどうかを判定する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; accessToken = &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt;! keychain.&lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;access_token&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// APIを呼ぶ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// contextとして自身（UIViewController)を指定する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; Auth.sharedInstance.oauth2?.authConfig.authorizeContext = &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ログイン画面を出す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; Auth.sharedInstance.oauth2?.authorize()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最後に、認証完了後、URLスキームでアプリに戻ってきたことを&lt;code&gt;oauth2&lt;/code&gt;オブジェクトに教えてあげることで成功時のコールバック&lt;code&gt;onAuthorize&lt;/code&gt;が呼ばれます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AppDelegate.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;application&lt;/span&gt;(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -&amp;gt; Bool {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; path = url.path {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; path.hasPrefix(&lt;span style="color:#e6db74"&gt;&amp;#34;/ios&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; Auth.sharedInstance.oauth2?.handleRedirectURL(url)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;なお今回は&lt;code&gt;oauth2&lt;/code&gt;オブジェクトを各所から参照するためにシングルトンを用いています。&lt;/p&gt;
&lt;h2 id="apiを使う"&gt;APIを使う&lt;/h2&gt;
&lt;p&gt;ここまでくれば、あとは取得したトークンでAPI呼び出しをするだけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;ApiClient.sharedInstance.&lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;/user&amp;#34;&lt;/span&gt;, parameters: [:], onSuccess: { json &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; alertController = UIAlertController(title: &lt;span style="color:#e6db74"&gt;&amp;#34;ログイン成功&amp;#34;&lt;/span&gt;, message: &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;json[&lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;]&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;としてログインしました&amp;#34;&lt;/span&gt;, preferredStyle: .Alert)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; defaultAction = UIAlertAction(title: &lt;span style="color:#e6db74"&gt;&amp;#34;OK&amp;#34;&lt;/span&gt;, style: .Default, handler: &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; alertController.addAction(defaultAction)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.presentViewController(alertController, animated: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;, completion: &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}, onFailure: { error &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; print(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;jsonにはRailsが返したid、名前、メールアドレスが入っています。アラートで表示（手抜き）してきちんと取得できるのが確認できるはずです。&lt;/p&gt;
&lt;p&gt;ちなみにAPIクライアントはこんな感じのコードです。本当のアプリケーションではもっと汎用的に使えるような書き方をしたほうが良いですが、サンプルなのでサッと書いてしまいました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ApiClient.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ApiClient&lt;/span&gt;: NSObject {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; sharedInstance = ApiClient()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; endpoint : String = &lt;span style="color:#e6db74"&gt;&amp;#34;YOUR_SERVER_URL/api&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(path: String, parameters: Dictionary&amp;lt;String, String&amp;gt;, onSuccess: (JSON)-&amp;gt;Void, onFailure: (NSError)-&amp;gt;Void) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;guard&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; url = NSURL(string: endpoint &lt;span style="color:#f92672"&gt;+&lt;/span&gt; path) &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; headers = [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Authorization&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Bearer &lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;Auth.sharedInstance.accessToken&lt;span style="color:#e6db74"&gt;()&lt;/span&gt;&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; Alamofire.request(.GET, url, headers: headers, parameters: parameters).responseJSON { response &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; response.result.isSuccess {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; value = response.result.value {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; onSuccess(JSON(value))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; error = response.result.error {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; onFailure(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでiOSアプリケーションとRailsの連携ができるようになりました。ライブラリに頼りっきりではありますが、その分連携するまでをサッと作ることができます。アプリケーションそのものに時間を使ったほうがいいですからね。&lt;/p&gt;
&lt;p&gt;何回か書いていますが、サンプルコードを見てもらったほうがわかりやすいと思います。&lt;/p&gt;</description></item><item><title>RailsアプリをHeroku→さくらVPSに移行</title><link>https://blog.piyo.tech/posts/2015-08-28-200600/</link><pubDate>Fri, 28 Aug 2015 20:06:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-08-28-200600/</guid><description>&lt;p&gt;Herokuのプランが変わったのでRailsアプリケーションをさくらに移行した。&lt;/p&gt;
&lt;p&gt;ここ最近Herokuの料金体系が変わってFree Dynoは18時間までしか動かせないようになったらしい。それにともなってこんなHackをする人まで出てきているようで、Freeでとりあえず動かしたいという人たちに与える影響はそれなりにあるように思える。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ssig33.com/text/%E6%9C%80%E6%82%AA%EF%BC%81%E6%84%8F%E5%9C%B0%E3%81%A7%E3%82%82%20Heroku%20%E3%82%92%E7%84%A1%E6%96%99%E3%81%A7%E4%BD%BF%E3%81%86"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?http://ssig33.com/text/%E6%9C%80%E6%82%AA%EF%BC%81%E6%84%8F%E5%9C%B0%E3%81%A7%E3%82%82%20Heroku%20%E3%82%92%E7%84%A1%E6%96%99%E3%81%A7%E4%BD%BF%E3%81%86" alt=""&gt;&lt;/a&gt;
&lt;a href="http://ssig33.com/text/%E6%9C%80%E6%82%AA%EF%BC%81%E6%84%8F%E5%9C%B0%E3%81%A7%E3%82%82%20Heroku%20%E3%82%92%E7%84%A1%E6%96%99%E3%81%A7%E4%BD%BF%E3%81%86"&gt;http://ssig33.com/text/%E6%9C%80%E6%82%AA%EF%BC%81%E6%84%8F%E5%9C%B0%E3%81%A7%E3%82%82%20Heroku%20%E3%82%92%E7%84%A1%E6%96%99%E3%81%A7%E4%BD%BF%E3%81%86&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そういう僕も家族用に自分で作ったウェブアプリケーションを運用していたんだけど、料金体系が変わる前から自分のさくらVPSに移行したいと思っていたところにこのプラン変更が来たのでこれを機にと思い移行してみることにした。&lt;/p&gt;
&lt;p&gt;ちなみに移行したアプリケーションは、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;普通のRailsアプリケーション&lt;/li&gt;
&lt;li&gt;PostgresqlがあればOK&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;というシンプルなものだった。Herokuで色々なアドオンを使いまくってるぜというわけではなかったのでそんなには手間ではなかったと思う。&lt;/p&gt;
&lt;p&gt;移行先は色々な用途のために元々使っていたさくらVPSの1Gプラン。月額900円。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CentOS 6.4&lt;/li&gt;
&lt;li&gt;2 core&lt;/li&gt;
&lt;li&gt;1GBメモリ&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="postgresqlのインストール"&gt;Postgresqlのインストール&lt;/h1&gt;
&lt;p&gt;別のRailsアプリケーションも動かしていたけれどそちらはMySQLを使っていたので、移行先のサーバーにはPostgresqlが入っていなかった。&lt;/p&gt;
&lt;p&gt;インストールして初期設定を済ます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ wget http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/pgdg-centos94-9.4-1.noarch.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ sudo rpm -ivh pgdg-centos94-9.4-1.noarch.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ sudo yum install -y postgresql94-server postgresql94-devel postgresql94-contrib
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;$ sudo /etc/rc.d/init.d/postgresql-9.4 initdb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;$ sudo /etc/rc.d/init.d/postgresql-9.4 start
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;$ sudo chkconfig postgresql-9.4 on
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;$ sudo su - postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;$ createuser -s hiromasa
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="rbenv"&gt;rbenv&lt;/h1&gt;
&lt;p&gt;対象のアプリケーションが&lt;code&gt;2.0.0-p598&lt;/code&gt;で動いていたので、対象のマシンのrbenvにもそのバージョンを入れ、bundlerのインストールも済ませておく。bundlerはよく忘れる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ rbenv install 2.0.0-p598
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ rbenv local 2.0.0-p598
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ gem i bundler
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="passenger"&gt;Passenger&lt;/h1&gt;
&lt;p&gt;これまで動かしていたRailsアプリケーションは全部Ruby1.9.3系で動いていたが、今回Ruby2系も導入したことにより、Passengerも使い分けなければいけないことになった。&lt;/p&gt;
&lt;p&gt;幸い、それを指南してくれる記事があったのでまんまこれと同じようにやったら使い分けることができた。よかった。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://y-ken.hatenablog.com/entry/how-to-use-multiple-ruby-version-in-one-apache-passenger"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?http://y-ken.hatenablog.com/entry/how-to-use-multiple-ruby-version-in-one-apache-passenger" alt=""&gt;&lt;/a&gt;
&lt;a href="http://y-ken.hatenablog.com/entry/how-to-use-multiple-ruby-version-in-one-apache-passenger"&gt;http://y-ken.hatenablog.com/entry/how-to-use-multiple-ruby-version-in-one-apache-passenger&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;本当に助かりました。ありがたい。&lt;/p&gt;
&lt;p&gt;ここまででサーバー側は大体OKになったと思う。&lt;/p&gt;
&lt;h1 id="デプロイ"&gt;デプロイ&lt;/h1&gt;
&lt;p&gt;Herokuの恩恵の1つにデプロイの簡単さがあげられる。しばらく自前でのデプロイをしてこなかったため、いざ自分でやろうとするとものすごく面倒だということを思い出した。&lt;/p&gt;
&lt;h2 id="capistrano"&gt;Capistrano&lt;/h2&gt;
&lt;p&gt;2年前にちょちょっと使っていたCapistranoは3系になって色々進化していた。一応3系がベータのときに使っていたことがあり、そのときのデプロイスクリプトも残っていたので、今回のデプロイもそれを参考にすれば楽勝だろうとタカをくくっていたが、変なところで動かなくてハマった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p lang="ja" dir="ltr"&gt;Herokuからさくらに移行しようとして久しぶりにCapistrano使ったらかなり辛い。まったくデプロイできない…&lt;/p&gt;&amp;mdash; hiromasa (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/status/636873268423618560"&gt;August 27, 2015&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;エラーの内容を残しておくのを忘れたのでうろ覚えでどんな現象だったのかを書いておくと、デプロイ途中で何かを&lt;code&gt;cp&lt;/code&gt;するコマンドがあるんだけど、本来は&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;cp a b c destination/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;という風になっていてほしいところを、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;cp a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;b
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;c
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;destination/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;と改行が入った状態でコマンドが実行されるようで、&lt;code&gt;b&lt;/code&gt;とか&lt;code&gt;c&lt;/code&gt;みたいなコマンドはありません、というエラーで終了してしまっていた。&lt;/p&gt;
&lt;p&gt;調べても全然わからないので別のデプロイツールを探すことに。&lt;/p&gt;
&lt;h2 id="mina"&gt;Mina&lt;/h2&gt;
&lt;p&gt;Capistranoが嫌になったのでRuby Toolboxで他のデプロイツールを探したら、Minaってのを見つけました。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p lang="en" dir="ltr"&gt;The Ruby Toolbox - Deployment Automation &lt;a href="https://t.co/qy26fJfXO6"&gt;https://t.co/qy26fJfXO6&lt;/a&gt;&lt;/p&gt;&amp;mdash; hiromasa (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/status/636877130316451840"&gt;August 27, 2015&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p lang="ja" dir="ltr"&gt;こっちにする&amp;#10;&lt;a href="https://t.co/kD6Ipm9Frs"&gt;https://t.co/kD6Ipm9Frs&lt;/a&gt;&lt;/p&gt;&amp;mdash; hiromasa (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/status/636877423133351938"&gt;August 27, 2015&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;今回やりたかったデプロイプロセスはすごく単純で、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ソース持ってくる&lt;/li&gt;
&lt;li&gt;bundleする&lt;/li&gt;
&lt;li&gt;db:migrateする&lt;/li&gt;
&lt;li&gt;asset:precompileする&lt;/li&gt;
&lt;li&gt;Apacheを再起動する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;っていうだけだったので設定はほとんどいらなかった。サーバーの情報やソース管理のURLぐらいかな。&lt;/p&gt;
&lt;p&gt;Minaの使い方はREADMEにある通りで、まず、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ mina init
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;して設定ファイルを生成し、次にその設定ファイルの一部をこんな風に書き換え、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;mina/rbenv&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# コメントを外す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;set &lt;span style="color:#e6db74"&gt;:user&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;hiromasa&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;set &lt;span style="color:#e6db74"&gt;:domain&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;vps&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# ~/.ssh/configのHostを使うと便利&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;set &lt;span style="color:#e6db74"&gt;:deploy_to&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;/home/hiromasa/apps/myappname&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;set &lt;span style="color:#e6db74"&gt;:repository&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;https://user:password@bitbucket.org/hiromasa/myapp.git&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;task &lt;span style="color:#e6db74"&gt;:environment&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; invoke &lt;span style="color:#e6db74"&gt;:&amp;#39;rbenv:load&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# コメントを外す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次にセットアップコマンドを叩く。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ mina setup
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これをやるとティレクトリ等が生成され、&lt;code&gt;database.yml&lt;/code&gt;や&lt;code&gt;secrets.yml&lt;/code&gt;が用意される。データベースのパスワードなどはここに書けばいいのでソース管理に含める必要はないということになる。&lt;/p&gt;
&lt;p&gt;最後にデプロイコマンドを叩く。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ mina deploy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;capistranoに比べてシンプルに書けた気がする。少なくとも&lt;code&gt;cp&lt;/code&gt;で変なエラーは起きなかったし。&lt;/p&gt;
&lt;h1 id="databaseの移行"&gt;databaseの移行&lt;/h1&gt;
&lt;p&gt;Herokuからデータを移行する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ heroku pg:backups capture -a myapp
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ curl -o latest.dump &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;heroku pg:backups public-url -a myapp&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでPostgresqlのdumpが手に入るので、さくらVPSのデータベースにインポートしてあげれば良い。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ローカル&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ scp latest.dump vps:~/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# リモート&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;pg_restore --verbose --clean --no-acl --no-owner -U hiromasa -d mydatabse latest.dump
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで無事動くようになりました。&lt;/p&gt;
&lt;p&gt;これで18時間で止まることもなくなったし、日本のサーバーになったのでレスポンスが速くなり快適に使えるようになった。おしまい。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4774164283/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/81qsTUjiLTL._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;チーム開発実践入門 ~共同作業を円滑に行うツール・メソッド (WEB&amp;#43;DB PRESS plus)&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>Yosemiteで日本語入力が遅い問題が解決</title><link>https://blog.piyo.tech/posts/2015-08-25-182548/</link><pubDate>Tue, 25 Aug 2015 18:25:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-08-25-182548/</guid><description>&lt;p&gt;昨年末にMacbook Pro 15inchに買い替えてからOS X Yosemiteで日本語入力が遅い問題にずっと困っていたのを、さっきおこなった対策で直せた気がするのでメモしておく。&lt;/p&gt;
&lt;p&gt;まず、以前試していて少し改善したのがこれ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://discussionsjapan.apple.com/thread/10153975"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://discussionsjapan.apple.com/thread/10153975" alt="Excel2011で日本語入力のスピードが極端に遅い | Apple サポートコミュニティ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://discussionsjapan.apple.com/thread/10153975"&gt;Excel2011で日本語入力のスピードが極端に遅い | Apple サポートコミュニティ&lt;/a&gt;&lt;br style="clear:left;"&gt;
フォントの重複が起こるのをFont Bookから解消するという話。&lt;/p&gt;
&lt;p&gt;これでよくなった！と思っていたらそんなことはなくてしばらくすると再発するというのを繰り返していた。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;Yosemiteでの日本語入力が遅すぎてつらい。特定のソフト上で遅くなる印象。ブラウザなど。 &lt;a href="http://t.co/BE6q7rb7oj"&gt;pic.twitter.com/BE6q7rb7oj&lt;/a&gt;&lt;/p&gt;&amp;mdash; ぴよ（ぴー） (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/status/634515935785799680"&gt;August 21, 2015&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;特定のソフトというのは、ブラウザや一部のエディタ（Atomなど）、Evernoteなど。ATOK PadやEmacsのように遅くならないエディタもあった。&lt;/p&gt;
&lt;p&gt;今日もいつものように「Yosemite 日本語 遅い」などとググっていくうちにこの方のブログに辿り着き、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;アクセシビリティの設定で、次のようにアクセシビリティの設定で「コントラストを上げる」「透明度を下げる」の設定をONにすると解決しました。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;このような対策をして解決したことがわかった。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.downtown.jp/~soukaku/archives/2015/0416_182211.html"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?http://www.downtown.jp/~soukaku/archives/2015/0416_182211.html" alt=""&gt;&lt;/a&gt;
&lt;a href="http://www.downtown.jp/~soukaku/archives/2015/0416_182211.html"&gt;http://www.downtown.jp/~soukaku/archives/2015/0416_182211.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ちなみにこの方、数記事に渡って色々な対策をしていくのを書いてくれているので、同じような問題に直面している身としては解決策を知るだけではなく途中経過も追えて良かったと思う。&lt;/p&gt;
&lt;p&gt;「コントラストを上げる」「透明度を下げる」の対策後は問題のあったソフト上での日本語入力も問題なくできるようになった。ようやく解消してよかったという気持ちでいっぱいだが、もうすぐ新しいバージョンのOS Xが出るんだよなと思うと、また別の問題が起こりそうで面倒だ。いつもはすぐにインストールしていたが、今回はアップデート数回分待つぐらいのことはしてもいいかもしれない。&lt;/p&gt;
&lt;p&gt;ところで、「コントラストを上げる」を選ぶと画面の雰囲気がそこそこ大きく変わる。&lt;/p&gt;
&lt;p&gt;有効にする前（通常の見た目）はこれだが、&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA8hEgyPhBxMO7zUZ5HHhG3mEzYinLOk0lMB/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;コントラストを上げるとこうなる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA8eEsWsSzpHOqa1_jUqAlpLiBbov_VepncB/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;でもすぐに慣れるので問題ないと思う。&lt;/p&gt;</description></item><item><title>SwiftでMicrosoft Azure StorageのAPIクライアントを書きました（書いてます）</title><link>https://blog.piyo.tech/posts/2015-08-18-221625/</link><pubDate>Tue, 18 Aug 2015 22:16:25 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-08-18-221625/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA-0dz0JGMZP_quvTflJNXSB00k9fQAisZoB/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;最近はSwift版のMicrosoft Azure StorageのAPIクライアントを書いている。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/AzureStorageApiClient"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?https://github.com/pi-chan/AzureStorageApiClient" alt=""&gt;&lt;/a&gt;
&lt;a href="https://github.com/pi-chan/AzureStorageApiClient"&gt;https://github.com/pi-chan/AzureStorageApiClient&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Microsoft Azure Storageを管理するようなMacまたはiOSのアプリを書きたくてSwiftかObjective-Cで書かれたAPIクライアントライブラリを探したのだけれど、現時点ではそのようなものはないということがわかったのでSwiftを勉強しつつ自分で書くことにした（ここにそう書かれている→&lt;a href="http://blogs.msdn.com/b/windowsazurestorage/archive/2015/04/29/microsoft-azure-storage-client-library-for-c-v1-0-0-general-availability.aspx" title="Microsoft Azure Storage Client Library for C++ v1.0.0 (General Availability) - Microsoft Azure Storage Team Blog - Site Home - MSDN Blogs"&gt;Microsoft Azure Storage Client Library for C++ v1.0.0 (General Availability) - Microsoft Azure Storage Team Blog - Site Home - MSDN Blogs&lt;/a&gt;）&lt;/p&gt;
&lt;p&gt;このクライアントを使って書いたMacアプリは現在申請中でレビュー待ち。というか1回リジェクトされてしまった。&lt;/p&gt;
&lt;p&gt;そもそもなぜMacアプリを書く必要があるのか、そしてそもそもなぜAWSではなくAzureなのか、ということに答える必要があるかもしれないけど、今回はその点はスルーすることにする。&lt;/p&gt;
&lt;h1 id="ms-azure-storage"&gt;MS Azure Storage&lt;/h1&gt;
&lt;p&gt;（ここ、間違っていたらごめんなさい）&lt;/p&gt;
&lt;p&gt;MS Azure StorageにはBlob、Queue、Table、Fileという4つのサービスの総称で、AWSと対応させると大体こんな感じになっている。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Azure Storage&lt;/th&gt;
&lt;th&gt;AWS&lt;/th&gt;
&lt;th&gt;用途&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Blob&lt;/td&gt;
&lt;td&gt;S3&lt;/td&gt;
&lt;td&gt;ファイル&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Queue&lt;/td&gt;
&lt;td&gt;SQS&lt;/td&gt;
&lt;td&gt;メッセージング&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Table&lt;/td&gt;
&lt;td&gt;DynamoDB&lt;/td&gt;
&lt;td&gt;NoSQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File&lt;/td&gt;
&lt;td&gt;（ない？）&lt;/td&gt;
&lt;td&gt;ファイル共有&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;今回書いているAPIクライアントはこれら4つのサービスのうちBlobとQueueに対応しようと考えていて、実際主要なAPIはある程度実装できたと思っている。&lt;/p&gt;
&lt;p&gt;ちなみにAzure StorageのAPIリファレンスはこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://msdn.microsoft.com/ja-jp/library/azure/dd179355.aspx" title="ストレージ サービス REST API リファレンス | Windows Azure のテクニカル ドキュメント ライブラリ"&gt;ストレージ サービス REST API リファレンス | Windows Azure のテクニカル ドキュメント ライブラリ&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="設計"&gt;設計&lt;/h1&gt;
&lt;p&gt;Swift力不足のためAPIクライアントをSwiftでいい感じに書くにはどうしたらいいのか全く検討がつかなかった。そこで「Swift API クライアント」などと適当にググって調べらとてもいい記事を発見し、記事やサンプルアプリケーションを見て良い感じだなと思ったのでほぼそのままの設計で実装することにした。この記事に感謝します。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.ishkawa.org/2015/02/17/1424099641/" title="堅牢で使いやすいAPIクライアントをSwiftで実装したい"&gt;堅牢で使いやすいAPIクライアントをSwiftで実装したい&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;設計方針はこの3つだそう。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;目標としたのは以下の3つの条件を満たすことです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;レスポンスはモデルオブジェクトとして受け取る (便利)&lt;/li&gt;
&lt;li&gt;個々のリクエスト/レスポンスの定義は1箇所で済ます (変更しやすくしたい)&lt;/li&gt;
&lt;li&gt;リクエストオブジェクトはAPIクライアントから分離させたい&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;この記事を読んでいただければ僕のライブラリでやっていることも全部わかると思うが、一応簡単に設計について触れておく。&lt;/p&gt;
&lt;h2 id="クライアントの主要コード"&gt;クライアントの主要コード&lt;/h2&gt;
&lt;p&gt;クライアントの主要メソッド&lt;code&gt;call&lt;/code&gt;の擬似コードを載せてみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Client&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;call&lt;/span&gt;&amp;lt;T: Request&amp;gt;(request: T, handler: (Response&amp;lt;T.Response&amp;gt;) -&amp;gt; Void) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ① 成功時の処理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; success = { (task: NSURLSessionDataTask!, responseObject: AnyObject!) -&amp;gt; Void &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; statusCode = (task.response &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt;? NSHTTPURLResponse)?.statusCode
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (statusCode, request.convertResponseObject(responseObject)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; (.Some(&lt;span style="color:#ae81ff"&gt;200.&lt;/span&gt;.&amp;lt;&lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;), .Some(&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; response)):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; handler(Response(response))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; userInfo = [NSLocalizedDescriptionKey: &lt;span style="color:#e6db74"&gt;&amp;#34;unresolved error occurred.&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; error = NSError(domain: &lt;span style="color:#e6db74"&gt;&amp;#34;WebAPIErrorDomain&amp;#34;&lt;/span&gt;, code: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, userInfo: userInfo)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; handler(Response(error))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ② 失敗時の処理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; failure = { (task: NSURLSessionDataTask!, error: NSError!) -&amp;gt; Void &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; handler(Response(error))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ③ リクエスト&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; manager = AFHTTPSessionManager()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; url = scheme &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;://&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; host() &lt;span style="color:#f92672"&gt;+&lt;/span&gt; request.path()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; manager.responseSerializer = AFHTTPResponseSerializer()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; manager.responseSerializer.acceptableContentTypes = request.responseTypes()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; manager.GET(url, parameters: &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;, success: success, failure: failure)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;③の部分は単に&lt;code&gt;AFNetworking&lt;/code&gt;の呼び出しなのでここでは特に触れない。通信のライブラリとしては&lt;code&gt;AFNetworking&lt;/code&gt;を選択した。同じ作者が書いたSwift版のライブラリ、&lt;code&gt;Alamofire&lt;/code&gt;のほうがSwiftらしく書けるのかもしれないけれど、一度も使ったことがなかったので今回はパスした。いずれ書き換えてみてもいいかもしれないと思っている。&lt;/p&gt;
&lt;p&gt;次は短い②の部分だけど、これは単にエラーオブジェクトを&lt;code&gt;call&lt;/code&gt;に渡ってきたハンドラに返している。&lt;/p&gt;
&lt;p&gt;最後の①はレスポンスが正常に返ってきたときの処理で、ステータスコードとレスポンスから正しくモデルオブジェクトに変換できたかどうかで処理を分岐している。&lt;/p&gt;
&lt;p&gt;全体を見ると、個々のリクエストに必要な情報（メソッド、パラメータ、HTTPレスポンスから得たいモデルオブジェクトなど）はリクエストオブジェクトから取り出して使うようになっている。そのためクライアントのコードは全てのリクエストに共通の処理だけ書いておけば良い。&lt;/p&gt;
&lt;h2 id="レスポンス"&gt;レスポンス&lt;/h2&gt;
&lt;p&gt;クライアントの&lt;code&gt;call&lt;/code&gt;メソッドに渡すハンドラには&lt;code&gt;Response&amp;lt;T&amp;gt;&lt;/code&gt;が渡ってくるようになっている。このResponseは値付きenum（というのかなんというのか…？）になっていて、成功時はリクエストオブジェクトが持つレスポンスの型に対応したモデルオブジェクトが、失敗時にはNSErrorを持っていることになる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Wrapper&lt;/span&gt;&amp;lt;T&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; value: T
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; value: T) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.value = value
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;enum&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Response&lt;/span&gt;&amp;lt;T&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; Success(Wrapper&amp;lt;T&amp;gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; Failure(Wrapper&amp;lt;NSError&amp;gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; value: T) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt; = .Success(Wrapper(value))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; error: NSError) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt; = .Failure(Wrapper(error))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;クライアントの呼び出し側はこのようになる。&lt;code&gt;response: Response&amp;lt;T&amp;gt;&lt;/code&gt;でSwitchして成功時、失敗時の処理をしてあげる感じになる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;client.call(AzureQueue.ListQueuesRequest(), handler: { response &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; response {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .Success(&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; wrapper):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; println(wrapper.value) &lt;span style="color:#75715e"&gt;// AzureQueue.ListQueuesRequest.Response&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .Failure(&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; wrapper):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; println(wrapper.value) &lt;span style="color:#75715e"&gt;// NSError&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="リクエストオブジェクト"&gt;リクエストオブジェクト&lt;/h2&gt;
&lt;p&gt;さっき書いたようにリクエストオブジェクトには個々のHTTPリクエストで必要な情報を個別に定義して、クライアントから使えるようにしてある。&lt;/p&gt;
&lt;p&gt;参考にした記事では&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;パス&lt;/li&gt;
&lt;li&gt;メソッド（GET,POSTなど）&lt;/li&gt;
&lt;li&gt;モデルオブジェクトへの変換&lt;/li&gt;
&lt;li&gt;モデルオブジェクトへの型&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などが書かれていたが、Azure Storageのクライアントではさらに、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;リクエストBody&lt;/li&gt;
&lt;li&gt;追加のHTTPヘッダー（BodyのContent-Lengthなど）&lt;/li&gt;
&lt;li&gt;HTTPレスポンスのContent−Type&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;あたりを追加している。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ListQueuesRequest&lt;/span&gt;: Request {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; method = &lt;span style="color:#e6db74"&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;typealias&lt;/span&gt; Response = Collection&amp;lt;Queue&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;() {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;() -&amp;gt; String {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/?comp=list&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;body&lt;/span&gt;() -&amp;gt; NSData? {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;additionalHeaders&lt;/span&gt;() -&amp;gt; [String : String] {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;convertResponseObject&lt;/span&gt;(object: AnyObject?) -&amp;gt; Response? {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; ResponseUtility.responseItems(object, keyPath: &lt;span style="color:#e6db74"&gt;&amp;#34;Queues.Queue&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;responseTypes&lt;/span&gt;() -&amp;gt; Set&amp;lt;String&amp;gt;? {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;application/xml&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="promise版の呼び出し"&gt;Promise版の呼び出し&lt;/h1&gt;
&lt;p&gt;ここまで書いたことでAPIクライアントとしての機能は大体果たせるようになった。&lt;/p&gt;
&lt;p&gt;ところでJavascriptなんかではよくあるように、非同期処理を待ってから次の非同期処理を書こうとするととても書きにくいという問題が、Objective-CやSwiftでAPIクライアントを書くときにも現れる。これはまあ放っておいてもいいのだけど使うときに便利なほうがいいと思ったので試しに対応してみることにした。&lt;/p&gt;
&lt;p&gt;SwiftでもJavascriptのPromise的なアプローチを使えることができると知っていたので調べてみたところ次のようなライブラリが候補に挙がった。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://promisekit.org/" title="PromiseKit"&gt;PromiseKit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ReactKit/SwiftTask" title="ReactKit/SwiftTask"&gt;ReactKit/SwiftTask&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Thomvis/BrightFutures" title="Thomvis/BrightFutures"&gt;Thomvis/BrightFutures&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;決め手はなんだったかよく覚えていないが、上に挙げた3つのライブラリを全て試してみて最終的に&lt;a href="https://github.com/Thomvis/BrightFutures" title="Thomvis/BrightFutures"&gt;BrightFutures&lt;/a&gt;を採用してみた。&lt;/p&gt;
&lt;p&gt;実装の際に参考にしたリンクはこちら。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://dev.classmethod.jp/smartphone/swift-brightfutures-1/" title="[Swift] 非同期処理フレームワークBrightFutures ~導入編~ ｜ Developers.IO"&gt;[Swift] 非同期処理フレームワークBrightFutures &lt;del&gt;導入編&lt;/del&gt; ｜ Developers.IO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Thomvis/BrightFutures" title="Thomvis/BrightFutures"&gt;Thomvis/BrightFutures&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="brightfutures版のクライアント"&gt;BrightFutures版のクライアント&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Client&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;future&lt;/span&gt;&amp;lt;T: Request&amp;gt;(request: T) -&amp;gt; Future&amp;lt;T.Response, NSError&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; promise = Promise&amp;lt;T.Response, NSError&amp;gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ① 成功時の処理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; success = { (task: NSURLSessionDataTask!, responseObject: AnyObject!) -&amp;gt; Void &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; statusCode = (task.response &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt;? NSHTTPURLResponse)?.statusCode
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (statusCode, request.convertResponseObject(responseObject)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; (.Some(&lt;span style="color:#ae81ff"&gt;200.&lt;/span&gt;.&amp;lt;&lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;), .Some(&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; response)):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; promise.success(response)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; userInfo = [NSLocalizedDescriptionKey: &lt;span style="color:#e6db74"&gt;&amp;#34;unresolved error occurred.&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; error = NSError(domain: &lt;span style="color:#e6db74"&gt;&amp;#34;WebAPIErrorDomain&amp;#34;&lt;/span&gt;, code: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, userInfo: userInfo)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; promise.failure(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ② 失敗時の処理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; failure = { (task: NSURLSessionDataTask!, error: NSError!) -&amp;gt; Void &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; promise.failure(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ③ リクエスト&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; manager = AFHTTPSessionManager()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; url = scheme &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;://&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; host() &lt;span style="color:#f92672"&gt;+&lt;/span&gt; request.path()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; manager.responseSerializer = AFHTTPResponseSerializer()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; manager.responseSerializer.acceptableContentTypes = request.responseTypes()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; manager.GET(url, parameters: &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;, success: success, failure: failure)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ④ Futureオブジェクトを返す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; promise.future
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;通常版と変わったのは&lt;code&gt;call&lt;/code&gt;メソッドにハンドラを渡さなくなり、代わりに&lt;code&gt;Future&lt;/code&gt;というオブジェクトを返すようになったことで、レスポンスが返ってきたときにはハンドラにモデルオブジェクトやエラーを渡す代わりに&lt;code&gt;Promise&lt;/code&gt;オブジェクトの&lt;code&gt;success&lt;/code&gt;や&lt;code&gt;failure&lt;/code&gt;メソッドを呼ぶようになっている。&lt;/p&gt;
&lt;h2 id="brightfutures版を使う側のコード"&gt;BrightFutures版を使う側のコード&lt;/h2&gt;
&lt;p&gt;例えば、&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Queueの一覧を取得した後で、&lt;/li&gt;
&lt;li&gt;Queueを新しく生成し、&lt;/li&gt;
&lt;li&gt;次にそのQueueを削除する&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;というAPI呼び出し（意味はないが）をしたいとき、通常版ではこのようになる（ひどすぎる…）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onError&lt;/span&gt;(error: NSError) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; println(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;normal&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; req1 = AzureQueue.ListQueuesRequest()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; queueClient.call(req1, handler: { response &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; response {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .Success(&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; wrapper):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; req2 = AzureQueue.CreateQueueRequest(queue: &lt;span style="color:#e6db74"&gt;&amp;#34;brandnewqueue&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.queueClient.call(req2, handler: { response &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; response {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .Success(&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; wrapper):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; req3 = AzureQueue.DeleteQueueRequest(queue: &lt;span style="color:#e6db74"&gt;&amp;#34;brandnewqueue&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.queueClient.call(req3, handler: { response &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; response {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .Success(&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; wrapper):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; println(&lt;span style="color:#e6db74"&gt;&amp;#34;Success!!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .Failure(&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; wrapper):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.onError(wrapper.value)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .Failure(&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; wrapper):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.onError(wrapper.value)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; .Failure(&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; wrapper):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.onError(wrapper.value)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;BrightFutures版では煩雑さは残るものの幾分かマシに書けるようになる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;promise&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; req1 = AzureQueue.ListQueuesRequest()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; queueClient.future(req1).flatMap { response -&amp;gt; Future&amp;lt;AzureQueue.CreateQueueRequest.Response, NSError&amp;gt; &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; req = AzureQueue.CreateQueueRequest(queue: &lt;span style="color:#e6db74"&gt;&amp;#34;brandnewqueue&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.queueClient.future(req)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; }.flatMap { response -&amp;gt; Future&amp;lt;AzureQueue.DeleteQueueRequest.Response, NSError&amp;gt; &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; req = AzureQueue.DeleteQueueRequest(queue: &lt;span style="color:#e6db74"&gt;&amp;#34;brandnewqueue&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.queueClient.future(req)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }.onSuccess { response &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; println(response)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; }.onFailure { error &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; println(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;煩雑さの原因になっている&lt;code&gt;flatMap { response -&amp;gt; Future&amp;lt;AzureQueue.CreateQueueRequest.Response, NSError&amp;gt; in&lt;/code&gt;のようなクロージャの型の部分だが、これを省略してしまうと現状のXcode6.4ではambiguousとか言われてコンパイルできなかった。PromiseKitなどでも同じように見えるエラーに出会ったのでこのあたりはSwiftやXcodeの進化が必要なのかな。&lt;/p&gt;
&lt;p&gt;とにかく、これでAPI呼び出しを順番にしたいという要求にも一応答えられるようになった。&lt;/p&gt;
&lt;p&gt;あとPromise系のライブラリはそれぞれ進化が速いらしい。すぐに色々変わってしまうかもしれない。&lt;/p&gt;
&lt;h1 id="テスト"&gt;テスト&lt;/h1&gt;
&lt;p&gt;プロジェクトをCocoaPodsの&lt;code&gt;pod lib create&lt;/code&gt;で生成したらデフォルトで&lt;code&gt;Quick&lt;/code&gt;というテストライブラリが入ってきたのでそのままこれを使った。Quickでのテストは書いたことがなかったが参考になるコード（後述）が見つかったのであまり苦労することはなかった。&lt;/p&gt;
&lt;p&gt;テストはできるだけ書いておきたいと思ったものの、APIクライアントはAPIサーバーあっての話なのでテストはどうしようか迷って色々試した結果、今のように実際のAzure環境を使ったテストに落ち着いた。&lt;/p&gt;
&lt;h2 id="nocillaでスタブ"&gt;Nocillaでスタブ？&lt;/h2&gt;
&lt;p&gt;最初は&lt;code&gt;Nocilla&lt;/code&gt;というライブラリを使ってスタブしてテストを書こうと思ったが、マッチポンプ的あまり意味がない気がしたのでこれは却下することにした。&lt;/p&gt;
&lt;p&gt;なお、Nocillaを使おうとして色々調べているときに見つけたサンプルコードがQuickでテストを書くときにも訳にたったので紹介しておく。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bitbucket.org/snippets/atlassian/xyzKj/sample-swift-code-for-http-stubbing-using" title="Sample swift code for http stubbing using Nocilla (XCTest vs Quick) — Bitbucket"&gt;Sample swift code for http stubbing using Nocilla (XCTest vs Quick) — Bitbucket&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="azure-storage-emulator"&gt;Azure Storage Emulator&lt;/h2&gt;
&lt;p&gt;次に試そうとしたのはWindowで動かすことができるAzure Storage Emulatorを使うことだ。ざっくり言うとAPIサーバーのエミュレータをローカルに立てられるというものらしい。ということはこれをMacに入れたVMWareとかで動かしておけばテストに使えるんじゃねーか（少なくともローカルでは）と考え色々準備してみた。&lt;/p&gt;
&lt;p&gt;ところがクライアントの接続先にVMWareのIPを指定してもどうにもうまくいかない。3時間近く奮闘したものの何も得られなかったのでこの作戦も却下することに。&lt;/p&gt;
&lt;h2 id="実環境でテストする"&gt;実環境でテストする&lt;/h2&gt;
&lt;p&gt;ここでようやく他の言語のクライアントではどうしてるんだろうということに気がついたので、Railsで使ったことがあるRuby版のクライアントを見てみることにした。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Azure/azure-sdk-for-ruby" title="Azure/azure-sdk-for-ruby"&gt;Azure/azure-sdk-for-ruby&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これのテストコードを見ると環境変数にストレージのアカウントやアクセスキーが設定されているときだけテストを動かせるようになっていた。つまり本物のAzure環境でテストを動かすよ、ということのようだった。&lt;/p&gt;
&lt;p&gt;そういうわけでSwift版でも同じようにAzure環境でテストを動かすコードを書くことになった。テストコードを書くにあたってBrightFutures版が非常に役に立った。これをしてそれをして、最後にあれをしたらこうなっている、というコードを通常版で書こうとしていたらだいぶ辛いことになっていたと思う。&lt;/p&gt;
&lt;h1 id="コード"&gt;コード&lt;/h1&gt;
&lt;p&gt;もう1回貼っておきます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/AzureStorageApiClient"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?https://github.com/pi-chan/AzureStorageApiClient" alt=""&gt;&lt;/a&gt;
&lt;a href="https://github.com/pi-chan/AzureStorageApiClient"&gt;https://github.com/pi-chan/AzureStorageApiClient&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="宣伝"&gt;宣伝&lt;/h1&gt;
&lt;p&gt;途中に出てきた表は自作のMacアプリで作りました。日本語入力で若干不具合があるけどMarkdownで表を書くときにはWebにある表生成ツール（&lt;a href="http://www.tablesgenerator.com/markdown_tables" title="Markdown Tables generator - TablesGenerator.com"&gt;Markdown Tables generator&lt;/a&gt;）よりも便利なのでぜひどうぞ。&lt;/p&gt;
&lt;p&gt;&lt;span class="appIcon"&gt;&lt;img class="appIconImg" height="100" src="https://is4.mzstatic.com/image/pf/us/r30/Purple7/v4/d0/a1/1d/d0a11d90-beb5-f280-a723-f3b08553a6a2/AppIcon.512x512-75.png" style="float:left;margin: 0px 15px 15px 5px;"&gt;&lt;/span&gt;&lt;span class="appName"&gt;&lt;strong&gt;&lt;a href="https://itunes.apple.com/jp/app/table2text-markdown-csv/id1021891242?mt=12&amp;uo=4" target="itunes_store"&gt;Table2Text (Markdown, CSV)&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="appCategory"&gt;カテゴリ: 開発ツール, ユーティリティ&lt;/span&gt;&lt;br&gt;&lt;span class="badgeL" style="display:inline-block; margin:4px"&gt;&lt;a href="https://itunes.apple.com/jp/app/table2text-markdown-csv/id1021891242?mt=12&amp;uo=4" target="itunes_store" style="display:inline-block;overflow:hidden;background:url(http://linkmaker.itunes.apple.com/htmlResources/assets/ja_jp//images/web/linkmaker/badge_macappstore-lrg.png) no-repeat;width:165px;height:40px;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;br style="clear:both;"&gt;&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4797380497/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/610tr6vG5HL._SL1238_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;詳解 Swift&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>CocoaアプリケーションでファイルやURLを開く</title><link>https://blog.piyo.tech/posts/2015-08-11-195937/</link><pubDate>Tue, 11 Aug 2015 19:59:37 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-08-11-195937/</guid><description>&lt;p&gt;覚書でーす。&lt;/p&gt;
&lt;h1 id="url"&gt;URL &lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;NSWorkspace.sharedWorkspace().openURL(NSURL(string: &lt;span style="color:#e6db74"&gt;&amp;#34;http://google.co.jp&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;!&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="ファイルフォルダ"&gt;ファイル/フォルダ&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;NSWorkspace.sharedWorkspace().openFile(&lt;span style="color:#e6db74"&gt;&amp;#34;/Applications/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>XcodeでiOSシミュレータがサイズごとに2つずつダブって表示されたのを直した</title><link>https://blog.piyo.tech/posts/2015-08-11-134639/</link><pubDate>Tue, 11 Aug 2015 13:46:39 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-08-11-134639/</guid><description>&lt;p&gt;タイトル通りなのだが、気がついたらこんな感じでiOSシミュレータがたくさん並んでいて気持ち悪かったので直した。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA8N0D8UmGxHsIutonjrJaBTKiIsn8tXpkYB/image.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="devicesを開く"&gt;Devicesを開く&lt;/h2&gt;
&lt;p&gt;まずXcodeのメニューからDevicesを開く。&lt;code&gt;Window&lt;/code&gt;→&lt;code&gt;Devices&lt;/code&gt;、または&lt;code&gt;Cmd+Shift+2&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA_i6QeHCppPvKxWOd0S-AcKr_NlgRDZEGYB/image.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="左ペインのデバイス一覧からダブっているものを削除"&gt;左ペインのデバイス一覧からダブっているものを削除&lt;/h2&gt;
&lt;p&gt;ダブっているもののうちどちらを消しても実質違いはないと思うんで、適当に選びながらDeleteキーで削除していく。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA8HJlvD4sVJro1SlUCexzw8cpPz2Js3ZoEB/image.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり&lt;/h2&gt;
&lt;p&gt;わーい直った。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA8U8wUuX_VDf7DePG1OLkuoZ7t3R9a8J5wB/image.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>SwiftでN文字ずつに分割した文字列を得る方法</title><link>https://blog.piyo.tech/posts/2015-08-10-132744/</link><pubDate>Mon, 10 Aug 2015 13:27:44 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-08-10-132744/</guid><description>&lt;p&gt;例えば&lt;code&gt;&amp;quot;hogefugapiyo&amp;quot;&lt;/code&gt;という文字列があるとして、これを4文字ずつに分割するなら&lt;code&gt;[&amp;quot;hoge&amp;quot;, &amp;quot;fuga&amp;quot;, &amp;quot;piyo&amp;quot;]&lt;/code&gt;、5文字ずつに分割するなら&lt;code&gt;[&amp;quot;hogef&amp;quot;, &amp;quot;ugapi&amp;quot;, &amp;quot;yo&amp;quot;]&lt;/code&gt;を得たい。&lt;/p&gt;
&lt;p&gt;Rubyであればscanメソッドを使って次のように実行できるということがわかった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;str &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hogefugapiyo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# =&amp;gt; &amp;#34;hogefugapiyo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;str&lt;span style="color:#f92672"&gt;.&lt;/span&gt;scan(&lt;span style="color:#e6db74"&gt;/.{1,5}/&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# =&amp;gt; [&amp;#34;hogef&amp;#34;, &amp;#34;ugapi&amp;#34;, &amp;#34;yo&amp;#34;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;参考&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qiita.com/paty-fakename/items/990fe9d57864054409e1" title="Ruby 文字列を任意の文字数に分割する - Qiita"&gt;Ruby 文字列を任意の文字数に分割する - Qiita&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これと同じことをSwiftでやりたくなったが、どうやら全く同じようなことをする関数はなさそうに見えた。なのでSwift力が足りないながらも自前で書いてみたのでそれを晒してみる。&lt;/p&gt;
&lt;p&gt;Rubyの用にArrayを返す関数を追加するのでもよかったが、SequenceTypeを使うほうがよさそうな気がしたので↓のように実装した。&lt;code&gt;String&lt;/code&gt;に&lt;code&gt;substr(Int)&lt;/code&gt;という関数を生やして、それを呼ぶとforループやmapとかが使えるという感じになった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;extension&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; length: Int { &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; count(&lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;internal&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SubstringGenerator&lt;/span&gt;: GeneratorType {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;typealias&lt;/span&gt; Element = String
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; count: Int
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; string: String
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; i = &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(count: Int, string: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; count &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; fatalError(&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#39;count&amp;#39; must be bigger than 0.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.count = count
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.string = string
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;next&lt;/span&gt;() -&amp;gt; Element? {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; string.length {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; endIndex : String.Index
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; i &lt;span style="color:#f92672"&gt;+&lt;/span&gt; count &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; string.length {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; endIndex = string.endIndex
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; endIndex = advance(string.startIndex, i &lt;span style="color:#f92672"&gt;+&lt;/span&gt; count)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; range = advance(string.startIndex, i)..&amp;lt;endIndex
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; i &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; count
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; string.substringWithRange(range)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;internal&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SubstringSequence&lt;/span&gt; : SequenceType {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; count: Int
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; string : String
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;typealias&lt;/span&gt; Generator = SubstringGenerator
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(count: Int, string: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;42&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.count = count
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;43&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.string = string
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;44&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;45&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;46&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;generate&lt;/span&gt;() -&amp;gt; Generator {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;47&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; Generator(count: count, string: string)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;48&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;49&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;50&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;51&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;substr&lt;/span&gt;(count: Int) -&amp;gt; SubstringSequence {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;52&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; SubstringSequence(count: count, string: &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;53&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;54&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この&lt;code&gt;substr&lt;/code&gt;を実際に使ってみるとこうなる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; substr &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hogefugapiyo&amp;#34;&lt;/span&gt;.substr(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; println(substr)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// hogef&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ugapi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// yo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; array = map(&lt;span style="color:#e6db74"&gt;&amp;#34;hogefugapiyo&amp;#34;&lt;/span&gt;.substr(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;)) {$0}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;println(array)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// [hogef, ugapi, yo]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;どうですかね、これ。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4797380497/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/610tr6vG5HL._SL1238_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;詳解 Swift&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>Mac Logicoolマウス Shift+ホイールでの横スクロールが遅い問題が解決した</title><link>https://blog.piyo.tech/posts/2015-08-08-081400/</link><pubDate>Fri, 07 Aug 2015 22:58:06 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-08-08-081400/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA-Skl8MGoNH9L1lEQDnswX5DRdg7qF-gWsB/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;OSX Marvericksの頃だったと記憶しているが、Logicoolのマウス（というかトラックボール）でのShiftキーを押しながらの横スクロールが1pxずつぐらいしか動いてないんじゃないかと思うほど遅くなってしまい、全く使い物にならなくなってしまった。仕方ないので横スクロールだけはトラックパッドを2本指でなぞるという不毛なことを長いこと続けていたが、この問題が先ほど解決した。&lt;/p&gt;
&lt;p&gt;このRedditの投稿によると問題の原因はドライバであるLogicool Control Centerだったようだ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.reddit.com/r/mac/comments/2s90sm/maverick_osx_shift_scrolling_horizontal_scrolling/" title="Maverick osx &amp;quot;Shift scrolling (horizontal scrolling) very slow. Any fix? : mac"&gt;Maverick osx &amp;quot;Shift scrolling (horizontal scrolling) very slow. Any fix? : mac&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;実際にLogicool Control Centerをアンインストールしたら横スクロールが遅い問題は解決していた。なお、アンインストールにはLCC Uninstallerを実行する必要がある。これはアプリケーション→ユーティリティ以下にある。&lt;/p&gt;
&lt;p&gt;ところで、ドライバを削除してしまうことでせっかくのマウスの機能を活かせなくなってしまうのは勿体ない。同じRedditのスレッドでsteermouseという汎用のドライバソフトが挙がっていおり、それを使えばある程度は対処できるみたい。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://plentycom.jp/steermouse/" title="ステアーマウス"&gt;ステアーマウス&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;有償のソフトだけど30日間の無料トライアル期間がある。マウスについているボタン4・ボタン5でブラウザの戻る・進むができるなど、公式のドライバでできていたことは問題なくできているような気がするので、このまま使っていける気がしている。&lt;/p&gt;
&lt;p&gt;横スクロールが遅い問題はFinderのカラム表示や、XcodeでのStoryboardを編集する際にとても困っていたので対処できて本当に嬉しい。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B00E19UYO8/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/51JTI2n7qqL._AC_SL1024_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;ロジクール ワイヤレスマウス シルバー&amp;amp;ブルー トラックボール 無線 M570t Unifying 5ボタン トラックボールマウス 電池寿命最大18ケ月 国内正規品 3年間無償保証&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>AFHTTPSessionManagerでHTTPBodyを設定する</title><link>https://blog.piyo.tech/posts/2015-08-06-133153/</link><pubDate>Thu, 06 Aug 2015 13:31:53 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-08-06-133153/</guid><description>&lt;p&gt;AFNetworkingのAFHTTPSessionManagerを使っていてBodyに素のXMLを入れてPOSTしたかったのだが、そのやり方がなかなか見当たらずソースコードを読んで解決したのでメモしておく。&lt;/p&gt;
&lt;p&gt;ざっくり言うとAFHTTPSessionManagerでのPOSTはこんな感じに行う。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; manager = AFHTTPSessionManager()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;manager.POST(url, parameters: params, success: { (task, response) -&amp;gt; Void &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// success&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}) { (task, error) -&amp;gt; Void &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// failure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;POSTするパラメータがあれば、上のメソッドの&lt;code&gt;parameters&lt;/code&gt;のところにdictionaryとかで渡せばいいはずだが（確か）、今回やりたいのはBodyにXMLのテキストを入れるということだった。&lt;/p&gt;
&lt;p&gt;まず気軽にparametersにXML文字列を直接渡してみようなどとやってみたら失敗した。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; manager = AFHTTPSessionManager()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; xmlstr = &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;?xml ...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;manager.POST(url, parameters: xmlstr, success: { (task, response) -&amp;gt; Void &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// success&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;}) { (task, error) -&amp;gt; Void &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// failure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでできたリクエストを見てみるとBodyにはこんなのが入っていた。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;(null)=%3C%3Fxml%20...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;どうやら名前が空で値がURLエンコード済文字列のパラメータをBodyとして設定してしまっているらしい。&lt;/p&gt;
&lt;p&gt;ソースコードを読むとそれがデフォルトの動作だということがわかった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AFURLRequestSerialization.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (self.queryStringSerializationStyle) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; AFHTTPRequestQueryStringDefaultStyle:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; query &lt;span style="color:#f92672"&gt;=&lt;/span&gt; AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;じゃあデフォルトじゃない動作は、というと上のコードの近くにあった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AFURLRequestSerialization.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (self.queryStringSerialization) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; NSError &lt;span style="color:#f92672"&gt;*&lt;/span&gt;serializationError;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; query &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self.queryStringSerialization(request, parameters, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;serializationError);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (serializationError) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (error) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;error &lt;span style="color:#f92672"&gt;=&lt;/span&gt; serializationError;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; nil;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;self.queryStringSerialization&lt;/code&gt;はBlockで、このブロックを設定してparameterのシリアライズをカスタマイズできるよ、ということのようだった。&lt;/p&gt;
&lt;p&gt;つまり文字列をそのままBodyに入れたい場合は、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; manager = AFHTTPSessionManager()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; xmlstr = &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;?xml ...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;manager.requestSerializer.setQueryStringSerializationWithBlock { (request, params, error) -&amp;gt; String! &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; params &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt;! String
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;manager.POST(url, parameters: xmlstr, success: { (task, response) -&amp;gt; Void &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// success&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}) { (task, error) -&amp;gt; Void &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// failure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;manager.requestSerializer.setQueryStringSerializationWithBlock&lt;/code&gt;でparameterをそのまま文字列と返してあげればよかった。&lt;/p&gt;
&lt;p&gt;これで解決できた。良かった。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4863541686/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/81ck9SIy6oL._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;Webエンジニアの教科書&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>NSTextFieldで入力を検出する</title><link>https://blog.piyo.tech/posts/2015-07-30-080500/</link><pubDate>Thu, 30 Jul 2015 08:05:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-07-30-080500/</guid><description>&lt;p&gt;iOS開発からCocoaにも手を付け始めた人間によくあることだろうが、UIKitとAppKitでお作法が同じだったり微妙に違ったりすることでちょくちょくつまずくことがある。&lt;/p&gt;
&lt;p&gt;今日はテキストフィールドでユーザーが入力を行うたびに入力値のチェックをしてOKボタンの有効/無効を切り替えるという処理を書こうとしてつまづいた。&lt;/p&gt;
&lt;h2 id="uitextfieldの場合"&gt;UITextFieldの場合&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;UITextField&lt;/code&gt;の場合はStoryboardからCtrl+ドラッグでActionを作るときに&lt;code&gt;Editing Changed&lt;/code&gt;イベントを選んであげればOK。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA8x_Jp3AuNFZ6mVsLPanqIGUe6oQWRp3csB/image.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="nstextfieldの場合"&gt;NSTextFieldの場合&lt;/h2&gt;
&lt;p&gt;Storyboardを使って同じようなことをやろうとしてもiOSのようにコントロールに発生したイベントに対応したActionを作ることができない。ここまで書いて気がついたけどAppKitはイベント型（？）じゃないということなんだね。&lt;/p&gt;
&lt;p&gt;ではどうすればいいかといえば、Delegateが存在するのでそれを実装してあげれば良い。DelegateはiOS開発でも毎回使うだろうからiOS Developerなら大丈夫のはず。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ViewController&lt;/span&gt;: NSViewController, NSTextFieldDelegate {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBOutlet&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; textField: NSTextField!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.viewDidLoad()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Do view setup here.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; textField.delegate = &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;controlTextDidChange&lt;/span&gt;(obj: NSNotification) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; doSomething()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;できた。&lt;/p&gt;</description></item><item><title>Cocoaアプリケーション(OSXアプリ)はじめました</title><link>https://blog.piyo.tech/posts/2015-07-29-083200/</link><pubDate>Wed, 29 Jul 2015 08:32:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-07-29-083200/</guid><description>&lt;p&gt;実験的な意味も含めてCocoaアプリの開発を始めた。完成したものはMac App Storeに並べてもらうべくiOSと同じように申請して審査してもらっている。&lt;/p&gt;
&lt;p&gt;そもそもMac App Storeに並んでいるアプリはなんと呼ぶのが正解なのかすらよくわかっていないが、Cocoaアプリということにしておく。&lt;/p&gt;
&lt;p&gt;iOSの開発は5年ぐらいやっているけれど、Cocoaアプリの開発は全くの初めてだったから調べながら進めている。今は単機能のSingle Windowアプリを3つ作った程度で、ドキュメントベースのアプリケーションのような複雑なことはしていないが、Cocoaアプリ開発についてのコメントというか感想を書いてみようと思う。ただの感想文ですよ。&lt;/p&gt;
&lt;h1 id="情報が少ない見つけにくい"&gt;情報が少ない、見つけにくい&lt;/h1&gt;
&lt;p&gt;まず言えるのはこれだと思う。iOS開発の情報はネットの世界に溢れている。日本語でも大量の情報があるから大抵のことは調べればできる。&lt;/p&gt;
&lt;p&gt;その反面、Cocoaアプリケーションの情報はなかなか見つからない。日本語で書かれたそこそこ新しい情報がたまにヒットするが、大抵はAppleのドキュメントページが検索のトップに来る。そしてその情報も数年前に書かれたものだったりする（必ずしも情報が古いというわけではなく、SDKが変わっていないというだけだったりするが）。&lt;/p&gt;
&lt;p&gt;検索自体もしづらい。例えば&lt;code&gt;AVFoundation OSX Swift ○○&lt;/code&gt;とか調べようとするとiOSの検索結果がずらりと出てくる。iOSとは独立してはっきりしたネーミングがあればよかったのにと思う。&lt;/p&gt;
&lt;p&gt;最近気がついたのは、&lt;code&gt;Cocoa&lt;/code&gt;というキーワードを入れておくとなかなか良さそうな検索結果を得られる気がする。&lt;/p&gt;
&lt;h1 id="お作法が割と違う"&gt;お作法が割と違う&lt;/h1&gt;
&lt;p&gt;UI周りがまあまあ違う。iOSのように画面サイズを制限されない分、自由にビューを配置したり複数のウィンドウを使ったり色々なことができる。&lt;/p&gt;
&lt;p&gt;例えばiOSでは&lt;code&gt;UIImage&lt;/code&gt;を使っているところをCocoaでは&lt;code&gt;NSImage&lt;/code&gt;を使うことになるんだけど、このクラスのインターフェースが微妙に異なるので同じように使えるもんだと思っているといちいち躓く。&lt;/p&gt;
&lt;p&gt;で、ドキュメントを探したり例を探そうとすると最初の話「情報が見つからない」に行き着いて時間がかかる。&lt;/p&gt;
&lt;p&gt;慣れるまでは同じことを何度も調べる可能性があるので見つけたページはEvernoteのWebClipすることにしている。この機能は最近全く使っていなかったけれど久しぶりに重宝しそうだ。&lt;/p&gt;
&lt;h1 id="iosの経験はかなり活きる"&gt;iOSの経験はかなり活きる&lt;/h1&gt;
&lt;p&gt;お作法が微妙に異なるとは言え、SDKの思想はiOSとほぼ変わらないからiOS経験者は比較的すんなり入ることができる。&lt;/p&gt;
&lt;p&gt;例えば、縦横の表を表現するときには&lt;code&gt;NSTableView&lt;/code&gt;を使うが、iOSの経験のない人がいきなりこのViewを使おうとしたら混乱するんじゃないかと思う。予想です。&lt;/p&gt;
&lt;p&gt;iOSの&lt;code&gt;UITableView&lt;/code&gt;もこの&lt;code&gt;NSTableView&lt;/code&gt;も&lt;code&gt;delegate&lt;/code&gt;と&lt;code&gt;dataSource&lt;/code&gt;を用いてコンテンツや挙動を制御するわけだけど、行と列がある分&lt;code&gt;NSTableView&lt;/code&gt;のほうが複雑と言っていいと思う。先に複雑じゃない&lt;code&gt;UITableView&lt;/code&gt;を触っていれば、比較的すんなり入れるんじゃないかな。&lt;/p&gt;
&lt;p&gt;Cocoaアプリケーション開発でもStoryBoardやSegueのようなUI開発の仕組みがあるし、Cocoapodsなども活用できるからiOS経験者にはハードル低いんじゃないかな。みんなやったほうがいいよ。&lt;/p&gt;
&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;p&gt;これからは備忘録的にちょくちょく書いていく予定。&lt;/p&gt;
&lt;p&gt;ちなみに最初に作ったのはiPhoneやiPadのAppStoreで使えるPreview動画を自動生成するアプリ。ネーミングやデザインなどはお察しだけどなかなか便利なのができたよ。&lt;/p&gt;
&lt;p&gt;&lt;span class="appIcon"&gt;&lt;img class="appIconImg" height="100" src="https://is3.mzstatic.com/image/pf/us/r30/Purple7/v4/1b/3f/f5/1b3ff5e1-67aa-6b02-50b9-3f9b8a79a154/AppIcon.512x512-75.png" style="height: 200px; width: 200px; float:left;margin: 0px 15px 15px 5px;"&gt;&lt;/span&gt;&lt;span class="appName"&gt;&lt;strong&gt;&lt;a href="https://itunes.apple.com/jp/app/movie-resize-for-app-previews/id1017708570?mt=12&amp;uo=4" target="itunes_store"&gt;Movie Resize for App Previews&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="appCategory"&gt;カテゴリ: ユーティリティ, グラフィック&amp;amp;デザイン&lt;/span&gt;&lt;br&gt;&lt;span class="badgeL" style="display:inline-block; margin:4px"&gt;&lt;a href="https://itunes.apple.com/jp/app/movie-resize-for-app-previews/id1017708570?mt=12&amp;uo=4" target="itunes_store" style="display:inline-block;overflow:hidden;background:url(http://linkmaker.itunes.apple.com/htmlResources/assets/ja_jp//images/web/linkmaker/badge_macappstore-lrg.png) no-repeat;width:165px;height:40px;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;br style="clear:both;"&gt;&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4501552700/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/71Tna-mVLDL._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;MAC OS X COCOAプログラミング&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>Single WindowなOSX Appで全てのWindowが閉じたときの挙動でリジェクト</title><link>https://blog.piyo.tech/posts/2015-07-28-091736/</link><pubDate>Tue, 28 Jul 2015 09:17:36 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-07-28-091736/</guid><description>&lt;p&gt;MacのアプリケーションはWindowを赤ボタンとか&lt;code&gt;⌘W&lt;/code&gt;で閉じてもアプリケーション自体が終了しないことが多いが、その場合メインウィンドウを再表示できるようにしておかないとMac App Storeに申請した際にリジェクトを食らってしまう（食らった）。&lt;/p&gt;
&lt;p&gt;1つめの対応方法として、Dockアイコンをクリックしたときにメインウィンドウを再表示するコードを&lt;code&gt;AppDelegate&lt;/code&gt;に書く。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;applicationShouldHandleReopen&lt;/span&gt;(sender: NSApplication, hasVisibleWindows flag: Bool) -&amp;gt; Bool {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; flag == &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sender.windows.count &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; sender.windows[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;].makeKeyAndOrderFront(&lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;もしくは全てのウィンドウが閉じたときアプリケーションを終了させてしまうというのもOKらしい。これは推測だけど、申請したのがシングルウィンドウなアプリケーションだったからこの対処方法でもいいよと言ってくれたんじゃないかと思う。ドキュメントベースの場合はウィンドウが閉じることって頻繁にあるだろうから多分だめなんじゃないかな。&lt;/p&gt;
&lt;p&gt;その場合は&lt;code&gt;AppDelegate&lt;/code&gt;にこんなコードを書く。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;applicationShouldTerminateAfterLastWindowClosed&lt;/span&gt;(sender: NSApplication) -&amp;gt; Bool {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今回は単機能のアプリだったので後者で対応することにしてみた。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4501552700/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/71Tna-mVLDL._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;MAC OS X COCOAプログラミング&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>【追記あり】デフォルトアプリケーションがXcode-betaになってしまったのを戻した</title><link>https://blog.piyo.tech/posts/2015-07-27-103846/</link><pubDate>Mon, 27 Jul 2015 10:38:46 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-07-27-103846/</guid><description>&lt;p&gt;XCodeのベータ版を入れたらxcodeprojなどを開くときのデフォルトアプリケーションがベータ版のほうになってしまった。いやいや君普段はそんなに使わないから。&lt;/p&gt;
&lt;p&gt;僕はターミナルでそのプロジェクトのGitディレクトリに移動して、そこから&lt;code&gt;open hogehoge.xcodeproj&lt;/code&gt;とかやることが多いのでデフォルトアプリケーションは重要なのだ。&lt;/p&gt;
&lt;p&gt;デフォルトアプリケーションの変更はFinderの&lt;code&gt;情報を見る&lt;/code&gt;あたりからできるというのは知っていたが、ついでに&lt;code&gt;*.h&lt;/code&gt;など、基本XCodeで開くよねとなっているファイルたちのデフォルトも変えたかったからそれだと物足りなかった。全部のファイルタイプに同じことするの面倒なので。&lt;/p&gt;
&lt;p&gt;そこで強引な方法で解決することにした。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;XCode-beta.appを削除&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;ゴミ箱から戻す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これでOK！&lt;/p&gt;
&lt;h2 id="追記"&gt;追記&lt;/h2&gt;
&lt;p&gt;だめだったー。ベータを起動したら元に戻ってました。なんとかならんのこれ。&lt;/p&gt;</description></item><item><title>UIWebView内リンクでの遷移をNavigationでやるやつ、Swiftバージョン</title><link>https://blog.piyo.tech/posts/2015-05-19-083000/</link><pubDate>Tue, 19 May 2015 08:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-05-19-083000/</guid><description>&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2015-05-18-130552" title="iOSでUIWebView内のリンクをタップしたらNavigationで画面遷移させる実験 - ぴよログ"&gt;iOSでUIWebView内のリンクをタップしたらNavigationで画面遷移させる実験 - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;↑こんなん書いたけどこのときはObjective-Cで書いてたのでSwiftで書き換えてみました。オプショナルが全然慣れませんがこれから勉強します。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/-p9hlzeR6r27eW1nURO_K02HK35KFbcKFqVwaEXsvs6n3OreHEL8JZxeaeS-f-ePRwzLcYc4VYbNRM6NeIjc8BZP0rt373w7XYulFYitM2ZGCyimbJkEPitqfNIT4q5O0PlUCK6pWEjy6NU1q_D5-P6q70M672eut2kQ9RLg5C8wLN9NA391GFMuaCEdsMAdPvyEzUj3XRUjOc9xyT6hvaMapG6IV_ck2bOKX9KCCBpUyxfs6UIUHryPm7grLINPYpX_39-9Z1KOk95XX8XoCsRU6lBIJGghNSy9j8sHomftLJ9ebBA-_NaFFCCLlWHZslUS3cpq6sqxsjjq4JU5jSwyk-yfI_St92-TBKedGvrkuX-PlnOcj7W12VVLOeCr-pOKsO2mpSRM1TZXEw35aOHnMGaeqX_eoi4ysuxLdm_o68sPbttzLrOhUJMF_4owMIJaxXxjRaxGNU6ubUcfW21SfhwQMFD4NOyxWHq9FDAMtBUregtWiL30AWQBc3fK1n7EMBBPjxRm553Dt6uG2SsrQmxTQ6VnJCrgB6ND74XnX4s_tuMg95LdWXI6W64VIpsxjgxoIF1pB9RCtfTHnaUJMz_7MXHDtaZsnI5bpjMEDh70bqhZpZ7AWnsjD2T6WX96tgRS_Smwg_WBc0eCnY-ZBcfW3IhU4Q=w374-h278-no" alt=""&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UIKit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TKRSegueOptions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ViewController&lt;/span&gt;: UIViewController, UIWebViewDelegate {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; HOST = &lt;span style="color:#e6db74"&gt;&amp;#34;http://localhost:4000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBOutlet&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; webView: UIWebView!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.viewDidLoad()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Do any additional setup after loading the view, typically from a nib.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; webView.delegate = &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; urlstring = HOST &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; path = &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.segueOptions?[&lt;span style="color:#e6db74"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;] &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt;? String {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; urlstring = HOST &lt;span style="color:#f92672"&gt;+&lt;/span&gt; path
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; url = NSURL(string: urlstring)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; req = NSURLRequest(URL: url!)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; webView.loadRequest(req)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;didReceiveMemoryWarning&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.didReceiveMemoryWarning()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Dispose of any resources that can be recreated.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;webView&lt;/span&gt;(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -&amp;gt; Bool {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(request.URL?.scheme == &lt;span style="color:#e6db74"&gt;&amp;#34;callback&amp;#34;&lt;/span&gt;){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; println(request.URL?.absoluteString)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; urlstring = request.URL?.absoluteString
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; href = urlstring?.substringFromIndex(advance(urlstring!.startIndex, &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; performSegueWithIdentifier(&lt;span style="color:#e6db74"&gt;&amp;#34;next&amp;#34;&lt;/span&gt;, options: [&lt;span style="color:#e6db74"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;: href!])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4797380497/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/610tr6vG5HL._SL1238_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;詳解 Swift&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>iOSでUIWebView内のリンクをタップしたらNavigationで画面遷移させる実験</title><link>https://blog.piyo.tech/posts/2015-05-18-130552/</link><pubDate>Mon, 18 May 2015 13:05:52 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-05-18-130552/</guid><description>&lt;p&gt;しばらくiOSから離れていてSwiftはほとんど触ったことないのでとりあえずObjective-Cでやりました。このあとSwiftで実装し直そうと思ってるけれど、一旦エントリにします。&lt;/p&gt;
&lt;p&gt;いつだったかDHHが既存のWebサイトを活かしてアプリ作るよーみたいなことを言ってたのを覚えていたので、今回は「いや、実際どうやってやるんだろうな」というのを考えてみたわけです。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" lang="ja"&gt;&lt;p lang="en" dir="ltr"&gt;Hybrid sweet spot: Native navigation, web content, &lt;a href="https://t.co/LWmqbmg3iX"&gt;https://t.co/LWmqbmg3iX&lt;/a&gt; — How we build mobile apps for Basecamp with tiny teams.&lt;/p&gt;&amp;mdash; DHH (@dhh) &lt;a href="https://twitter.com/dhh/status/464423427550748672"&gt;2014, 5月 8&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;h2 id="何をやりたいか"&gt;何をやりたいか&lt;/h2&gt;
&lt;p&gt;こういうページ遷移がある普通のWebサイトがあるとして、&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/l/AA_TwA7vQmhJObMbvitnrK3CZIdXF39RhW0B/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;このページをiOSのUIWebViewで表示するんだけど、リンクをタップしたときに新しいViewControllerを作ってNavigationで遷移するということをやってみます。普通にやるとリンクをタップしたら同一WebView内画面遷移するところを、あたかもiOSのネイティブのように動かしてみようということね。&lt;/p&gt;
&lt;p&gt;結論からいうとそれは可能です。↓のアニGIFを見てもらえばリンクを押したときにナビゲーションで次のビューがスタックしてくるのがわかると思います。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/-p9hlzeR6r27eW1nURO_K02HK35KFbcKFqVwaEXsvs6n3OreHEL8JZxeaeS-f-ePRwzLcYc4VYbNRM6NeIjc8BZP0rt373w7XYulFYitM2ZGCyimbJkEPitqfNIT4q5O0PlUCK6pWEjy6NU1q_D5-P6q70M672eut2kQ9RLg5C8wLN9NA391GFMuaCEdsMAdPvyEzUj3XRUjOc9xyT6hvaMapG6IV_ck2bOKX9KCCBpUyxfs6UIUHryPm7grLINPYpX_39-9Z1KOk95XX8XoCsRU6lBIJGghNSy9j8sHomftLJ9ebBA-_NaFFCCLlWHZslUS3cpq6sqxsjjq4JU5jSwyk-yfI_St92-TBKedGvrkuX-PlnOcj7W12VVLOeCr-pOKsO2mpSRM1TZXEw35aOHnMGaeqX_eoi4ysuxLdm_o68sPbttzLrOhUJMF_4owMIJaxXxjRaxGNU6ubUcfW21SfhwQMFD4NOyxWHq9FDAMtBUregtWiL30AWQBc3fK1n7EMBBPjxRm553Dt6uG2SsrQmxTQ6VnJCrgB6ND74XnX4s_tuMg95LdWXI6W64VIpsxjgxoIF1pB9RCtfTHnaUJMz_7MXHDtaZsnI5bpjMEDh70bqhZpZ7AWnsjD2T6WX96tgRS_Smwg_WBc0eCnY-ZBcfW3IhU4Q=w374-h278-no" alt=""&gt;&lt;/p&gt;
&lt;p&gt;こうすることでWebにコンテンツを自由にデプロイしつつ、ユーザー体験はネイティブに近づけられるんじゃないかと。&lt;/p&gt;
&lt;p&gt;こんなことはすでに昔からみんながやってたりしたかもしれないけど、最近は端末も速くなっているし、個人的にはWebView+ナビゲーションってあまり見たことがない気がするのでその部分の実験ということで見てもらえると良いです。&lt;/p&gt;
&lt;h2 id="webページの準備"&gt;Webページの準備&lt;/h2&gt;
&lt;p&gt;まずはHTML側のソースです。ここで見るべきは、&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;タグについてる&lt;code&gt;callback-to-ios&lt;/code&gt;クラスぐらい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;p&lt;/span&gt;&amp;gt;1ページ目&amp;lt;/&lt;span style="color:#f92672"&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/secondpage.html&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;callback-to-ios&amp;#34;&lt;/span&gt;&amp;gt;2ページ目ヘ&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;続いてJavascriptです。こっちが肝ね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-coffee" data-lang="coffee"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; reportBackToIOS = &lt;span style="color:#a6e22e"&gt;(href)-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; iframe = &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;lt;iframe /&amp;gt;&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;attr&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;src&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;callback://&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;body&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;append&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;iframe&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;iframe&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;remove&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; iframe = &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;.callback-to-ios&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;reportBackToIOS&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;@&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;attr&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;まずリンクのクリック時に&lt;code&gt;reportBackToIOS&lt;/code&gt;を呼び出した上で、falseを返してリンクを辿らないようにしてあります。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;reportBackToIOS&lt;/code&gt;は名前の通りiOSにリンクがタップされたことを知らせる役割を担っています。iOSのUIWebViewではWebView内でURLの読み込みが発生する直前にコールバックを通るんですが、ここではそれを利用しています。&lt;/p&gt;
&lt;p&gt;具体的には、iOSに渡したい情報をURL（の一部）として持った&lt;code&gt;iframe&lt;/code&gt;を作って一旦HTMLのbodyに追加し、すぐに削除していますね。&lt;code&gt;iframe&lt;/code&gt;がbodyに追加されたとき、&lt;code&gt;src&lt;/code&gt;アトリビュートで持っているURL（ここでは、&amp;lsquo;callback://&amp;rsquo; + 遷移先のURL）をiframe内で開こうとするため、WebViewのコールバックが呼ばれることになるわけです。&lt;/p&gt;
&lt;h2 id="ios側の対応"&gt;iOS側の対応&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ViewController&lt;/code&gt;に適当にUIWebViewを置いてあり、&lt;code&gt;ViewController&lt;/code&gt;→&lt;code&gt;ViewController&lt;/code&gt;の遷移をするSegueが&lt;code&gt;next&lt;/code&gt;という名前で定義されているとします（実際にはViewControllerからViewControllerへのSegueは定義できないので、隠しボタンからViewControllerへのSegueです。）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;#define HOST @&amp;#34;http:&lt;/span&gt;&lt;span style="color:#75715e"&gt;//localhost:4000&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; [super viewDidLoad];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; self.webView.delegate &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt; urlstring &lt;span style="color:#f92672"&gt;=&lt;/span&gt; NULL;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt; path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self.segueOptions.stringValue;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(path) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; urlstring &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSString stringWithFormat:&lt;span style="color:#e6db74"&gt;@&amp;#34;%@%@&amp;#34;&lt;/span&gt;, HOST, path];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; urlstring &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSString stringWithFormat:&lt;span style="color:#e6db74"&gt;@&amp;#34;%@%@&amp;#34;&lt;/span&gt;, HOST, &lt;span style="color:#e6db74"&gt;@&amp;#34;/&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; NSURL&lt;span style="color:#f92672"&gt;*&lt;/span&gt; url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSURL URLWithString:urlstring];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; NSURLRequest&lt;span style="color:#f92672"&gt;*&lt;/span&gt; urlRequest &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSURLRequest requestWithURL:url];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; [self.webView loadRequest:urlRequest];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;肝心のコールバックはこんな感じで実装しておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;webView:&lt;/span&gt;(UIWebView &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)webView &lt;span style="color:#a6e22e"&gt;shouldStartLoadWithRequest:&lt;/span&gt;(NSURLRequest &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)request &lt;span style="color:#a6e22e"&gt;navigationType:&lt;/span&gt;(UIWebViewNavigationType)navigationType
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ([[[request URL] scheme] isEqualToString:&lt;span style="color:#e6db74"&gt;@&amp;#34;callback&amp;#34;&lt;/span&gt;]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt; href &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[[request URL] absoluteString] substringFromIndex:&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; [self performSegueWithIdentifier:&lt;span style="color:#e6db74"&gt;@&amp;#34;next&amp;#34;&lt;/span&gt; options:href];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; NO;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; YES;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;shouldStartLoadWithRequest&lt;/code&gt;は新しいリクエストが来た時に通るコールバックで、何もしないときは&lt;code&gt;YES&lt;/code&gt;を返すことで読み込みをスタートさせることができるわけですが、今回は&lt;code&gt;callback://&lt;/code&gt;で始まるURLの場合だけは&lt;code&gt;next&lt;/code&gt;という名前のSegueを実行して&lt;code&gt;NO&lt;/code&gt;を返すことにします。NOを返せばURLの読み込みは行われないので、&lt;code&gt;callback://****&lt;/code&gt;みたいなURLを処理しちゃってエラー、ということも起こりません。&lt;/p&gt;
&lt;p&gt;これで最初に紹介したGIFアニメのようなページ遷移ができるようになりました。便利なような、使いどころ難しいようなそんな感じですが、ネイティブっぽく動かすという目的はなんとなく果たせていますね。&lt;/p&gt;
&lt;h2 id="参考リンク"&gt;参考リンク&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;reportBackToIOS&lt;/code&gt;のところはStackOverflowのこの質問を参考にしました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/14358774/how-can-i-reliably-detect-a-link-click-in-uiwebview" title="ios - How can I reliably detect a link click in UIWebView? - Stack Overflow"&gt;ios - How can I reliably detect a link click in UIWebView? - Stack Overflow&lt;/a&gt;&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4798140287/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/71A24-mU1OL._SL1305_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;クラウドでできるHTML5ハイブリッドアプリ開発 Cordova/Onsen UIで作るiOS/Android両対応アプリ&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>markdown_section_numbering gemをアップデート</title><link>https://blog.piyo.tech/posts/2015-03-19-092955/</link><pubDate>Thu, 19 Mar 2015 09:29:55 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-03-19-092955/</guid><description>&lt;p&gt;昔こんなのを作ったわけだけど、本当に少しだけ足りないなと思うところがあったのでアップデートしました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-07-06-193000"&gt;&amp;lt;img src=&amp;ldquo;&lt;a href="https://capture.heartrails.com/small?https://blog.piyo.tech/posts/2014-07-06-193000%22"&gt;https://capture.heartrails.com/small?https://blog.piyo.tech/posts/2014-07-06-193000&amp;quot;&lt;/a&gt; alt=&amp;ldquo;マークダウンに見出し番号をつけるRuby Gem書いた - ぴよログ&amp;quot;style=&amp;ldquo;border:none;float:left; margin:0;&amp;rdquo; /&amp;gt;&lt;/a&gt;&lt;div style="margin-left:135px;"&gt;&lt;a href="https://blog.piyo.tech/posts/2014-07-06-193000"&gt;マークダウンに見出し番号をつけるRuby Gem書いた - ぴよログ&lt;/a&gt; &lt;a href="http://b.hatena.ne.jp/entry/https://blog.piyo.tech/posts/2014-07-06-193000" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/https://blog.piyo.tech/posts/2014-07-06-193000" alt="はてなブックマーク - マークダウンに見出し番号をつけるRuby Gem書いた - ぴよログ" style="border:none" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br style="clear:left;" /&gt;&lt;/p&gt;
&lt;p&gt;上の記事で、「Automatorと連携して選択中のテキストを変換する」っていう使い方について書いたのだけれど、それをやるには標準入力を受け取ってgemのクラスに渡して標準出力するっていうスクリプトをわざわざgem外で用意する必要があったわけです。&lt;/p&gt;
&lt;p&gt;そのときは気が回っていなかったんだけど、そんな機能はgemに実行ファイルとして含めればいいということにようやく気がついたので今回のアプデに至りました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://rubygems.org/gems/markdown_section_numbering/versions/1.1.0" title="markdown_section_numbering | RubyGems.org | your community gem host"&gt;markdown_section_numbering | RubyGems.org | your community gem host&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;バージョン1.1をインストールすると&lt;code&gt;markdown-section-numbering&lt;/code&gt;というコマンドが使えるようになります。このコマンドにMarkdown形式のテキストを与えると番号付きのマークダウンが標準出力に返ってきます。&lt;/p&gt;
&lt;p&gt;中身は単純でこんな感じ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/usr/bin/env ruby&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;begin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;markdown_section_numbering&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;rescue&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;LoadError&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;markdown_section_numbering&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;$stdout&lt;span style="color:#f92672"&gt;.&lt;/span&gt;write &lt;span style="color:#66d9ef"&gt;MarkdownSectionNumbering&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;convert($stdin&lt;span style="color:#f92672"&gt;.&lt;/span&gt;read)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4798139823/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/7181tvgTVaL._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;Effective Ruby&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>Rubyで濁点/半濁点が分離した文字を1文字に統一するには</title><link>https://blog.piyo.tech/posts/2015-03-17-072707/</link><pubDate>Tue, 17 Mar 2015 07:27:07 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-03-17-072707/</guid><description>&lt;p&gt;Macのファイル名周りで発生するのでハマったことがある人もいると思うんだけど、ひらがなやカタカナの濁音や半濁音の文字を表現するのに2文字分使われていることがあったりする。&lt;/p&gt;
&lt;p&gt;例えばFinderで&lt;code&gt;ぱぴぷぺぽ.txt&lt;/code&gt;というファイルを作ってEmacsで開いてみるとこんなふうになる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/6e4d5363-6840-4eca-8381-25dcc65e5a8e/7843831515fa7388896dc98fe66bfa1f/deep/0/nfd.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Rubyでもこの手のファイル名から文字列を作ったりすると同じようなことが起こる。例えばこんな感じで。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/15f93b21-caea-4fdb-b074-1527a4545651/844b81130d5e1c7fe1016f85ce1f6d9d/deep/0/nfc-nfd.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;同じ文字列に見えて全く違うってことが起こる。こういう文字列がデータベースに入っていると検索にかからないことがあるし他にも色々困ったことになりそうな感じがする。&lt;/p&gt;
&lt;p&gt;なお、この手の話を真面目に語るには僕の知識は足りないので今回はどうやって回避するかを書くだけに留めるけど、軽く触れておくとUnicodeの正規化に関係する現象らしいということがわかった。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ja.wikipedia.org/wiki/Unicode%E6%AD%A3%E8%A6%8F%E5%8C%96" title="Unicode正規化 - Wikipedia"&gt;Unicode正規化 - Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="対策"&gt;対策&lt;/h2&gt;
&lt;p&gt;このタイプの文字列が入力として入ってきそうな箇所で正規化の形式を変換しておくことで対処できた。変換にはActiveSupportのメソッドを使用した。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://apidock.com/rails/ActiveSupport/Multibyte/Unicode/normalize" title="normalize (ActiveSupport::Multibyte::Unicode) - APIdock"&gt;normalize (ActiveSupport::Multibyte::Unicode) - APIdock&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 例えばファイル名から文字列をとってくる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;basename(textfile, &lt;span style="color:#e6db74"&gt;&amp;#39;.txt&amp;#39;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# &amp;#34;は゜ひ゜ふ゜へ゜ほ゜&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveSupport&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Multibyte&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Unicode&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;normalize(filename, &lt;span style="color:#e6db74"&gt;:c&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# &amp;#34;ぱぴぷぺぽ&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Azure Storage QueueでBase64関係の例外</title><link>https://blog.piyo.tech/posts/2015-01-26-110531/</link><pubDate>Mon, 26 Jan 2015 11:05:31 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-01-26-110531/</guid><description>&lt;p&gt;バッチ処理のためのメッセージキューとしてMicrosoftのAzure Storage Queueを使っている。C#での使い勝手は言わずもがなだし、Rubyでも最低限のSDKが提供されているのでAWSと比べて使い勝手が悪いということはない。&lt;/p&gt;
&lt;p&gt;ただ、Rubyでメッセージを追加してC#でメッセージを取り出すということをやっていたらエンコード関係ではまったのでその部分について今日はメモしておきたい。&lt;/p&gt;
&lt;h1 id="例外が発生するケース"&gt;例外が発生するケース&lt;/h1&gt;
&lt;h2 id="rubyでメッセージ追加"&gt;Rubyでメッセージ追加&lt;/h2&gt;
&lt;p&gt;基本的には公式のドキュメントを参考にした。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://azure.microsoft.com/ja-jp/documentation/articles/storage-ruby-how-to-use-queue-storage/"&gt;キュー サービスを使用する方法 (Ruby) | Microsoft Azure&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;メッセージを追加はRailsアプリケーションから行いたかったので、上のドキュメントを参考にしてこんな風にかいた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# config/initializer/azure.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Azure&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;configure &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;config&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;storage_account_name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;AZURE_STORAGE_ACCOUNT&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;storage_access_key &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;AZURE_STORAGE_ACCESS_KEY&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;AZURE_QUEUE_SERVICE&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Azure&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;QueueService&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;AZURE_QUEUE&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;AZURE_QUEUE&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;AZURE_QUEUE_SERVICE&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create_queue(&lt;span style="color:#66d9ef"&gt;AZURE_QUEUE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# in controller&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;AZURE_QUEUE_SERVICE&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create_message(&lt;span style="color:#66d9ef"&gt;AZURE_QUEUE&lt;/span&gt;, @model&lt;span style="color:#f92672"&gt;.&lt;/span&gt;id&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_s)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="cでメッセージ取り出し"&gt;C#でメッセージ取り出し&lt;/h2&gt;
&lt;p&gt;同じく公式ドキュメントを参考にして、メッセージを取り出す部分を書いた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cs" data-lang="cs"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Func()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; sc = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; StorageCredentials( Constants.AZURE_STOREGE_ACCOUNT, Constants.AZURE_STOREGE_ACCSESS_KEY );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; storageAccount = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; CloudStorageAccount( sc, &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; queueClient = storageAccount.CreateCloudQueueClient();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; queue = queueClient.GetQueueReference( Constants.AZURE_QUEUE );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; queue.CreateIfNotExists();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; timeSpan = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; System.TimeSpan(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; message = queue.GetMessage( timeSpan );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; messsage.AsString;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="例外発生"&gt;例外発生&lt;/h2&gt;
&lt;p&gt;実装はめちゃくちゃ簡単だしこれで動くだろうと思ったのだが、&lt;code&gt;message.AsString&lt;/code&gt;の部分で&lt;code&gt;Base-64 文字配列または文字列の長さが無効です。&lt;/code&gt;という例外が発生してしまった。しかもAzure Storage Explorerなどのツールでも同じ例外が起こった。&lt;/p&gt;
&lt;p&gt;SDKのソースを見てみたところ、メッセージにはエンコードした文字列かそうでないものかのタイプを持っているらしいが、どうやら今回のケースでは部エンコードされていない文字列であるにもかかわらず、タイプがエンコード済となっていて、想定外のコードを通ることになってしまっていたらしい。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Azure/azure-storage-net/blob/master/Lib/Common/Queue/CloudQueueMessage.Common.cs"&gt;azure-storage-net/CloudQueueMessage.Common.cs at master · Azure/azure-storage-net&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cs" data-lang="cs"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// Gets the content of the message, as a string.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// &amp;lt;value&amp;gt;A string containing the message content.&amp;lt;/value&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; AsString
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.MessageType == QueueMessageType.RawString)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.RawString;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;[] messageData = Convert.FromBase64String(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.RawString);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; utf8Encoder.GetString(messageData, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, messageData.Length);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="回避策"&gt;回避策&lt;/h1&gt;
&lt;p&gt;これもソースをみたらわかったんだけど、RubyのSDKでエンキューするときにエンコードオプションを指定できるみたいだった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;create_message&lt;/span&gt;(queue_name, message_text, options&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; query &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; options&lt;span style="color:#f92672"&gt;.&lt;/span&gt;empty?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; query&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;visibilitytimeout&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; options&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:visibility_timeout&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; options&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:visibility_timeout&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; query&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;messagettl&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; options&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:message_ttl&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; options&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:message_ttl&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; query&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;timeout&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; options&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:timeout&lt;/span&gt;&lt;span style="color:#f92672"&gt;].&lt;/span&gt;to_s &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; options&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:timeout&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; uri &lt;span style="color:#f92672"&gt;=&lt;/span&gt; messages_uri(queue_name, query)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; body &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Serialization&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;message_to_xml(message_text, options&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:encode&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; call(&lt;span style="color:#e6db74"&gt;:post&lt;/span&gt;, uri, body, {})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;options[:encode]&lt;/code&gt;の部分！&lt;/p&gt;
&lt;p&gt;そういうわけで、最初の実装にオプションを追加してこうしてあげればよかった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# in controller&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;AZURE_QUEUE_SERVICE&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create_message(&lt;span style="color:#66d9ef"&gt;AZURE_QUEUE&lt;/span&gt;, @model&lt;span style="color:#f92672"&gt;.&lt;/span&gt;id&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_s, &lt;span style="color:#e6db74"&gt;encode&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例外もでなくなりました。めでたし！&lt;/p&gt;</description></item><item><title>ActiveRecordの日付カラムでレコードを絞り込める by_star gem</title><link>https://blog.piyo.tech/posts/2015-01-14-232659/</link><pubDate>Wed, 14 Jan 2015 23:26:59 +0900</pubDate><guid>https://blog.piyo.tech/posts/2015-01-14-232659/</guid><description>&lt;p&gt;久々に便利なの見つけた。有名だったりするのかな？&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/radar/by_star"&gt;radar/by_star&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;by_starはモデルの絞り込みに使えるgemで、ActiveRecordとMongoidで使える。&lt;/p&gt;
&lt;p&gt;ある期間内のレコードだけを表示したり集計を取ったりというときに使える。自分でも大したコードにはならないんだけど汎用的なものなのでこのgemを使うのが良いでしょう。&lt;/p&gt;
&lt;p&gt;githubのREADMEを見れば一目瞭然なのだけど、一応紹介しておく。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Post&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;by_year(&lt;span style="color:#ae81ff"&gt;2013&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# all posts in 2013&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Post&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;before(&lt;span style="color:#66d9ef"&gt;Date&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;today) &lt;span style="color:#75715e"&gt;# all posts for before today&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Post&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;yesterday &lt;span style="color:#75715e"&gt;# all posts in 2013&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Post&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;between_times(&lt;span style="color:#66d9ef"&gt;Time&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;zone&lt;span style="color:#f92672"&gt;.&lt;/span&gt;now &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hours, &lt;span style="color:#75715e"&gt;# all posts in last 3 hours&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Time&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;zone&lt;span style="color:#f92672"&gt;.&lt;/span&gt;now)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;@post&lt;span style="color:#f92672"&gt;.&lt;/span&gt;next &lt;span style="color:#75715e"&gt;# next post after a given post&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;カラムを指定しない場合は&lt;code&gt;created_at&lt;/code&gt;が使われる。自分で定義したカラムを使いたいなら次のようにすればOK。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Post&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;by_year(&lt;span style="color:#ae81ff"&gt;2013&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;field&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:hogehoge_at&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# hogehoge_at という Date/DateTimeなカラムを使用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こういう絞り込みでよくあるのは○年○月のデータ一覧みたいなのだと思うのでそのやりだけ簡単に書いておく。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Post&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;by_year &lt;span style="color:#75715e"&gt;# 今年のpost&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Post&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;by_month &lt;span style="color:#75715e"&gt;# 今月のpost&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Post&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;by_month(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 今年の4月&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Post&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;by_month(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;year&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2012&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 2014年の4月&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;自前カラムを使うならscopeにしとくと便利だと思う。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Post&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; scope &lt;span style="color:#e6db74"&gt;:by_year_month&lt;/span&gt;, &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;(y, m) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; by_month(m, &lt;span style="color:#e6db74"&gt;year&lt;/span&gt;: y, &lt;span style="color:#e6db74"&gt;field&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:hogehoge_at&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実装を見てみると最終的には&lt;code&gt;between_times_query&lt;/code&gt;ていうメソッドに行き着くっぽかった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;between_times_query&lt;/span&gt;(start, finish, options&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; start_field &lt;span style="color:#f92672"&gt;=&lt;/span&gt; by_star_start_field(options)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; end_field &lt;span style="color:#f92672"&gt;=&lt;/span&gt; by_star_end_field(options)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; scope &lt;span style="color:#f92672"&gt;=&lt;/span&gt; by_star_scope(options)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; scope &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; options&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:strict&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; start_field &lt;span style="color:#f92672"&gt;==&lt;/span&gt; end_field
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; scope&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;start_field&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &amp;gt;= ? AND &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;end_field&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;= ?&amp;#34;&lt;/span&gt;, start, finish)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; scope&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;end_field&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &amp;gt; ? AND &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;start_field&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt; ?&amp;#34;&lt;/span&gt;, start, finish)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; scope &lt;span style="color:#f92672"&gt;=&lt;/span&gt; scope&lt;span style="color:#f92672"&gt;.&lt;/span&gt;order(options&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:order&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; options&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:order&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; scope
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;単機能をいい感じに切り出せてて良さげです。この発想は見習うとこありそう。&lt;/p&gt;</description></item><item><title>Grapeで独自のレスポンスヘッダーを追加する</title><link>https://blog.piyo.tech/posts/2014-11-17-134021/</link><pubDate>Mon, 17 Nov 2014 13:40:21 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-11-17-134021/</guid><description>&lt;p&gt;先日こんなエントリーを書いた。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-10-29-153203"&gt;Grapeを使ったAPIで独自のエラーコードも一緒に返す工夫 - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;その後色々調べているうちに、エラーコードはレスポンスヘッダーに入れたらいいよ～という話を見かけたので、その方針を採るかどうかは別として実現方法を調べてみた。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.yappo.jp/yappo/archives/000829.html"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://blog.yappo.jp/yappo/archives/000829.html" alt="YappoLogs: 2014年に向けた JSON API の実装の方向性と X-JSON-Status 改め X-API-Status header のご提案" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://blog.yappo.jp/yappo/archives/000829.html"&gt;YappoLogs: 2014年に向けた JSON API の実装の方向性と X-JSON-Status 改め X-API-Status header のご提案&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://blog.yappo.jp/yappo/archives/000829.html" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://blog.yappo.jp/yappo/archives/000829.html" alt="はてなブックマーク - YappoLogs: 2014年に向けた JSON API の実装の方向性と X-JSON-Status 改め X-API-Status header のご提案" title="はてなブックマーク - YappoLogs: 2014年に向けた JSON API の実装の方向性と X-JSON-Status 改め X-API-Status header のご提案" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;調べたところによるとgem、GrapeにはHTTPヘッダーを追加するインターフェースが用意されているらしい。エラー時にヘッダーを追加するには&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;error! &lt;span style="color:#e6db74"&gt;&amp;#39;Unauthorized&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;401&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;X-Error-Detail&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Invalid token.&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;と、こんな風に書けばいいそうだ。&lt;/p&gt;
&lt;h1 id="以前の続きから"&gt;以前の続きから&lt;/h1&gt;
&lt;p&gt;先ほどリンクを貼った自分のエントリーではエラーフォーマッターをカスタマイズした上でヘルパーを使ってJSONのレスポンスを返す感じにしていた。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-10-29-153203"&gt;Grapeを使ったAPIで独自のエラーコードも一緒に返す工夫 - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;HTTPヘッダーに項目を追加するためにはヘルパーメソッドをちょちょっと変更してあげるだけで済みそうだ。&lt;/p&gt;
&lt;h2 id="before"&gt;before&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;my_error!&lt;/span&gt;(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; error!({&lt;span style="color:#e6db74"&gt;message&lt;/span&gt;: error&lt;span style="color:#f92672"&gt;.&lt;/span&gt;message, &lt;span style="color:#e6db74"&gt;code&lt;/span&gt;: error&lt;span style="color:#f92672"&gt;.&lt;/span&gt;code}, error&lt;span style="color:#f92672"&gt;.&lt;/span&gt;status)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="after"&gt;after&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;my_error!&lt;/span&gt;(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; error!({&lt;span style="color:#e6db74"&gt;message&lt;/span&gt;: error&lt;span style="color:#f92672"&gt;.&lt;/span&gt;message, &lt;span style="color:#e6db74"&gt;code&lt;/span&gt;: error&lt;span style="color:#f92672"&gt;.&lt;/span&gt;code}, error&lt;span style="color:#f92672"&gt;.&lt;/span&gt;status,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;X-API-Status&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; error&lt;span style="color:#f92672"&gt;.&lt;/span&gt;code&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_s,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;X-API-Error-Message&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; error&lt;span style="color:#f92672"&gt;.&lt;/span&gt;message)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とまあ、大体こんな感じ。1つ目の引数と内容的にはダブっているし、ヘッダーのフィールド名？っていうのかな？それも適当なのでもうちょっとブラッシュアップする必要がりそうだが、一応レスポンスヘッダーにエラー詳細情報を載せることはできそうだ。&lt;/p&gt;
&lt;p&gt;このAPIを呼び出すクライアントを実装するのであればレスポンスヘッダーを解析して、HTTPのStatusとこの&lt;code&gt;X-API-Status&lt;/code&gt;を見て処理を分岐すればいいんだと思う。確かにJSONのパースは不要になるからこちらのほうが（レスポンスBodyにJSONとしてエラー詳細を含めるよりも）いい気がしなくもない。&lt;/p&gt;
&lt;p&gt;クライアントの実装も自分でやることになるので、サーバー側の実装はどちらの手段も提供するようにしておいてあとから決めることにしよう。&lt;/p&gt;</description></item><item><title>Grapeを使ったAPIで独自のエラーコードも一緒に返す工夫</title><link>https://blog.piyo.tech/posts/2014-10-29-153203/</link><pubDate>Wed, 29 Oct 2014 15:32:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-10-29-153203/</guid><description>&lt;p&gt;RailsでGrapeをっていうgemを使うとちょちょいっとAPIが作れるという話は以前にも書いた。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2014-05-12-204748"&gt;RailsのGrapeとJbuilderでAPI開発 - ぴよログ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2014-05-15-201100"&gt;Grapeを使ったAPI実装でのネストやパラメータ - ぴよログ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;このときはお試しだったんだけど、今回ちょっと本格的に書くかもという感じになってちゃんとエラー処理とかもしないといけなくなった。それにあたり試行錯誤したことをちょっとメモっておこうと思う。&lt;/p&gt;
&lt;h1 id="普通にエラーを返す"&gt;普通にエラーを返す&lt;/h1&gt;
&lt;p&gt;以下フォーマットはJSONだとする。&lt;/p&gt;
&lt;p&gt;エラーは&lt;code&gt;error!&lt;/code&gt;メソッドによって発生させることができる。&lt;code&gt;error!&lt;/code&gt;は例外を使っているようなので呼んだ時点で処理が中断するため、エラー発生後の処理のことは考えなくていい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;API&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Grape&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;API&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; resource &lt;span style="color:#e6db74"&gt;:users&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; get &lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; error!(&lt;span style="color:#e6db74"&gt;&amp;#34;Unauthorized! Invalid token.&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;401&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このAPIからはステータスコード401で次のようなJSONが戻ってくる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;error&amp;#34;&lt;/span&gt; : &lt;span style="color:#e6db74"&gt;&amp;#34;Unauthorized! Invalid token.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="独自のエラーコードも戻したくなる"&gt;独自のエラーコードも戻したくなる&lt;/h1&gt;
&lt;p&gt;具体的にどのようなエラーが起こったか、という詳細はエラーメッセージやHTTPのステータスコードだけで判別するのは厳しい。アプリケーション独自のエラーコードを使ってもっと詳細な情報まで返してあげたほうが呼び出し元のクライアントためになると思う。&lt;/p&gt;
&lt;p&gt;そのためにGrapeのErrorFormatterというのを使える。文字通りエラー出力のフォーマットをカスタマイズするための物だと思う。&lt;/p&gt;
&lt;p&gt;こんなFormatterを定義して、&lt;code&gt;error_formatter&lt;/code&gt;に指定してみた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;module&lt;/span&gt; ErrorFormatter
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;call&lt;/span&gt; message, backtrace, options, env
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; message&lt;span style="color:#f92672"&gt;.&lt;/span&gt;is_a?(&lt;span style="color:#66d9ef"&gt;Hash&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; { &lt;span style="color:#e6db74"&gt;error&lt;/span&gt;: message&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:message&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;code&lt;/span&gt;: message&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:code&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; }&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; { &lt;span style="color:#e6db74"&gt;error&lt;/span&gt;: message }&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;API&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Grape&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;API&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; error_formatter &lt;span style="color:#e6db74"&gt;:json&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;ErrorFormatter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; resource &lt;span style="color:#e6db74"&gt;:users&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;1つめの引数&lt;code&gt;message&lt;/code&gt;には&lt;code&gt;error!&lt;/code&gt;メソッドの第1引数がそのまま渡るので、ここにHashを渡してしまおうというわけ。&lt;/p&gt;
&lt;p&gt;使い方はこうなる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;error!({&lt;span style="color:#e6db74"&gt;message&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Unauthorized!&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;code&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;123&lt;/span&gt;}, &lt;span style="color:#ae81ff"&gt;401&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;レスポンスはこんな感じになる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;error&amp;#34;&lt;/span&gt; : &lt;span style="color:#e6db74"&gt;&amp;#34;Unauthorized!&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;code&amp;#34;&lt;/span&gt; : &lt;span style="color:#ae81ff"&gt;123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとはドキュメントとかを整備しておけば123番のエラーはこれだ！みたいなのがより詳細に判別できるようになると思う。&lt;/p&gt;
&lt;h1 id="ヘルパーにする"&gt;ヘルパーにする&lt;/h1&gt;
&lt;p&gt;毎度Hashを組み立てるのが面倒だからGrapeのヘルパー機構を使ってもう少し楽に呼び出せる方が良さそう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;helpers &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;my_error!&lt;/span&gt;(message, error_code, status)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; error!({&lt;span style="color:#e6db74"&gt;message&lt;/span&gt;: message, &lt;span style="color:#e6db74"&gt;code&lt;/span&gt;: error_code}, status)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;my_error!(&lt;span style="color:#e6db74"&gt;&amp;#34;Unauthorized!&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;123&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;401&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# こう呼べる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="エラー定義をまとめる"&gt;エラー定義をまとめる&lt;/h1&gt;
&lt;p&gt;APIのいろいろな箇所で&lt;code&gt;my_error!(うんぬん)&lt;/code&gt;があるのは生じい鬱陶しいんじゃないかと思う。あそこのエラーメッセージちょっと変えたいなと思ってもいろいろなところから探さないといけないし。&lt;/p&gt;
&lt;p&gt;ということで、エラー定義を一箇所にまとめる方法を模索している。今のところ&lt;code&gt;rails_config&lt;/code&gt;gem を使って、環境によらずアプリケーション全体でその設定を使いまわすような感じで作ってみている。&lt;/p&gt;
&lt;p&gt;RailsConfigの導入は公式を見れば十分だと思う。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/railsconfig/rails_config"&gt;railsconfig/rails_config&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;導入できたら全体の設定ファイルである&lt;code&gt;config/settings.yml&lt;/code&gt;にいろいろ書いていく。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;errors&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;unauthorized_token&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;message&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Unauthorized. Invalid token.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;code&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;124&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;status&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;401&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;unauthorized_user&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;message&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Unauthorized. Invalid user.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;code&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;125&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;status&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;401&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;RailsConfigにより、上のように書いた内容はアプリケーション内で&lt;code&gt;Settings.errors.unauthorized_token.message&lt;/code&gt;などとして呼び出せるため、エラー箇所がすっきりするんじゃないかと思う。&lt;/p&gt;
&lt;p&gt;最終的には&lt;code&gt;my_error!&lt;/code&gt;を書き換えていい感じにしてみた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;my_error!&lt;/span&gt;(error) 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; error!({&lt;span style="color:#e6db74"&gt;message&lt;/span&gt;: error&lt;span style="color:#f92672"&gt;.&lt;/span&gt;message, &lt;span style="color:#e6db74"&gt;code&lt;/span&gt;: error&lt;span style="color:#f92672"&gt;.&lt;/span&gt;code}, error&lt;span style="color:#f92672"&gt;.&lt;/span&gt;status)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 呼び出し&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;my_error!(&lt;span style="color:#66d9ef"&gt;Settings&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;errors&lt;span style="color:#f92672"&gt;.&lt;/span&gt;unauthorized_token)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;定義も一覧しやすくなったし、呼び出しもすっきりした。まあまあいいところに落ち着いたと思う。&lt;/p&gt;
&lt;p&gt;もっといい方法、一般的な方法があったら知りたいです。&lt;/p&gt;</description></item><item><title>Magitてきとう入門</title><link>https://blog.piyo.tech/posts/2014-09-06-200000/</link><pubDate>Sat, 06 Sep 2014 20:00:09 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-09-06-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/ad8cfbe1-0eeb-47ba-a9fa-037080db7065/bfacc990924a4f0425040246a81837df/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-09-03-21-16.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;magitという拡張があるのは知っていたしインストールはしていたけれどハードルが高くて使っていなかった。コマンドラインも好きだし十分使えていたので。この間もこういうエントリーを書いたばかり。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-08-31-200000"&gt;gitコマンドライン厨の俺だけどヘルプ見ないと使えないコマンドが多いのでメモ - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ところで今日、ある拍子に「Diff見づれえ！」って思ってしまったから試しに使ってみることにした。&lt;/p&gt;
&lt;h1 id="基本は2つかな"&gt;基本は2つ（かな？）&lt;/h1&gt;
&lt;p&gt;Magitは色々なことができるが、最初は最低限の使いかたを知るほうがいい。普通にコードを書いていてそこから使いうる基本的なコマンドはこの2つなのかな？というのがちょっと使ってみた感想です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;magit-status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;magit-log&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="magit-status"&gt;magit-status&lt;/h1&gt;
&lt;p&gt;Magitの全てはここから始まるぐらいの勢いで重要なコマンドのよう。このコマンドを叩くと現在のワーキングツリーの様子が表示される。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/1ecddd73-f5c5-4515-8e7b-e0d1efdc4984/f4ea85d216106ec8dd6bf74bb2e8a28d/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-09-03-20-35.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;この画面で色々操作することになるわけ。&lt;/p&gt;
&lt;p&gt;例えば上のスクショではUnstaged ChangesやStaged Changesなファイルの名前が出ているんだけど、ファイルにカーソルを合わせて&lt;code&gt;Tab&lt;/code&gt;キーを押すとこの画面内でDiffを見ることができる。さらに他のキー操作でIndexへの追加や取り消し、PullやPush、Stashの操作などもできたりする。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b13fb080-7aee-4abb-bd80-b9f2b74ac17c/600b76e53221ee38ab455794fa84255f/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-09-03-20-38.png" alt=""&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作&lt;/th&gt;
&lt;th&gt;コマンド&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Diffを表示/非表示&lt;/td&gt;
&lt;td&gt;Tab&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;カーソルのファイルをStage&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;全ての変更をStage&lt;/td&gt;
&lt;td&gt;S&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;カーソルのファイルをUnstage&lt;/td&gt;
&lt;td&gt;u&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;全ての変更をUnstage&lt;/td&gt;
&lt;td&gt;U&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ファイルの変更を元に戻す&lt;/td&gt;
&lt;td&gt;v&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;カーソルのファイルを.gitignoreに追加する&lt;/td&gt;
&lt;td&gt;i&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;このぐらいのコマンドを覚えておけば基本的なことができるようになるから日常的に使えるようにあってくる。込み入ったことをしたくなったとしてもその都度覚えるコマンドが少しで済むので躓くことはなくなると思う。&lt;/p&gt;
&lt;h1 id="magit-log"&gt;magit-log&lt;/h1&gt;
&lt;p&gt;もう1個使いそうなのが&lt;code&gt;magit-log&lt;/code&gt;コマンド。名前の通りコミットログを閲覧するためのもの。実行するとこんな画面が出る。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/229f2b07-f906-4c7c-8bc3-ebd7487e986e/fa6ca8387c17b35cbd3f20419a784005/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-09-03-21-03.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;n&lt;/code&gt;と&lt;code&gt;p&lt;/code&gt;でコミットを次々に移動でき、もう1つのWindowにはそのときのDiffが展開された状態でこんな具合に表示される。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/dc9f38ae-1656-4cf9-a8ed-1b46fb2a43e7/74012145af838caa32d92737bf35c43b/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-09-03-21-04.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;いい感じ。&lt;/p&gt;
&lt;h1 id="色"&gt;色&lt;/h1&gt;
&lt;p&gt;さてこんな便利そうなMagitだけど、デフォルトの色が超見づらいので僕は早速色を変えた。上のスクショも実は色を変えたあとだ。変える前はこんな感じだった。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/6ad35979-c818-4d67-b38f-7d9abce39e2d/3e282ef70cea7a5c59c25d30e1ec4e50/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-09-03-21-07.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;個人的にEmacsではbackground-colorが付いてるのがものすごく見づらいと思う。だから次のように変えた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;;; 文字色変更&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;(set-face-foreground &lt;span style="color:#e6db74"&gt;&amp;#39;magit-diff-add&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;#00FF00&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;; 追加行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;(set-face-foreground &lt;span style="color:#e6db74"&gt;&amp;#39;magit-diff-del&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;#FF0000&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;; 削除行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;(set-face-foreground &lt;span style="color:#e6db74"&gt;&amp;#39;magit-diff-file-header&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;#00FFFF&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;; Diffのファイル名部分&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;(set-face-foreground &lt;span style="color:#e6db74"&gt;&amp;#39;magit-diff-hunk-header&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;#00AADD&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;; Diffのhunk部分&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;(set-face-foreground &lt;span style="color:#e6db74"&gt;&amp;#39;magit-section-title&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;#FF00FF&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;; 見出し部分&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;;; 背景色変更&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;(set-face-background &lt;span style="color:#e6db74"&gt;&amp;#39;magit-item-highlight&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;#282822&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;; 選択行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;(set-face-background &lt;span style="color:#e6db74"&gt;&amp;#39;magit-diff-add&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;#282822&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;; 追加行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;(set-face-background &lt;span style="color:#e6db74"&gt;&amp;#39;magit-diff-del&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;#282822&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;; 削除行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;(set-face-background &lt;span style="color:#e6db74"&gt;&amp;#39;magit-diff-file-header&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;#282822&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;; Diffのファイル名部分&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;(set-face-background &lt;span style="color:#e6db74"&gt;&amp;#39;magit-diff-hunk-header&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;#282822&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;; Diffのhunk部分&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;(set-face-background &lt;span style="color:#e6db74"&gt;&amp;#39;magit-section-title&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;#282822&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;; 見出し部分&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;背景色はEmacsのテーマに合わせてある。このほうが断然見やすい。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://magit.github.io/master/magit.html#Status"&gt;Magit User Manual&lt;/a&gt;&lt;/p&gt;</description></item><item><title>ボタン以外（UILabelとか）をタップしたいなら透明ボタンがいいかも</title><link>https://blog.piyo.tech/posts/2014-09-05-200000/</link><pubDate>Fri, 05 Sep 2014 20:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-09-05-200000/</guid><description>&lt;p&gt;iOS開発でボタン以外の要素をタップさせたくなることがたまにあるかもしれない。例えばラベルとか画像とかね。&lt;/p&gt;
&lt;p&gt;そういった場合によく取られる方法はもしかしたら&lt;code&gt;touchesBegan&lt;/code&gt;や&lt;code&gt;touchesEnded&lt;/code&gt;のイベントを使うことかもしれない。けれど、タッチ系のイベントで自分で何とかしようとするとタップしたあと領域外で離したときとかその逆の動きとかで微妙に挙動がうまくいかないので操作感も悪くなってしまう。&lt;/p&gt;
&lt;p&gt;やはりボタン系の操作はUIButtonが最強なのでここはUIButtonを透明にしてしまって、触らせたい要素の上におけばいいじゃないか。&lt;/p&gt;
&lt;p&gt;例えばUIImageViewをタップさせたいならこういう↓ふうにまったく同じ大きさのボタンを作って、ボタンの文字をなくして背景色を透明にしてしまう（デフォルト透明）。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/d8a0df11-64df-440f-8d53-efe422714efe/b801918c3f162e0cb19b88262acc4427/deep/0/button.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ボタンのほうが上にある感じ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/28032c1d-03a7-4730-831f-e1f2ec11cc6a/c0371437cbb9b32a59bb9ffe121bf678/deep/0/button.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;あとは普通にUIButtonのTouchUpInsideを受け取ればOK。あたかも画像をタップしているようにみえる。&lt;/p&gt;</description></item><item><title>Chromeで使うカメラを外付けのWebカメラに切り替える</title><link>https://blog.piyo.tech/posts/2014-09-04-200000/</link><pubDate>Thu, 04 Sep 2014 20:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-09-04-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/af02e823-80aa-46d8-b85c-b6cd1c8808a5/5477506cfc4202be5ba345f9daabb512/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-09-03-9-09.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Skypeのようなアプリでは設定でビデオ通話のときのカメラを切り替えることができる。Hangoutのようなサービスを使うときにはブラウザからもカメラを使うが、ブラウザが使うカメラも当然切り替えることができる。&lt;/p&gt;
&lt;p&gt;今回はGoogle Chromeの設定方法をメモしておく。探すのに手間どったので。&lt;/p&gt;
&lt;p&gt;Google Chromeの右上にある3本線のボタン（ハンバーガーメニュー的な？）を押し、「設定」→「詳細設定を表示」→「コンテンツの設定」と進む。&lt;/p&gt;
&lt;p&gt;少しスクロールすると「メディア」という項目があるので、そこのカメラのところで切り替えられる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/33d62eba-9af6-478a-b58f-74ba65d07816/c56c00078401a0355ac1efa8d7102960/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-09-03-8-58.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>今更Objective-C、ブロックをプロパティにして呼び出すメモ</title><link>https://blog.piyo.tech/posts/2014-09-03-200000/</link><pubDate>Wed, 03 Sep 2014 20:00:04 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-09-03-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/6456362f-92db-4740-b285-e167ede8d392/7e1aa119c261b9db4cbcb739df6e33de/deep/0/xcode.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;コールバック的に呼びたい処理をブロックプロパティにして使う方法。&lt;/p&gt;
&lt;h1 id="ヘッダー"&gt;ヘッダー&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;void&lt;/span&gt; (&lt;span style="color:#f92672"&gt;^&lt;/span&gt;Handler)(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyViewController&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;UIViewController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;copy&lt;/span&gt;) Handler handler;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;IBAction&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;buttonTapped:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)sender;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="実装"&gt;実装&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;IBAction&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;buttonTapped:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)sender {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; self.handler();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="使う側"&gt;使う側&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;func&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; MyViewController&lt;span style="color:#f92672"&gt;*&lt;/span&gt; myVC &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ...;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; myVC.handler &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// do something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;MyViewController&lt;/code&gt;にはボタンがあってボタンが呼ばれたときに何かするコールバックみたいなイメージ。ブロック周りの書き方はつい忘れてしまうのでスニペット的な目的でここに残しておく。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4797368276/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/61q6pahYciL._SL1114_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;詳解 Objective-C 2.0 第3版&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>Segueによる画面遷移を便利にするTKRSegueOptions</title><link>https://blog.piyo.tech/posts/2014-09-02-200000/</link><pubDate>Tue, 02 Sep 2014 20:00:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-09-02-200000/</guid><description>&lt;p&gt;4月ぐらいにスライドで見ていいなーと思ったんだけど、最近初めて使ってみてやはり便利だったので整理しておく。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.tokoro.me/posts/improve-storyboard-segue/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;https://www.tokoro.me/posts/improve-storyboard-segue/&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;span class="truncate"&gt;www.tokoro.me&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;余談だけどスライドでみたときはTKRIntentって名前だったんだけど、わかりやすさのために名前変えたんですかね。&lt;/p&gt;
&lt;p&gt;どんなときに便利かっていうと、個人的にはテーブルビューでセルを選択して次の画面に行きたいときに、選択したセルに関連する情報とかを次のViewControllerに渡したいときかなと思う。&lt;/p&gt;
&lt;p&gt;TKRSegueOptionsを使わないときは、ViewControllerを生成してidを渡して画面遷移するっていうやり方をしてた気がする。もっとスマートな方法があったかもしれないが。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;tableView:&lt;/span&gt;(UITableView &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)tableView &lt;span style="color:#a6e22e"&gt;didSelectRowAtIndexPath:&lt;/span&gt;(NSIndexPath &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)indexPath
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; MyViewController&lt;span style="color:#f92672"&gt;*&lt;/span&gt; viewController &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[MyViewController alloc] initWithNibName:&lt;span style="color:#e6db74"&gt;@&amp;#34;MyViewController&amp;#34;&lt;/span&gt; bundle:nil];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; viewController.index &lt;span style="color:#f92672"&gt;=&lt;/span&gt; indexPath.row;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; [self.navigationController pushViewController:viewController animated:YES];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これがTKRSegueOptionsを使うとこんな感じでいける。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;tableView:&lt;/span&gt;(UITableView &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)tableView &lt;span style="color:#a6e22e"&gt;didSelectRowAtIndexPath:&lt;/span&gt;(NSIndexPath &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)indexPath
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; [self performSegueWithIdentifier:&lt;span style="color:#e6db74"&gt;@&amp;#34;Design&amp;#34;&lt;/span&gt; options:&lt;span style="color:#ae81ff"&gt;@{&lt;/span&gt;&lt;span style="color:#e6db74"&gt;@&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;[NSNumber numberWithInteger:indexPath.row]&lt;span style="color:#ae81ff"&gt;}&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;画面遷移自体はStoryboardでくっつけたSegueをIdentifier経由で呼べばよくて、移動先で&lt;code&gt;self.segueOptions[@&amp;quot;index&amp;quot;];&lt;/code&gt;みたいに取り出すことができる。&lt;/p&gt;
&lt;p&gt;これSDK標準でやって欲しいぐらい便利。使わない手はない。&lt;/p&gt;</description></item><item><title>ActionViewのdom_id便利そう</title><link>https://blog.piyo.tech/posts/2014-09-01-200000/</link><pubDate>Mon, 01 Sep 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-09-01-200000/</guid><description>&lt;p&gt;RailsアプリでJSでデータを書き換えたあとでHTMLを更新するってことはよくあって、そのときはだいたいidを使うと思う。そしてidにはモデル名とモデルのidをそのまま使うことが多いはず。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;item-192&amp;#34;&lt;/span&gt;&amp;gt;...&amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このようなidを書くとき今までは自分でベタ書きしてしまっていたが、&lt;code&gt;ActionView&lt;/code&gt;には&lt;code&gt;dom_id&lt;/code&gt;というヘルパーがあって、こちらを使えばもっとスマートに書けることがわかった。&lt;/p&gt;
&lt;p&gt;こういう感じで書くと、&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-erb" data-lang="erb"&gt;&amp;lt;li id=&amp;#34;&amp;lt;%= dom_id(@item) %&amp;gt;&amp;#34;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;こういうidを生成してくれるみたい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;item_123&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これを使うと似たような記述を減らすことができるのがいい。&lt;/p&gt;
&lt;p&gt;同様に&lt;code&gt;dom_class&lt;/code&gt;というメソッドもあって、こちらはシンプルにモデル名がクラスになるようなイメージだ。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-erb" data-lang="erb"&gt;&amp;lt;li class=&amp;#34;&amp;lt;%= dom_class(@item) %&amp;gt;&amp;#34;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;↓&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;item&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>gitコマンドライン厨の俺だけどヘルプ見ないと使えないコマンドが多いのでメモ</title><link>https://blog.piyo.tech/posts/2014-08-31-200000/</link><pubDate>Sun, 31 Aug 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-31-200000/</guid><description>&lt;p&gt;gitは基本コマンドラインを使っている。コマンドライン厨とか書いたけど、むしろ逆でコマンドラインの基本的なことしか使えないというのが正しい。SourceTreeとかはMagitとかは使いこなせない。&lt;/p&gt;
&lt;h1 id="普段使うコマンド"&gt;普段使うコマンド&lt;/h1&gt;
&lt;p&gt;ヘルプを見なくても使えるコマンドがここらへん。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;コマンド&lt;/th&gt;
&lt;th&gt;意味&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git checkout -b NEWBRANCH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;新しいブランチ作る&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git rebase -i HEAD~5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;過去のコミットを修正する（5つ分を指定）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git rm FILENAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;管理下からFILENAMEを削除する&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git reset --HEAD PATHNAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PATHNAMEをインデックスから削除（addしてない状態にする）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git commit -m 'COMMIT MSG'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;コミットメッセージ付きでコメント&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git merge TOPICBRANCH --squash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;トピックブランチの変更をコミットなしでマージ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git push origin :LOCALBRANCH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;originのブランチを削除&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git cherry-pick 03sda89&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;特定のコミットを現在のブランチにとりこむ&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;当たり前だけど&lt;code&gt;log&lt;/code&gt;とか&lt;code&gt;status&lt;/code&gt;も使う。&lt;/p&gt;
&lt;h1 id="ヘルプみないと使えない"&gt;ヘルプみないと使えない&lt;/h1&gt;
&lt;p&gt;今日のエントリは自分のためにこれをメモしておくというところに意味がある。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;コマンド&lt;/th&gt;
&lt;th&gt;意味&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git branch -m LOCALBRANCH NEWLOCALBRANCH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ブランチの名前を変える&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git log -p -2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2つ分のコミット履歴をDiff付きで表示&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git log --stat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ログと一緒にファイルの変更も見る&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git diff --name-status HEAD~&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;HEAD~で変更したファイルを一覧にする&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git archive --format=zip -o package.zip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;package.zipという名前でソース管理下のファイルをZIP化する&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;もっといろいろありそうだから思い出したら追記する。&lt;/p&gt;</description></item><item><title>CSVをマークダウンの表に変換するcsvtomdをアップデート</title><link>https://blog.piyo.tech/posts/2014-08-30-200000/</link><pubDate>Sat, 30 Aug 2014 20:00:12 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-30-200000/</guid><description>&lt;p&gt;自分用便利gemが便利じゃなかったのでその部分を修正しました。これぞドッグフーディング。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-08-24-200000"&gt;CSVテキストをMarkdown形式のテーブルに変換するgem作った - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;以前作ったときはスペースとか消してよくね？と思って&lt;code&gt;gsub(&amp;quot; &amp;quot;,&amp;quot;&amp;quot;)&lt;/code&gt;してたんだけど全然だめでした。そりゃそうだよね。セルの中のコンテンツにスペースが入ることだってあるよね。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;コマンド&lt;/th&gt;
&lt;th&gt;解説&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;% rails server -p 3001&lt;/td&gt;
&lt;td&gt;3001番でサーバーを起動&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;% rails console &amp;ndash;sandbox&lt;/td&gt;
&lt;td&gt;DBへの変更を保存しないでコンソールを起動&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;上の表が下みたいになったら使い物にならないよね。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;コマンド&lt;/th&gt;
&lt;th&gt;解説&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;%railsserver-p3001&lt;/td&gt;
&lt;td&gt;3001番でサーバーを起動&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;%railsconsole&amp;ndash;sandbox&lt;/td&gt;
&lt;td&gt;DBへの変更を保存しないでコンソールを起動&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;そういうわけで、ちょっと修正しました。&lt;/p&gt;
&lt;h1 id="ソース"&gt;ソース&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/csvtomd"&gt;pi-chan/csvtomd&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="rubygems"&gt;rubygems&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://rubygems.org/gems/csvtomd"&gt;csvtomd | RubyGems.org | your community gem host&lt;/a&gt;&lt;/p&gt;</description></item><item><title>追加要素にshown.bs.collapseが効かない</title><link>https://blog.piyo.tech/posts/2014-08-29-200000/</link><pubDate>Fri, 29 Aug 2014 20:00:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-29-200000/</guid><description>&lt;p&gt;Bootstrapについてくるjavascriptのcollapseを使うとアコーディオン風のUIが簡単に作れるから便利。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://getbootstrap.com/javascript/#collapse"&gt;JavaScript · Bootstrap&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;で、隠れていたものが表示されたときに何かしたいってときのために&lt;code&gt;shown.bs.collapse&lt;/code&gt;っていうイベントが用意されているんだけど、このイベント、ajaxとかで追加した要素ではちゃんと呼ばれない。&lt;/p&gt;
&lt;p&gt;っていうかこれは別にこのイベントに限った話じゃなくて、javascriptのイベント全般の話なんだけどよく忘れるのでメモ的に残しておく。今回気がつきにくかったのはBootstrapだから違うかもと思ってしまったのが原因かも…？&lt;/p&gt;
&lt;p&gt;基本はdocument readyで↓みたいにすればいいんだけど、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;.collapse&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;on&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;shown.bs.collapse&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// do something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;追加要素の場合はこれが呼ばれていないことになっちゃうから、&lt;code&gt;.collapse&lt;/code&gt;じゃなくてdocumentにくっつけておく必要がある。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(document).&lt;span style="color:#a6e22e"&gt;on&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;shown.bs.collapse&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;.collapse&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// do something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これだと最初にdocumentにイベントとハンドラが紐付けられるから、後から追加した要素でも問題なく動いてくれる。&lt;/p&gt;</description></item><item><title>ruby-modeの野郎が勝手にマジックコメント入れてた</title><link>https://blog.piyo.tech/posts/2014-08-28-200000/</link><pubDate>Thu, 28 Aug 2014 20:00:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-28-200000/</guid><description>&lt;p&gt;Emacsのruby-mode使ってたら日本語を含むバッファを保存するときに勝手にマジックコメント入れてた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ruby2からは要らないので消しておく。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;(&lt;span style="color:#66d9ef"&gt;setq&lt;/span&gt; ruby-insert-encoding-magic-comment &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>自分の環境だけで特定のgemを使う方法</title><link>https://blog.piyo.tech/posts/2014-08-27-203000/</link><pubDate>Wed, 27 Aug 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-27-203000/</guid><description>&lt;p&gt;オープンソースのプロジェクトの動作確認するときとかに、いつも使っている開発用のgemを入れたいんだけどGemfileは更新したくないってことない？僕の場合、関係ないファイルを汚しておくとうっかりコミットしてしまうことがあるので避けたいと思ってる。&lt;/p&gt;
&lt;p&gt;使いたいツールがGemfileに書いてないと困るときが結構あって、例えばPryが入ってないと気持ち悪いとかそういう系のときに困る。デバッグに&lt;code&gt;pry-debugger&lt;/code&gt;とか使うし。&lt;/p&gt;
&lt;p&gt;で、調べたら一応なんとかする方法があった。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qiita.com/vzvu3k6k/items/12aff810ea93c7c6f307"&gt;Ruby - Gemfileにないgemを使いたい - Qiita&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Bundlerは&lt;code&gt;BUNDLE_GEMFILE&lt;/code&gt;っていう環境変数を読むようになっていて、この環境変数が設定されていなければ&lt;code&gt;Gemfile&lt;/code&gt;、設定されている場合はそのファイルを使うらしい。&lt;/p&gt;
&lt;p&gt;このエントリでは&lt;code&gt;BUNDLE_GEMFILE&lt;/code&gt;に&lt;code&gt;Gemfile.local&lt;/code&gt;をセットすることで追加gemを使えるようにしている。&lt;/p&gt;
&lt;p&gt;環境変数の設定は普通にこれ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% export BUNDLE_GEMFILE&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Gemfile.local&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Gemfile.local&lt;/code&gt;はこう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;eval_gemfile &lt;span style="color:#e6db74"&gt;&amp;#34;Gemfile&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#34;pry&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#34;pry-debugger&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際この方法でここに書いたgemを使えるようになった。yay！&lt;/p&gt;
&lt;h1 id="ちょっとだけマシにする"&gt;ちょっとだけマシにする&lt;/h1&gt;
&lt;p&gt;アプリケーションごとに普通の&lt;code&gt;Gemfile&lt;/code&gt;と&lt;code&gt;Gemfile.local&lt;/code&gt;を使い分けることになると、いちいち手書きで環境変数を変えるのは面倒だ。&lt;/p&gt;
&lt;p&gt;なので&lt;code&gt;.zshrc&lt;/code&gt;に環境変数の有効無効を切り替えるための関数を作っておいた。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;function use_local(){
export BUNDLE_GEMFILE=&amp;#34;Gemfile.local&amp;#34;
}
function unuse_local(){
unset BUNDLE_GEMFILE
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;まあ、名前はなんでもいいよね。&lt;/p&gt;
&lt;h1 id="本当はこうしたい"&gt;本当はこうしたい&lt;/h1&gt;
&lt;p&gt;Gemfile.localがあればそちらを優先、なければ&lt;code&gt;Gemfile&lt;/code&gt;という風にしたい。さっきのQiitaのエントリに載ってたリンクによると一度Bundler開発者でも議論があった上でこの機能は導入されていないらしい。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Gemfile.local&lt;/code&gt;があれば優先するっていう、bundler-gemfile-localみたいな拡張がないかなー。または作ってしまおうかなーという感じ。&lt;/p&gt;</description></item><item><title>1DynoなHerokuをNew Relicでアイドルを回避</title><link>https://blog.piyo.tech/posts/2014-08-25-200000/</link><pubDate>Mon, 25 Aug 2014 20:00:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-25-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/26723f8a-15bc-456d-9154-c73aa15b5b53/7e0e40dff6788281ccedfd8dbd60d851/deep/0/newrelic.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Herokuの無料版はしばらくアクセスがないと勝手に寝る。寝たあと最初のアクセスに時間がかかって鬱陶しいので定期的に起こす必要があるというのはよく知られた話。&lt;/p&gt;
&lt;p&gt;で、その方法として僕はこれまでHerokuスケジューラを使っていたが、New Relicの監視でできるよーという話をどこかで僕もやってみる聞いたのでやってみた。&lt;/p&gt;
&lt;p&gt;どこかで聞いたというか、今調べたら1年以上前にはてブしたページに書いてあった。そのときは気づいていなかったなぁ。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.mah-lab.com/2013/05/16/heroku-commons-16/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://blog.mah-lab.com/2013/05/16/heroku-commons-16/" alt="知っておきたい！Herokuを使う上では当たり前？の16の常識 | mah365" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://blog.mah-lab.com/2013/05/16/heroku-commons-16/"&gt;知っておきたい！Herokuを使う上では当たり前？の16の常識 | mah365&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://blog.mah-lab.com/2013/05/16/heroku-commons-16/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://blog.mah-lab.com/2013/05/16/heroku-commons-16/" alt="はてなブックマーク - 知っておきたい！Herokuを使う上では当たり前？の16の常識 | mah365" title="はてなブックマーク - 知っておきたい！Herokuを使う上では当たり前？の16の常識 | mah365" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h1 id="new-relic導入"&gt;New Relic導入&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% heroku addons:add newrelic:stark
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="監視設定"&gt;監視設定&lt;/h1&gt;
&lt;p&gt;このコマンドで設定画面へ行って、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% heroku addons:open newrelic
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;対象のアプリケーションを選ぶ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9d0073fd-1cab-490c-8f96-79d894555081/456b5797ef5ae9bb96019f8713582e27/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-25-10-02.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;画面上のほうにあるタブメニューから「Settins」→「Availability monitoring」と進んでいき、URL欄にアプリケーションのURLを入れておく。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/243cb0c7-a6c1-4d19-8a50-53559aef26a2/ea6f26068fc0dc38727b0fa069a327dc/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-25-10-01.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;で、これで定期的にチェックしてくれるようになるので、HerokuのほうはNew Relicからのアクセスによって起きたままになるというわけ。見た感じ20秒ごと？なのかな？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;New Relic checks your site approximately every 20 seconds. When we detect a failure, New Relic increases the rate to once every 10 seconds until the site recovers.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://docs.newrelic.com/docs/alerts/alert-policies/downtime-alerts/availability-monitoring#pingers"&gt;Availability monitoring | New Relic Documentation&lt;/a&gt; より&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>CSVテキストをMarkdown形式のテーブルに変換するgem作った</title><link>https://blog.piyo.tech/posts/2014-08-24-200000/</link><pubDate>Sun, 24 Aug 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-24-200000/</guid><description>&lt;p&gt;&lt;a href="http://rubygems.org/gems/markdown_section_numbering"&gt;markdown_section_numbering&lt;/a&gt;に続いて単発のテキスト変換gemを作ってRubygemsで公開した。&lt;/p&gt;
&lt;p&gt;今回作ったのはコンマ区切りで書いたテキストをマークダウン形式のテーブルに変換するメソッドを提供するモジュールで、基本的には自分がAutomator経由で呼び出すことを想定している。&lt;/p&gt;
&lt;p&gt;ブログや資料をMarkdown形式で書くことが多いんだけど、これまでは&lt;a href="http://www.tablesgenerator.com/markdown_tables"&gt;Markdown Tables generator&lt;/a&gt;を使っていた。このサイトはこのサイトでかなり素晴らしいが、どうせならエディタ内で簡単に済ませたい。Markdownのテーブルは人間が手作業で書けるものではないので人間でも書きやすいCSV形式を取ることにした。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;リンク&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/pi-chan/csvtomd"&gt;pi-chan/csvtomd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rubygems.org/gems/csvtomd"&gt;csvtomd | RubyGems.org | your community gem host&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="使いかた"&gt;使いかた&lt;/h1&gt;
&lt;p&gt;READMEからそのまんま持ってきた。&lt;/p&gt;
&lt;h2 id="基本"&gt;基本&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;csvtomd&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;csv &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;lt;&amp;lt;CSV
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;head1, head2, head3, head4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;line1&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, line1&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, line1&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, line1&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;line2&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, line2&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, line2&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, line2&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;line3&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, line3&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, line3&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, line3&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CSV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;puts &lt;span style="color:#66d9ef"&gt;CsvToMd&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;convert(csv)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上のコードで次の出力が得られる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;|head1|head2|head3|head4|
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;|---|---|---|---|
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;|line1-1|line1-2|line1-3|line1-4|
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;|line2-1|line2-2|line2-3|line2-4|
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;|line3-1|line3-2|line3-3|line3-4|
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際に表にしてみるとこんな感じ。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;head1&lt;/th&gt;
&lt;th&gt;head2&lt;/th&gt;
&lt;th&gt;head3&lt;/th&gt;
&lt;th&gt;head4&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;line1-1&lt;/td&gt;
&lt;td&gt;line1-2&lt;/td&gt;
&lt;td&gt;line1-3&lt;/td&gt;
&lt;td&gt;line1-4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;line2-1&lt;/td&gt;
&lt;td&gt;line2-2&lt;/td&gt;
&lt;td&gt;line2-3&lt;/td&gt;
&lt;td&gt;line2-4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;line3-1&lt;/td&gt;
&lt;td&gt;line3-2&lt;/td&gt;
&lt;td&gt;line3-3&lt;/td&gt;
&lt;td&gt;line3-4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="応用"&gt;応用&lt;/h2&gt;
&lt;p&gt;空のセルがあっても大丈夫。勝手に補うようにしている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;csvtomd&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;csv &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;lt;&amp;lt;CSV
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;, , , head,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;, ,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CSV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;puts &lt;span style="color:#66d9ef"&gt;CsvToMd&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;convert(csv)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上のコードではこんな出力になる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;||||head||
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;|---|---|---|---|---|
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;||||||
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;||||||
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;スカスカの表になる。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;head&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;※はてなブログではMarkdownの解釈が若干異なるようで5列目が潰れてしまっているが、KobitoやGitHubでは空の5列目はそのまま残って表示される。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/d63e1fc6-59db-479c-814e-04aed5064b76/95818c44d5208f9ac4d0d92a4252576a/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-23-15-13.png" alt="table"&gt;&lt;/p&gt;
&lt;h1 id="automatorと連携"&gt;Automatorと連携&lt;/h1&gt;
&lt;p&gt;このあたりに同じようなことが書いてあるので参考にしてもらえると良いっす。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-07-06-193000"&gt;マークダウンに見出し番号をつけるRuby Gem書いた - ぴよログ&lt;/a&gt;
&lt;a href="https://blog.piyo.tech/posts/2014-04-18-212759"&gt;テキスト欄に書いたRubyのコードをAutomatorで評価する - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;CSVを書く&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;選択する&lt;/li&gt;
&lt;li&gt;設定したショートカットキー&lt;/li&gt;
&lt;li&gt;Markdown形式に置き換えられる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Markdown生活がまた便利になった。&lt;/p&gt;</description></item><item><title>トラックボールM570のクリックが効きにくくなったから分解してみた</title><link>https://blog.piyo.tech/posts/2014-08-21-200000/</link><pubDate>Thu, 21 Aug 2014 20:00:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-21-200000/</guid><description>&lt;p&gt;愛用のトラックボールM570の左右クリックの効きが悪くなってきたので分解して様子をみてみることにした。M570は親指トラックボール。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/87505d8d-9b4f-4147-ab2f-443f9bcbc6a9/11054c4add0dfccf1213749065a80ffc/deep/0/IMG_2812.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;分解するにはT6というトルクスドライバーが必要となるが、そんなものはもっていなかったので仕方なく購入することにした。それがこのセット。38種類のドライバーがセットになっていて1000円しないってんだからすごい。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/ec3fc3b7-5536-4c10-bd61-2882ceea376b/9f60129e9d8963bdf4387f4cf750b1ea/deep/0/IMG_2811.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;話は脱線するが、このドライバーセットの容器を開けるときの機構がちょっとおもしろかったので動画にしてみた。こんな感じ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/gpNP04fqM7qcBFYTB-04LjfiDLIJdAFS8E4da7Jw8HbPgj_eFVUKZ-sbaZ7r0eel0syzEUYRoy-4Ekw1JWQ6qTLHCk_xBCWj061ghV_Rt8LGrIkUzIdiR910diSsyu-Ew9VRNzPzM0z1itoFtTPmCX_KYS7M6W2nZXDxJG4s5A2lClZRLcXelqDerht8X57grMegPGvmdjgfQUzF4iY-I8U6J9u_pOmKRSAnkMDreIgjyNuk62YpmwbJOlPt2A3ajnIfaYnHblIxV6-nZBUwRsNV49DHBWVh4GKSEsG-OVr1zV7dRfp9O5GoWHvIfLFim3Spw06R5RwIeH_3ys-R6XobkiJsVVhzjbw_pwJFw3qbWf2JzVG2iF3q8IEbM3n2_FZNRD3EjGfLI1FCzJDD5Fr3jzyjpuEIveCKDZmmtoupBmNoFVESF1Y1VNZxZ3WLKxnIx_Ddzw6OXZ4uNRklqSbq8c-5c47nfcFHYyDCRJ5dUy0zGa6e95Og69EvsmWJshtfWjdB_GqauMN6XKbIlQi-_zHTHlAG68MJMUC8z76f2We1G2a8ncjUWSHUtRKeYQwQo1pD3tmC3OqrlXagtSO-bJkLS0n9hl6-388H-_h3TuVswc_Xos-YiONXJw7SKrqueTWncc74VGggmtj1Lre3mFQG9DeW-g=w270-h480-no" alt=""&gt;&lt;/p&gt;
&lt;p&gt;これ見えるかなー。ふたを開けるとドライバーの取り替える部分が一斉に起き上がる。最初びっくりしたけど面白くて動画まで撮影してしまった。&lt;/p&gt;
&lt;p&gt;分解の話に戻る。分解のためにはトラックボールの背面にあるネジを5箇所はずさなければならない。一見すると背面に見えているネジは1個だが、ゴム状のマットの内側に3個、電池が入っているところのラベルの内側に1個、合計5箇所ある。&lt;/p&gt;
&lt;p&gt;なお、分解についてはこちらを参考にした。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.yahoo.co.jp/yoncha_p/24552305.html"&gt;Logicool M570分解 - きまぐれベンツ日記 - Yahoo!ブログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;分解したらこのようになった。ネジが小さいからなくしそうだ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7a7464f6-56a4-474a-84ce-8d778582e6d4/dea1a463d96e1676d96594445652333b/deep/0/IMG_2815.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;マウスクリックが不調ということでボタンの機構をみてみたが、操作するボタンを押すと基板についているボタンが押されるだけらしく、ホコリが詰まるようなところは特になかった気がする。ひとまずホコリを払ったり吹き飛ばしたりしてみた。&lt;/p&gt;
&lt;p&gt;ちなみに基板についているボタンはこういう対応になっている。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/e15e3c68-3f82-4619-b0a6-9ddb01a074a9/0449ed10ec1b5f28bf634325fed8b0b7/deep/0/IMG_2816.jpg" alt=""&gt;&lt;/p&gt;
&lt;h1 id="掃除結果"&gt;掃除結果&lt;/h1&gt;
&lt;p&gt;結果よくなったこともあれば明らかに悪くなってしまったところもある。分解は自己責任だなあ。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;左右ボタンの効き&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;なんとなくよくなった！&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;カーソルの動き&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;なぜか悪化した…！余計なことをしたせいかもしれない。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B00E19UYO8/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/51JTI2n7qqL._AC_SL1024_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;ロジクール ワイヤレスマウス シルバー&amp;amp;ブルー トラックボール 無線 M570t Unifying 5ボタン トラックボールマウス 電池寿命最大18ケ月 国内正規品 3年間無償保証&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="my-4 border border-dashed border-orange-300 rounded p-3 text-sm"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B00ASARYZQ/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:underline"&gt;
&lt;span class="text-orange-600 mr-1"&gt;amazon.co.jp →&lt;/span&gt;ASIN: B00ASARYZQ
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>仮想マシンのWindows8でCapsLockがオフにできないとき</title><link>https://blog.piyo.tech/posts/2014-08-20-200000/</link><pubDate>Wed, 20 Aug 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-20-200000/</guid><description>&lt;p&gt;VMWareとVirtualBoxとかにWindows入れて使ってるときにCapsLockが効いちゃって解除できなくてムッカーってことがまれによくある。ホストがMacだからキーボードも違うし、一体どれがCapsLockキーなのか全くわからなかったりする。&lt;/p&gt;
&lt;p&gt;そんなときはキーボードではなく、IMEのほうでソフトウェア的に解除してしまえばいいんだけど、Windows8ではあいつが見つからない。&lt;/p&gt;
&lt;p&gt;あいつって、IMEツールバーね。これ↓&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/e696210a-2e7b-49f3-ba25-1a7c66c2cc71/34d3500c9330fa9099dd09c6f84faa91/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-19-15-06.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;これが出ていれば「CAPS」ってとこをクリックすればCapsLockをトグルできるわけ。見当たらないなら出す方法を探せばいいってことで調べてみたら、ちゃんと言語設定あたりでできたのでその方法を書く。&lt;/p&gt;
&lt;h1 id="コントロールパネル"&gt;コントロールパネル&lt;/h1&gt;
&lt;p&gt;「言語の追加」「入力方法の変更」どっちでもいいのでクリックする。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/3aec077a-7801-490f-a0c8-d753db24af5a/66906c97d09eb13056ebd03d69c89b23/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-19-15-09.png" alt=""&gt;&lt;/p&gt;
&lt;h1 id="言語設定"&gt;言語設定&lt;/h1&gt;
&lt;p&gt;左側にある詳細設定を押す。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7d2c7fa9-b73a-4b82-860a-f59f3ef1a070/ae6359b84b950f7bc99fb7887690a3e7/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88.png" alt=""&gt;&lt;/p&gt;
&lt;h1 id="詳細設定"&gt;詳細設定&lt;/h1&gt;
&lt;p&gt;「使用可能な場合にデスクトップ言語バーを使用する」にチェック。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/079d2ce5-4159-4ffa-845e-830110cb3d30/7e31d152ed2901cb8ce38e878755046f/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;これであいつが出現するようになった。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/e696210a-2e7b-49f3-ba25-1a7c66c2cc71/34d3500c9330fa9099dd09c6f84faa91/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-19-15-06.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;サンキュー、言語バー。&lt;/p&gt;</description></item><item><title>mysqlslapコマンドの使いかた事例</title><link>https://blog.piyo.tech/posts/2014-08-19-200000/</link><pubDate>Tue, 19 Aug 2014 20:00:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-19-200000/</guid><description>&lt;p&gt;1年ほど前にRSSリーダーの開発をしていたとき、環境ごとのMySQLのパフォーマンスを調べるのに&lt;code&gt;mysqlslap&lt;/code&gt;というコマンドを使っていたが、割と適当に使っていたので今こそそれを振り返ってみようと思う。&lt;/p&gt;
&lt;p&gt;そもそもmysqlslapが何かと言うと、MySQLの公式ドキュメントにはこのように書かれている。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://dev.mysql.com/doc/refman/5.1/ja/mysqlslap.html"&gt;MySQL :: MySQL 5.1 リファレンスマニュアル :: 7.15 mysqlslap — クライアント負荷エミュレーション&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;mysqlslapはMySQLサーバのクライアント負荷をエミュレートし、各ステージのタイミングを報告する診断プログラムです。サーバにたいして複数のクライアントがアクセスしているかのように作動します。mysqlslapはMySQL 5.1.4.から提供されています。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;なるほどなるほど、複数クライアントから接続されている状況をエミューレートできるんだね。&lt;/p&gt;
&lt;p&gt;で、僕が検証に使っていたコマンドの一部がこんなのだった↓。ネットワークが影響しない状況で確認したかったからSSHで入ってlocalhostのMySQLに接続してテストした。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ mysqlslap \
--no-defaults \
--concurrency=10 \
--iterations=1 \
--number-int-cols=2 \
--number-char-cols=3 \
--auto-generate-sql \
--engine=innodb \
--auto-generate-sql-add-autoincrement \
--auto-generate-sql-load-type=key \
--auto-generate-sql-write-number=2000 \
--number-of-queries=30000 \
--host=localhost \
--port=3306 \
--user=root
# 結果はこんなふうに出る
Benchmark
Running for engine innodb
Average number of seconds to run all queries: 3.274 seconds
Minimum number of seconds to run all queries: 3.274 seconds
Maximum number of seconds to run all queries: 3.274 seconds
Number of clients running queries: 10
Average number of queries per client: 3000
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;それぞれのオプションがどんな意味なのかを見ていってみようと思う。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;no-defaults&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;設定ファイルに書かれているデフォルト値を無視するためのオプション。色々な環境で試すときにはこれをやっておくと環境ごとの差異をなくせる。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;concurrency=10&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;シミュレートする同時接続クライアントの数で、↑の場合は10。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;iterations=1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;実行する回数。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;number-int-cols=2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;使うINTカラムの数。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;number-char-cols=3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;使うVARCHARカラムの数。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;auto-generate-sql&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;テストに使うSQLを自動生成する。ファイルやオプションでSQLが与えられていない場合。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;engine=innodb&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;エンジンはInnoDBだよね〜。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;auto-generate-sql-add-autoincrement&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;自動生成されたテーブルにAUTO_INCREMENTカラムを追加する。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;auto-generate-sql-load-type=key&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;テストのタイプを指定する。ここでは&lt;code&gt;key（主キーの読み取り）&lt;/code&gt;を使ったけど、他にも色々ある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;read（テーブルのスキャン）&lt;/li&gt;
&lt;li&gt;write（テーブルの読み取り）&lt;/li&gt;
&lt;li&gt;update（主キーの更新）&lt;/li&gt;
&lt;li&gt;mixed（挿入とスキャンを半分ずつ）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;auto-generate-sql-write-number=2000&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;各スレッドで実行する挿入クエリの数。…ん？&lt;code&gt;key&lt;/code&gt;のときは意味ないのでは…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;number-of-queries=30000&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;クライアントで実行される合計のクエリ数。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;host=localhost&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;接続するホスト。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;port=3306&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;接続するポート番号。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ndash;user=root&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ユーザー名&lt;/p&gt;
&lt;p&gt;こうやって見るとオプションが多すぎてきちんと把握していなかったな。よく見ると意味がないかもしれないオプションとかもある。&lt;/p&gt;</description></item><item><title>Emacsinit-loader.elのログを非表示</title><link>https://blog.piyo.tech/posts/2014-08-18-200000/</link><pubDate>Mon, 18 Aug 2014 20:00:19 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-18-200000/</guid><description>&lt;p&gt;Emacsのinit-loaderというelispを使うと拡張機能の設定を複数ファイルに分けたり、環境ごとの設定を別ファイルにわけたりするなど管理が楽になる。&lt;/p&gt;
&lt;p&gt;詳しい設定についてはこのあたりを見ればわかる（丸投げ）。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qiita.com/catatsuy/items/5f1cd86e2522fd3384a0"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://qiita.com/catatsuy/items/5f1cd86e2522fd3384a0" alt="init-loader.el と package.el を導入して快適 Emacs ライフ - Qiita" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://qiita.com/catatsuy/items/5f1cd86e2522fd3384a0"&gt;init-loader.el と package.el を導入して快適 Emacs ライフ - Qiita&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://qiita.com/catatsuy/items/5f1cd86e2522fd3384a0" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://qiita.com/catatsuy/items/5f1cd86e2522fd3384a0" alt="はてなブックマーク - init-loader.el と package.el を導入して快適 Emacs ライフ - Qiita" title="はてなブックマーク - init-loader.el と package.el を導入して快適 Emacs ライフ - Qiita" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;で、このinit-loaderを使うとEmacs起動後にinit-loaderのログが表示されてしまって微妙に鬱陶しいので、init-loaderの設定のときにログを非表示にすべく、次のように書いておいた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;(&lt;span style="color:#a6e22e"&gt;require&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;init-loader&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;(&lt;span style="color:#66d9ef"&gt;setq&lt;/span&gt; init-loader-show-log-after-init &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;(init-loader-load &lt;span style="color:#e6db74"&gt;&amp;#34;~/.emacs.d/inits&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;しばらくはこれでよかったんだけど、何かのタイミングでバージョンがあがったらしく、設定があるにも関わらずログが表示されるようになってしまった。困ったのでソースコードを読んでみると、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;(defcustom init-loader-show-log-after-init &lt;span style="color:#66d9ef"&gt;t&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Show loading log message if this value is t. If this value is `error-only&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;log message is shown only errors occured.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;:type&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;boolean&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;:group&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;init-loader&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;error-onlyにすればよさそうだ、ということがわかったので設定を次のように変更。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;(&lt;span style="color:#a6e22e"&gt;require&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;init-loader&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;(&lt;span style="color:#66d9ef"&gt;setq&lt;/span&gt; init-loader-show-log-after-init &lt;span style="color:#e6db74"&gt;&amp;#39;error-only&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;(init-loader-load &lt;span style="color:#e6db74"&gt;&amp;#34;~/.emacs.d/inits&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで正常時はログが表示されなくなりました。&lt;/p&gt;</description></item><item><title>Emacsで開いているバッファを順次移動するelisp</title><link>https://blog.piyo.tech/posts/2014-08-17-200000/</link><pubDate>Sun, 17 Aug 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-17-200000/</guid><description>&lt;p&gt;Emacsのバッファ移動にはhelmとかを使っていろいろやっているんだけど、その中でも&lt;code&gt;C-,&lt;/code&gt;と&lt;code&gt;C-.&lt;/code&gt;で前後のバッファを順次移動するっていうシンプルなelispもヘビーユースしている。パッケージにはなっていないっぽいのでelispのコードをそのまま設定ファイルに書いて使っている。&lt;/p&gt;
&lt;p&gt;それがこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.jaist.ac.jp/~n-yoshi/tips/elisp_tips.html#buffer"&gt;[emacs 21] バッファ移動を簡単に（バッファリスト表示付き）&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この機能はウェブブラウザのタブ移動に似ている。&lt;code&gt;Ctrl+Tab&lt;/code&gt;で次々に右側のタブに移動できるし、&lt;code&gt;Shift+Ctrl+Tab&lt;/code&gt;で左側のタブに移動できたりするあれだ。このelispを入れるとそれに近いことが&lt;code&gt;C-,&lt;/code&gt;と&lt;code&gt;C-.&lt;/code&gt;でできるようになり、ちょっとしたバッファ変更に便利だ。&lt;/p&gt;
&lt;p&gt;ちなみにこのコードは10年近く前のコードみたいだけどきちんと動いている。僕も2006年ぐらいから使わせてもらっている。ってことを思い出したので書いてみました。&lt;/p&gt;</description></item><item><title>KobitoのカスタムCSSで見た目を変えて印刷も便利に</title><link>https://blog.piyo.tech/posts/2014-08-16-200000/</link><pubDate>Sat, 16 Aug 2014 20:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-16-200000/</guid><description>&lt;p&gt;前にKobitoのコマンドラインが便利って書いたけど、印刷時の文字がでかくてちょっと困っていた。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/2d3ef6d7-f6e3-4089-9ef5-86df0246ec04/da9f7a02b658f59554a7f8e783332420/deep/0/%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-06-20-200000"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-06-20-200000" alt="Kobitoのコマンドライン「kobito-cli」がめちゃ便利 - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-06-20-200000"&gt;Kobitoのコマンドライン「kobito-cli」がめちゃ便利 - ぴよログ&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/https://blog.piyo.tech/posts/2014-06-20-200000" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/https://blog.piyo.tech/posts/2014-06-20-200000" alt="はてなブックマーク - Kobitoのコマンドライン「kobito-cli」がめちゃ便利 - ぴよログ" title="はてなブックマーク - Kobitoのコマンドライン「kobito-cli」がめちゃ便利 - ぴよログ" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;そしたら見た目を変えられるカスタムCSSってのがあるのね。これを使うとKobitoのプレビューやブラウザで開いたときの見た目が変わるので印刷にも反映されて結構便利。&lt;/p&gt;
&lt;p&gt;カスタムCSSはKobitoの設定画面から開くことができる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/01dc1832-eeb5-4531-a628-451182191c00/04288d9cebad9346e6998bf4a0f5ad83/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-15-22-05.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;試しにこんな感じのCSSを書いてみた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;body&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;font-size&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;%&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実はこのブログはKobitoで書いてからはてなブログに貼り付けているので、CSSを使った例として今日の記事でカスタムCSSを使ったときとそうでないときの様子を比べてみる。&lt;/p&gt;
&lt;h2 id="適用前"&gt;適用前&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/4e7f0347-ffa5-4a7f-a36a-290d0b2785f5/dda56973bd8adf8cbfcb3e7e799e8c20/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-15-22-02.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="適用後"&gt;適用後&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/8f5599c4-e14e-4fd3-8985-5ea14c9f3ae8/59b34d1183c95b5aaa016d531683d179/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-15-22-01.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;文字ちっちゃくなった！&lt;/p&gt;
&lt;p&gt;&lt;code&gt;% kobito print 105&lt;/code&gt;などとしてブラウザで開いた時もこの設定が有効なので、好みの文字サイズにしたりフォントを変えたりということができそうだ。&lt;/p&gt;</description></item><item><title>サイドバイサイド構成が正しくないエラーは依存モジュールのバージョン確認で解消</title><link>https://blog.piyo.tech/posts/2014-08-15-200000/</link><pubDate>Fri, 15 Aug 2014 20:00:21 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-15-200000/</guid><description>&lt;p&gt;この間はリンクしたライブラリの影響で起動できない問題があったが、今度はもらった実行ファイルが動かないという問題が起きた。&lt;/p&gt;
&lt;p&gt;ちなみに以前のはこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-08-12-200000"&gt;VS2005 アプリケーション構成が正しくない - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今回はもらった実行ファイルを動かそうとしたら「サイドバイサイド構成が正しくないうんぬん」という、これまた同じエラーでそこそこよく見るものが出てしまった。&lt;/p&gt;
&lt;p&gt;このエラーは詳細な情報を見ることができる。&lt;/p&gt;
&lt;p&gt;そのためには管理ツールというものを起動する必要がある。エクスプローラとかにあるコンピュータ（またはPCなど）となっているところを右クリックすると「管理」というメニューが出てくる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/bf548a46-0eed-4ae4-89dc-df907ebf0133/a83e2c97df5b85c6b7a208b031f6dc42/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-14-12-56.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;これをクリックすると次のような管理ツールが開く。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/84ecf7be-8949-4bf7-a081-633ce9c3b062/130c1fea5a9d6c8af1aea29e91d29d50/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-14-12-55.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;左側のツリーから「コンピュータの管理」→「システムツール」→「イベントビューアー」→「Windowsログ」→「Application」と辿ることでさきほどのエラーのログが溜まっているところにたどり着く。&lt;/p&gt;
&lt;p&gt;で、真ん中のビューで「エラー、SideBySide」などとなっているところを選択すると下の部分にもう少し詳しい情報が出ていることがわかる。&lt;/p&gt;
&lt;p&gt;その部分を引用すると、&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;#34;C:\hogehoge\hoge.exe&amp;#34; のアクティブ化コンテキストの生成に失敗しました。
従属アセンブリ Microsoft.VC80.MFC,processorArchitecture=&amp;#34;x86&amp;#34;,
publicKeyToken=&amp;#34;1fc8b3b9a1e18e3b&amp;#34;,type=&amp;#34;win32&amp;#34;,version=&amp;#34;8.0.50727.6195&amp;#34;
が見つかりませんでした。 詳細な診断を行うには sxstrace.exe を実行してください。
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;このように書かれていることがわかった。めちゃくちゃ要約すると実行ファイルが依存しているモジュールがに当たらないというわけだ。&lt;/p&gt;
&lt;p&gt;開発環境のバージョンや再頒布パッケージが足りないことが主な原因で、不足しているモジュールをインストールすれば解決することもある。&lt;/p&gt;
&lt;p&gt;このモジュールは大体&lt;code&gt;C:\Windows\WinSxS&lt;/code&gt;に入っていて、エラーとなる場合は該当バージョンが存在しないことも見ればわかる。&lt;/p&gt;
&lt;p&gt;で、どうすれば解決できるかというと、見つからなかったモジュールのバージョンでググってやればよい。今回の場合は&lt;code&gt;8.0.50727.6195&lt;/code&gt;がそれに該当する。&lt;/p&gt;
&lt;p&gt;検索してみると、それっぽい情報がいくつか出てくるし、マイクロソフトのダウンロードページも出てくる。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.google.co.jp/search?q=8.0.50727.6195&amp;amp;gws_rd=ssl"&gt;8.0.50727.6195 - Google 検索&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今回に関しては関係するアップデートをインストールしたら問題のエラーも起こらなくなり、アプリケーションを起動できた。&lt;/p&gt;
&lt;h1 id="余談"&gt;余談&lt;/h1&gt;
&lt;p&gt;ちなみに、前回似たようなエラーではまったこちらの問題については、該当バージョンを入れても直らなかったので全く別の問題のようだ。とりあえず動いているのでよしとする。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-08-12-200000"&gt;VS2005 アプリケーション構成が正しくない - ぴよログ&lt;/a&gt;&lt;/p&gt;</description></item><item><title>cygwinでrbenv</title><link>https://blog.piyo.tech/posts/2014-08-14-200000/</link><pubDate>Thu, 14 Aug 2014 20:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-14-200000/</guid><description>&lt;p&gt;cygwinでもrubyを使いたいのでrbenvを導入した。導入プロセスと起こった問題への対処法をメモしておく。&lt;/p&gt;
&lt;h1 id="導入手順"&gt;導入手順&lt;/h1&gt;
&lt;p&gt;こちらの記事が詳しい。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.oiax.jp/rails/zakkan/rails_3_2_installation_on_cygwin.html"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://www.oiax.jp/rails/zakkan/rails_3_2_installation_on_cygwin.html" alt="Ruby on Rails 3.2 を Cygwin にインストールする手順をかなり丁寧に説明してみました - Rails 雑感 - Ruby on Rails with OIAX" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://www.oiax.jp/rails/zakkan/rails_3_2_installation_on_cygwin.html"&gt;Ruby on Rails 3.2 を Cygwin にインストールする手順をかなり丁寧に説明してみました - Rails 雑感 - Ruby on Rails with OIAX&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://www.oiax.jp/rails/zakkan/rails_3_2_installation_on_cygwin.html" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://www.oiax.jp/rails/zakkan/rails_3_2_installation_on_cygwin.html" alt="はてなブックマーク - Ruby on Rails 3.2 を Cygwin にインストールする手順をかなり丁寧に説明してみました - Rails 雑感 - Ruby on Rails with OIAX" title="はてなブックマーク - Ruby on Rails 3.2 を Cygwin にインストールする手順をかなり丁寧に説明してみました - Rails 雑感 - Ruby on Rails with OIAX" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;基本的にはrbenvとruby-buildをgithubから持ってくればOKということになる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ cd ~/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ git clone git://github.com/sstephenson/rbenv.git .rbenv
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ mkdir -p ~/.rbenv/plugins
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;$ cd ~/.rbenv/plugins
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;$ git clone git://github.com/sstephenson/ruby-build.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そして&lt;code&gt;.bashrc&lt;/code&gt;なり&lt;code&gt;.zshrc&lt;/code&gt;なりに追記し、&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;export PATH=&amp;#34;~/.rbenv/bin:$PATH&amp;#34;
eval &amp;#34;$(rbenv init -)&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;それを読みなおす。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ . ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここで問題がおこらなければあとはお好みのRubyをインストールすれば良い。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ rbenv install 2.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ rbenv rehash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="エラー発生"&gt;エラー発生&lt;/h1&gt;
&lt;p&gt;ところが僕の環境では&lt;code&gt;$ . ~/.bashrc&lt;/code&gt;のタイミングで次のようなエラーが出た。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/cygdrive/c/home/.rbenv/bin/rbenv: line1: ../libexec/ruby: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;調べてみると、&lt;code&gt;~/.rbenv/bin/rbenv&lt;/code&gt;は&lt;code&gt;~/.rbenv/libexec/rbenv&lt;/code&gt;へのシンボリックリンクになっているべきらしいのだが、cloneしたものではそのようになっていなかった。&lt;/p&gt;
&lt;p&gt;そこで元々あるものは退避しておき、シンボリックリンクを貼り直した。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ mv ~/.rbenv/bin/rbenv ~/.rbenv/bin/rbenv-org
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ ln -s ~/.rbenv/libexec/rbenv ~/.rbenv/bin/rbenv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで&lt;code&gt;$ . ~/.bashrc&lt;/code&gt;が失敗しなくなった。&lt;/p&gt;</description></item><item><title>Windows8以降で使えそうなファイラーを比較した</title><link>https://blog.piyo.tech/posts/2014-08-13-200000/</link><pubDate>Wed, 13 Aug 2014 20:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-13-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7bc7b4a7-a27d-4285-9dd0-13beef39570e/67d35449efa6eccbd4e39238c49b30b7/deep/0/folder-saved-search.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Windows XPを仕事に使っていた頃はMDIEという軽量なMDIなファイラーを使っていたが、Windows7以降はデフォルトファイラーに設定できなくなってしまった。&lt;/p&gt;
&lt;p&gt;それからほどなくしてMac OS Xを仕事で使うようになったためファイラー問題から離れることができたが、最近一時的にWindowsに戻ってきて再びファイラー問題に直面している。&lt;/p&gt;
&lt;h1 id="要件"&gt;要件&lt;/h1&gt;
&lt;p&gt;ファイラーに求めるところはいくつかあるものの、最低限のところでは次の2つが満たされているといい。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;タブを並べられる&lt;/li&gt;
&lt;li&gt;デフォルトのファイラーに設定できること&lt;/li&gt;
&lt;li&gt;使い方がエクスプローラー互換であること&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="タブを並べられる"&gt;タブを並べられる&lt;/h2&gt;
&lt;p&gt;タブ型であることは当然だけど、そのタブを並べて表示する機能が欲しい。MDIEの場合はこんな風に2個でも3個でも9個でも並べて使うことができる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/6c64b42f-3d39-4fd9-8d3c-fc722e44b110/0eb90aacd9e7eef2c38da83030e93d80/deep/0/cdn6.atwikiimg.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="デフォルトファイラー"&gt;デフォルトファイラー&lt;/h2&gt;
&lt;p&gt;どうせファイラーを使うなら普通にフォルダーを開いたときにそのファイラーが起動するようにして欲しい。いちいちエクスプローラーが起動したのではやっていられない。&lt;/p&gt;
&lt;p&gt;MDIEは（確か）Win7からデフォルトファイラーにできなくなってしまった。&lt;/p&gt;
&lt;h2 id="エクスプローラー互換"&gt;エクスプローラー互換&lt;/h2&gt;
&lt;p&gt;ファイラーによっては凝った使い方ができたり、エクスプローラーとはちょっと違う使い方をしたりするものがある。慣れれば使いやすいんだろうが、ファイラーはエクスプローラーぐらいがいい。&lt;/p&gt;
&lt;h1 id="xyplorer"&gt;XYplorer &lt;/h1&gt;
&lt;p&gt;&lt;a href="http://www.xyplorer.com/free.php"&gt;XYplorer - XYplorerFree&lt;/a&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;タブ並べ&lt;/th&gt;
&lt;th style="text-align: center"&gt;デフォルトファイラー&lt;/th&gt;
&lt;th style="text-align: center"&gt;エクスプローラー互換&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;△&lt;/td&gt;
&lt;td style="text-align: center"&gt;◯&lt;/td&gt;
&lt;td style="text-align: center"&gt;△&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/2b83ce6d-9169-44ea-8c49-5be4091f04f4/86c07d5542715e0b749ad2183a47da49/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;惜しい。左右2ペインでそれぞれタブブラウジングできるようになっている。&lt;/p&gt;
&lt;h1 id="explorer"&gt;Explorer++&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://explorerplusplus.com/"&gt;Explorer++ - A small and fast file manager for Windows&lt;/a&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;タブ並べ&lt;/th&gt;
&lt;th style="text-align: center"&gt;デフォルトファイラー&lt;/th&gt;
&lt;th style="text-align: center"&gt;エクスプローラー互換&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;×&lt;/td&gt;
&lt;td style="text-align: center"&gt;◯&lt;/td&gt;
&lt;td style="text-align: center"&gt;◯&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7ac7f1af-5b0e-4b06-bb5e-a3a9f19b5195/8ecb5aa3dc1426b7ea86855d54f7c6da/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;デフォルトのファイラーに設定できるのはよかったが、単なるタブファイラーだったのであまり使い勝手はよくなかった。&lt;/p&gt;
&lt;h1 id="asr"&gt;As/R&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://www.all.undo.jp/asr/"&gt;As/R&lt;/a&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;タブ並べ&lt;/th&gt;
&lt;th style="text-align: center"&gt;デフォルトファイラー&lt;/th&gt;
&lt;th style="text-align: center"&gt;エクスプローラー互換&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;◯&lt;/td&gt;
&lt;td style="text-align: center"&gt;△&lt;/td&gt;
&lt;td style="text-align: center"&gt;×&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;かなりOpinionatedなファイラーで、高機能である反面、開発者の考え方を色濃く反映している。例えばデフォルトファイラーに設定する方法はなくはないのでが、それを簡単にはやらせてくれない。FAQを見るとデフォルトファイラーにする方法についての質問があるのだが、回答は「設定した結果おかしくなる可能性もあるからレジストリとか分かる人だけやってね、やり方はヘルプに書いてあるからよく読んでね」的なことが書いてある。いろいろな操作もよく考えられているが、その分エクスプローラーから離れているため学習コストがかかる。&lt;/p&gt;
&lt;h1 id="結論"&gt;結論&lt;/h1&gt;
&lt;p&gt;結局、タブを並べられることとシンプルに使えることからMDIEを使うことにしている。ほんとデフォルトファイラーにできれば言うことないんだけど…。レジストリいじればできそうだけどそこまでしたくはないのです。&lt;/p&gt;</description></item><item><title>VS2005 アプリケーション構成が正しくない</title><link>https://blog.piyo.tech/posts/2014-08-12-200000/</link><pubDate>Tue, 12 Aug 2014 20:00:05 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-12-200000/</guid><description>&lt;p&gt;Windows8とVisual Studio 2005の組み合わせのせいなのかはわからないが少しはまった問題があるのでメモしておく。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.microsoft.com/ja-jp/dev/support/tools.aspx"&gt;開発ツール対応 OS 一覧&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そのそも↑のページにあるように&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Windows 8&lt;/li&gt;
&lt;li&gt;Visual Studio 2005&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;の組み合わせは公式には使えないことになっており、インストール時にも警告がでまくる。それでもインストールすればそれなりには使えるのでそのまま使っていた。&lt;/p&gt;
&lt;p&gt;ところが、あるとき環境依存の問題が発生した。それはビルド済みのスタティックライブラリ(.lib)を客先からもらって、手元でそのライブラリとリンクするプログラムを書いて動かしたときに起こった。&lt;/p&gt;
&lt;p&gt;リリースビルドでは動くのにデバッグビルドではこのようなエラーが出て動かないというものだった。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/3e4748a5-37b4-4299-bc53-6b7416159f87/c48c38bd69f0411f587aa152a97e46b6/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;正確に言うとデバッグ版でもデバッグなし実行であれば動作した。&lt;/p&gt;
&lt;p&gt;もらったスタティックライブラリには、デバッグ情報付きのものとそうでないものがあった。デバッグ版では当然デバッグ情報を含むlibをリンクしていたのだが、これをデバッグ情報を持たないものにリンクさせたところ正常に動くようになった。&lt;/p&gt;
&lt;p&gt;ライブラリをビルドした環境がVS2005+Win7だったらしいが、その環境でつけたデバッグ情報が正しく使えなかったことによって起こった問題らしい。&lt;/p&gt;
&lt;p&gt;本当の原因というのは解明できなかったが、デバッグ情報のありなしによって動く場合と動かない場合があるというのがわかったので良しとする。この手の問題は同じ現象に出会う人はごく少ない気もするが、誰か1人でも助かるといいなーと思って書いておいた。&lt;/p&gt;</description></item><item><title>Visual Studioで外部で変更したソースを自動読み込み</title><link>https://blog.piyo.tech/posts/2014-08-11-200000/</link><pubDate>Mon, 11 Aug 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-11-200000/</guid><description>&lt;p&gt;WindowsでC/C++だとビルドはVisual StudioだけどソースはEmacsで書くことが多い。で、Emacsで変更してVisual Studioに戻るとこのダイアログがでて結構うざい。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0b15431a-3542-41f8-a3e4-9eddc5509b7c/957bc148514523b9970e6a10cbd43de6/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;それでもとくに気にせず「すべてに適用」で乗り切っていたんだけど、普通に考えたら自動で反映させる方法があるんじゃないかということに気がついた。&lt;/p&gt;
&lt;p&gt;オプションをみていたら「保存する場合、変更を自動的に読み込み」というそれらしい項目があり、そこにチェックを入れたら確認ダイアログがでなくなった。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/21d5eaf5-c6ef-4980-b1b1-a48db25883ed/7c73b9539b1d0ae9bdb1ed2e428dd1f8/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;あー、Visual Studio使い始めてすぐにこの設定に気がついていれば…。累計で30分ぐらいは損しているかもしれない。&lt;/p&gt;</description></item><item><title>homebrewでpdftkを入れてコマンドラインでPDF結合</title><link>https://blog.piyo.tech/posts/2014-08-10-200000/</link><pubDate>Sun, 10 Aug 2014 20:00:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-10-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/928bcb9b-d58e-4171-8922-f3cc336899d6/0756ab11b49daaaaddd8138d58177daa/deep/0/pdf.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;PDFの結合にGUIを使うのが面倒なのでコマンドラインで実行する方法を探してみたらpdftkというのが使えるっぽかった。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/"&gt;PDFtk - The PDF Toolkit&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="導入編"&gt;導入編&lt;/h1&gt;
&lt;p&gt;homebrewで入れられないか探してみた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% brew search pdftk
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;No formula found &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;pdftk&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;Searching pull requests...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;Closed pull requests:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;pdftk: 2.02 - a Handy Tool &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; Manipulating PDF Documents &lt;span style="color:#f92672"&gt;(&lt;/span&gt;https://github.com/Homebrew/homebrew/pull/25953&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;お、ということは&lt;code&gt;brew pull&lt;/code&gt;すれば、、、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% brew pull https://github.com/Homebrew/homebrew/pull/25953
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;######################################################################## 100.0%&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Applying patch
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;Applying: pdftk: 2.02 - a Handy Tool &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; Manipulating PDF Documents
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Patch closes issue &lt;span style="color:#75715e"&gt;#25953&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Patch changed:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; Library/Formula/pdftk.rb | &lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; +++++++++++++++++++++++++++
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; file changed, &lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; insertions&lt;span style="color:#f92672"&gt;(&lt;/span&gt;+&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;入れられるようになった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% brew search pdftk
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;pdftk
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;普通にインストールする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% brew install pdftk
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="pdfを結合する"&gt;PDFを結合する&lt;/h1&gt;
&lt;p&gt;結合だけなら次のコマンドでいける。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% pdftk file1.pdf file2.pdf file3.pdf cat output merged.pdf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;file1.pdf file2.pdf file3.pdf&lt;/code&gt; 入力ファイル&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cat&lt;/code&gt; 実行する機能名、catで結合&lt;/li&gt;
&lt;li&gt;&lt;code&gt;output XXXX.pdf&lt;/code&gt; 出力ファイル名を指定する&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="回転分割など"&gt;回転・分割など&lt;/h1&gt;
&lt;p&gt;他にも色々なことが実行できそうだった。ここでは回転と分割だけ試してみる。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;時計回りに90度回転&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% pdftk input.pdf cat 1-endeast output output.pdf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;ページ分割&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% pdftk input.pdf burst
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>cygwinでもsilver searcher(ag)入れてみた</title><link>https://blog.piyo.tech/posts/2014-08-09-200000/</link><pubDate>Sat, 09 Aug 2014 20:00:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-09-200000/</guid><description>&lt;p&gt;高速な検索コマンド&lt;code&gt;ag&lt;/code&gt;をcygwinでも使えるようにしたかったので自分でビルドした。&lt;/p&gt;
&lt;h1 id="apt-cyg"&gt;apt-cyg&lt;/h1&gt;
&lt;p&gt;事前準備としてapt-cygをインストールする。&lt;/p&gt;
&lt;p&gt;apt-cygを入れるとcygwinでもaptとかyumみたいに依存ライブラリをインストールできて便利。導入方法はまとめている人がいるのでそちらを参照。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://kowaimononantenai.blogspot.jp/2013/12/cygwinapt-cyg.html"&gt;○○○○に怖いものなんてない！！: Cygwinにapt-cygを導入する&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="依存ライブラリを入れる"&gt;依存ライブラリを入れる&lt;/h1&gt;
&lt;p&gt;正確ではないかもしれないけれど、このへんのライブラリは入れておく必要がある。それぞれ&lt;code&gt;$ apt-cyg install autoconf&lt;/code&gt;などとする。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;mingw-gcc-g++&lt;/li&gt;
&lt;li&gt;mingw-zlib-devel&lt;/li&gt;
&lt;li&gt;pkg-config&lt;/li&gt;
&lt;li&gt;autoconf&lt;/li&gt;
&lt;li&gt;automake&lt;/li&gt;
&lt;li&gt;gettext&lt;/li&gt;
&lt;li&gt;gettext-devel&lt;/li&gt;
&lt;li&gt;liblzma-devel&lt;/li&gt;
&lt;li&gt;pcre&lt;/li&gt;
&lt;li&gt;libpcre&lt;/li&gt;
&lt;li&gt;xz&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="agをビルドする"&gt;agをビルドする&lt;/h1&gt;
&lt;p&gt;ソースコードをダウンロードしてビルドする。すぐに終わるはず。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ git clone https://github.com/ggreer/the_silver_searcher.git
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ cd the_silver_searcher/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ aclocal &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; autoconf &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; autoheader &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; automake --add-missing
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;$ ./configure
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;$ make
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;$ make install
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;$ which ag
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;/usr/local/bin/ag
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使えるようになった！yay！&lt;/p&gt;</description></item><item><title>ちょっと待て 技術書売るなら Amazonで</title><link>https://blog.piyo.tech/posts/2014-08-08-200000/</link><pubDate>Fri, 08 Aug 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-08-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0a045ab3-ec7c-4e4d-aae6-4804bec29e1d/e8d10d673bcdd1b5e956fb183645e467/deep/0/amazon.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;エンジニアならすでに読んでしまった技術書、内容をマスターしてしまった技術書が家にあるんじゃないかと思う。技術書は買うと高いが、ブックオフみたいなところで売ろうとしても大した値段がつかない。一般的にみれば需要は無いに等しいからね。&lt;/p&gt;
&lt;p&gt;ところでAmazonでは個人でも中古品を売ることができることを知っている人はどのぐらいいるだろうか。Amazonにはマーケットプレイスといって、Amazonに掲載されている商品ならだれでも販売できるプラットフォームがある。かなりいい値段で売れる技術書も多い。&lt;/p&gt;
&lt;p&gt;実際に最近売れた本を例に挙げてみると、例えば新品で購入すると5000円近くするPythonの本、これを4000円＋送料で出品したところすぐに売れた。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4873113938/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/81i7Hys8pxL._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;初めてのPython 第3版&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h1 id="amazonでの中古品"&gt;Amazonでの中古品&lt;/h1&gt;
&lt;p&gt;Amazonで買い物をする人なら知っているかもしれないけど、実は商品のページには中古品の表示がある。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/265022f7-8428-4729-a91f-184ec3950ee5/728d3176344bf98ee00ee9c9416d25e8/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-06-22-18.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;このリンクを押してみると出品されている中古品の一覧と、それぞれの値段、出品者情報、状態などの説明を見ることができる。そしてこの中から選んで購入することもできる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/e226f997-1551-42b4-ae9e-138e3318851f/8b0dfb6c29491453de5444c0c31bc7a3/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-06-22-20.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;買い手にとっては送料がかかったとしても新品よりも2割〜5割程度安い値段で本を購入できるので、一応それなりに買ってもらえる。&lt;/p&gt;
&lt;h1 id="出品手順"&gt;出品手順&lt;/h1&gt;
&lt;p&gt;実際のところ僕が出品者登録をしたのがかれこれ8年ほど前なので、現行の手順のことはよくわからないが、おそらくこちらのURLから進めればいいのだと思う。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://services.amazon.co.jp/services/sell-on-amazon/services-overview.html"&gt;提供するソリューション ： Amazon出品（出店）サービス&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/57e830c3-e93c-41c1-bfb5-452ba59413f0/b34478282b0a8828127a95cec3e91aba/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-06-22-28.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;出品者登録が済んだあとは、商品のページにある「マーケットプレイスに出品する」から出品できる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/41d560ac-7ec5-4e42-a564-e89c0ff5e254/8f481c42e2295f5712dbb60abfe5b0ec/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-06-22-32.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;出品時にはいくつかの情報を入力する。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;商品のコンディション
&lt;ul&gt;
&lt;li&gt;新品&lt;/li&gt;
&lt;li&gt;中古 - ほぼ新品&lt;/li&gt;
&lt;li&gt;中古 - 非常に良い&lt;/li&gt;
&lt;li&gt;中古 - 可&lt;/li&gt;
&lt;li&gt;中古 - 良い&lt;/li&gt;
&lt;li&gt;など&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;商品のコンディション説明&lt;/li&gt;
&lt;li&gt;在庫数&lt;/li&gt;
&lt;li&gt;価格&lt;/li&gt;
&lt;li&gt;配送を自分でやるか、Amazonに代行してもらうか&lt;/li&gt;
&lt;li&gt;国外発送に対応するかどうか&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これに入力すれば出品は終わる。あとは「売れたから発送してくれ」というメールが来るのを待つ。全然売れなければ値段や説明文を変更したほうがいいかもしれない。&lt;/p&gt;
&lt;h1 id="お金の流れ"&gt;お金の流れ&lt;/h1&gt;
&lt;p&gt;（これ書いていいのかな？いいよね？）&lt;/p&gt;
&lt;p&gt;さて、最初に挙げたPythonの本が売れたとき、実際のお金はどんなだったかを書いてみる。&lt;/p&gt;
&lt;p&gt;まず購入してくれた人が支払うのが次の金額。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;商品のお金 4,000円&lt;/li&gt;
&lt;li&gt;配送料 257円&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;計&lt;/strong&gt; 4,257円&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そして出品者である僕がAmazonから受け取ったのは&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;商品+配送料 4,257円&lt;/li&gt;
&lt;li&gt;手数料 -760円&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;計&lt;/strong&gt; 3,497円&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;となる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/370452e1-6aac-47ff-8034-e13fcfb3c248/930d73577ddaa873537e3ff22779eab7/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-06-22-40.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;この手数料は金額などによって変わってくるようだ。どういう決まりで掛かっているのかはわからないが、結構持っていかれる。&lt;/p&gt;
&lt;p&gt;それでも適当な書店で売却するよりはいい値段が付くし、本当に欲しいと思っている人に安く提供できるので良いサービスだと思っている。僕も良く買う。&lt;/p&gt;
&lt;h1 id="tips"&gt;Tips&lt;/h1&gt;
&lt;p&gt;僕が個人的に気をつけていることをちょっとだけ書いて今日の記事を終わりにする。&lt;/p&gt;
&lt;h2 id="商品の説明に個人での出品ですと書く"&gt;商品の説明に「個人での出品です」と書く&lt;/h2&gt;
&lt;p&gt;最近は業者さんが多いが、業者さんは個人と比べると圧倒的に評価件数が多いので何も書かないと評価が低い出品者に思われてしまう気がするからだ。&lt;/p&gt;
&lt;h2 id="状態は正直に書く"&gt;状態は正直に書く&lt;/h2&gt;
&lt;p&gt;勉強や仕事に使った技術書がきれいってことはほとんどない。だからちょっと擦れちゃってるよとか、表紙に傷があるよとかは正直に書く。商品のコンディションは大抵「可」で出すし、よくても「良い」程度にして出品している。&lt;/p&gt;
&lt;h2 id="ぷちぷちで梱包するよと書く"&gt;ぷちぷちで梱包するよ、と書く&lt;/h2&gt;
&lt;p&gt;個人での出品だと本の扱いが雑なんじゃないかと思う人がいる気がするので、ちゃんと梱包材で包みますよと書いておく。&lt;/p&gt;</description></item><item><title>Macでソースコードをきれいに印刷する</title><link>https://blog.piyo.tech/posts/2014-08-07-200000/</link><pubDate>Thu, 07 Aug 2014 20:00:05 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-07-200000/</guid><description>&lt;p&gt;あまりソースコードを印刷するような機会はないかもしれないが、それでもたまーにそういう機会がくることがある。&lt;/p&gt;
&lt;p&gt;これまで似たようなケースではEmacsの&lt;code&gt;htmlize-buffer&lt;/code&gt;を使っていたが、ビジュアル面が不満なので最近はあまり使っていない。&lt;/p&gt;
&lt;p&gt;WindowsではVisual Studioがそれなりの体裁で印刷してくれるのでそれで事足りるのだが、さてMacではどうだろう？今回初めて試したのでそれを記録しておく。&lt;/p&gt;
&lt;h1 id="xcode"&gt;Xcode&lt;/h1&gt;
&lt;p&gt;まずXcodeを試す。普通にソースコードを開いている状態で&lt;code&gt;コマンド+P&lt;/code&gt;で印刷ダイアログが開く。印刷ダイアログからテーマを変更できるので、普段はダーク系のテーマを使っている人も、印刷時は見やすいテーマをここで選ぶことができる。&lt;/p&gt;
&lt;p&gt;Xcodeは概ねよかったのだが、なんと行番号を印刷できない（ように見える）。印刷するのに行番号がないんじゃあかなり使い勝手が悪い。却下。&lt;/p&gt;
&lt;h1 id="sublime-text-3-or-2"&gt;Sublime Text 3 (or 2)&lt;/h1&gt;
&lt;p&gt;Sublime Textのプラグインに「Print to HTML」というものがある。このプラグインを入れて現在編集中のファイルをHTML化してブラウザで開くことができる。&lt;/p&gt;
&lt;h2 id="導入"&gt;導入&lt;/h2&gt;
&lt;p&gt;まずPackage Controlを入れる必要がある。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sublime.wbond.net/installation"&gt;Installation - Package Control&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;続いてコマンドパレットから「Install Package」を選び、「Print to HTML」と入力してこいつをインストールする。&lt;/p&gt;
&lt;p&gt;この状態で&lt;code&gt;Shift+Option+P&lt;/code&gt;キーを入力するとHTML化したものがブラウザで開く。もしくは「File」メニューの「Print as HTML via Browser」から実行してもいい。ブラウザで開くとすぐに印刷ダイアログが出るのであとは好みの設定で印刷すればいい。&lt;/p&gt;
&lt;p&gt;ところで、初期設定のせいかフォントがプロポーショナルフォントになっていてソースコードの印刷には適さない設定になっていた。&lt;/p&gt;
&lt;p&gt;そこで、「Sublime Text」→「Preferences」→「Package Settings」→「Print to HTML」と進み、「Settings - User」を選んでユーザー設定ファイルを開く。&lt;/p&gt;
&lt;p&gt;そしてこれを次のようにする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;font_face&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Consolas, &amp;#39;Courier New&amp;#39;, Courier, Monaco, monospace&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;font_size&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;75%&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;フォントを変更したついでにサイズも少し小さくしておいた。なお、フォントの設定についてはこちらを参考にしている。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://wada811.blogspot.com/2012/12/monospace-font-family.html"&gt;[CSS]等幅フォントにするためのおすすめのfont-family指定 | DevAchieve&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これでそこそこきれいな見た目でソースコードを印刷できるようになった。この方法はSublime Textが動く環境ならどこでもできそうな感じで良い。&lt;/p&gt;</description></item><item><title>Macでコード書いてVisuao Studioに持ってったら文字コードのせいでエラー頻発</title><link>https://blog.piyo.tech/posts/2014-08-06-200000/</link><pubDate>Wed, 06 Aug 2014 20:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-06-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/85f13f35-0fed-49ea-89f2-11f6978ed8ea/09491d3f6fc30b324535b46b925fa5c6/deep/0/7853.VisualStudioLogo_49DD9B64.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;環境に依存しないコードだってことでとりあえずMacとXcodeで開発して、一応動作確認しておくかという段になって初めてVisualStudio2013に持っていったら怪しいコンパイルエラーが頻出してどうにもこうにも困ったことになった。&lt;/p&gt;
&lt;h1 id="状況"&gt;状況&lt;/h1&gt;
&lt;p&gt;そのときの状況を僕のTwitterと共に振り返ってみる。&lt;/p&gt;
&lt;p&gt;まずVisualStudioのコンパイラのせいだと決めつける。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p&gt;VisualStudioのコンパイラがバグってる気がする&lt;/p&gt;&amp;mdash; 大野浩誠 (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/statuses/496551285789712385"&gt;August 5, 2014&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;Updateがあるかどうかを調べ、あったので適用してみる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p&gt;昨日付けでUpdate3が出てたのでまずはUpdateをかけて試してみる。これでダメだったら困るなぁ&lt;/p&gt;&amp;mdash; 大野浩誠 (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/statuses/496551508347871232"&gt;August 5, 2014&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;アップデート待ちの間にもう少し調べてみる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p&gt;コンパイルエラーの行番号が実際とずれてたり、どう見てもあるはずのシンボルがないってエラー出したりしてるからきっとバグ。エラーが出るファイルに必ずあるのはfor文なので、for文の構文解析にでも失敗してるんじゃないかな。どーだろ、わからん&lt;/p&gt;&amp;mdash; 大野浩誠 (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/statuses/496554730336690177"&gt;August 5, 2014&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;アップデートしても結局だめで、日本語コメントの辺りをいじっていたらコンパイルが通ることがわかった。文字コードの警告をそのままにしておくとダメだということだね&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p&gt;これのせいか「 warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。」&lt;/p&gt;&amp;mdash; 大野浩誠 (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/statuses/496565612940771328"&gt;August 5, 2014&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p&gt;日本語コメントの行末に特定の文字があるとコンパイルに失敗する。考えてみれば当たり前だ。疑ってすみません。&lt;/p&gt;&amp;mdash; 大野浩誠 (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/statuses/496565760227950592"&gt;August 5, 2014&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;h1 id="原因"&gt;原因&lt;/h1&gt;
&lt;p&gt;Macでコードを書いたので文字コードはUTF-8になっている。このファイルをVisual Studioに開くと、BOMがないために正しく解釈されないらしい。そんな状態で構文解析をするもんだからコンパイルエラーがでるようだ。&lt;/p&gt;
&lt;p&gt;BOMというのは、↓こういうもの。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Unicodeの符号化形式で符号化したテキストの先頭につける数バイトのデータのことである。このデータを元にUnicodeで符号化されていることおよび符号化の種類の判別に使用する。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://ja.wikipedia.org/wiki/%E3%83%90%E3%82%A4%E3%83%88%E3%82%AA%E3%83%BC%E3%83%80%E3%83%BC%E3%83%9E%E3%83%BC%E3%82%AF"&gt;バイトオーダーマーク - Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="解決法"&gt;解決法&lt;/h1&gt;
&lt;p&gt;全てのソースコードにBOM付けてあげればよい。Visual Studioで「名前をつけて保存」→「エンコード付きで保存」でもBOMはつくらしいが、ファイル数が多いとそんなことはやってられない。&lt;/p&gt;
&lt;p&gt;そこで&lt;code&gt;nkf&lt;/code&gt;コマンドを使い、一括処理することにする。nkfでは以下のコマンドでBOMの付与ができる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% nkf --overwrite --oc&lt;span style="color:#f92672"&gt;=&lt;/span&gt;UTF-8-BOM filepath
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ソースコードのルートディレクトリから&lt;code&gt;find&lt;/code&gt;コマンドと組み合わせて使えば一括処理が可能だ。&lt;/p&gt;
&lt;p&gt;例えば、&lt;code&gt;.h&lt;/code&gt;、&lt;code&gt;.c&lt;/code&gt;、&lt;code&gt;.cpp&lt;/code&gt;ファイルを変換するならこうすればいい（3行に分けずにできそうだけど、そこまでがんばることはない）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% find . -name &lt;span style="color:#e6db74"&gt;&amp;#34;*.h&amp;#34;&lt;/span&gt; -exec nkf --overwrite --oc&lt;span style="color:#f92672"&gt;=&lt;/span&gt;UTF-8-BOM &lt;span style="color:#f92672"&gt;{}&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;% find . -name &lt;span style="color:#e6db74"&gt;&amp;#34;*.c&amp;#34;&lt;/span&gt; -exec nkf --overwrite --oc&lt;span style="color:#f92672"&gt;=&lt;/span&gt;UTF-8-BOM &lt;span style="color:#f92672"&gt;{}&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;% find . -name &lt;span style="color:#e6db74"&gt;&amp;#34;*.cpp&amp;#34;&lt;/span&gt; -exec nkf --overwrite --oc&lt;span style="color:#f92672"&gt;=&lt;/span&gt;UTF-8-BOM &lt;span style="color:#f92672"&gt;{}&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでVisual Studioで警告もでなくなるし、コンパイルエラーもなくなる。よかった。&lt;/p&gt;</description></item><item><title>miniz.cを使ってC言語でファイルを展開する</title><link>https://blog.piyo.tech/posts/2014-08-05-200000/</link><pubDate>Tue, 05 Aug 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-05-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b9c5a6f0-4e5c-4f9f-8edf-401c36e36192/3878172bbf5db20ff7c24dcd64567674/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-05-12-20.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;1ファイルのテキストファイルをzip圧縮したものをC言語のプログラムで元の状態に戻すというサンプルを紹介する。&lt;/p&gt;
&lt;p&gt;使うのはzlib互換（？）っぽいminiz.cというオープンソースのライブラリで、このファイルを導入するだけで使えるようになる。zlibを入れるのは手間だというときに使える。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://code.google.com/p/miniz/"&gt;miniz - Single C source file Deflate/Inflate compression library with zlib-compatible API, ZIP archive reading/writing, PNG writing - Google Project Hosting&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;まずここからminiz.cをダウンロードする。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;プロジェクト&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://code.google.com/p/miniz/source/browse/trunk/miniz.c"&gt;miniz.c&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今回はXcodeを使ったのでこんな風にプロジェクトに追加する。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c5be03c5-df4a-40a1-bb80-7c97a94fe0b3/f75599c8c492bb84db100996548bf1b9/deep/0/decompress---main.cpp.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;main.cpp&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define MINIZ_HEADER_FILE_ONLY
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;#34;miniz.c&amp;#34;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; argc, &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; argv[])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 宣言など
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; mz_zip_archive zip_archive;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; memset(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;zip_archive, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(zip_archive));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// &amp;#34;hoge.txt.zip&amp;#34;を指定して初期化
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; mz_zip_reader_init_file(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;zip_archive, &lt;span style="color:#e6db74"&gt;&amp;#34;hoge.txt.zip&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 0番目（第2引数）のファイルを&amp;#34;hoge.txt&amp;#34;として展開
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; mz_zip_reader_extract_to_file(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;zip_archive, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;decompressed.txt&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;展開したいファイルとして指定している&lt;code&gt;hoge.txt.zip&lt;/code&gt;は単なるテキストファイルである&lt;code&gt;hoge.txt&lt;/code&gt;をFinder上で右クリックして圧縮したものである。このプログラムを実行するとちゃんと作業ディレクトリに&lt;code&gt;decompressed.txt&lt;/code&gt;ができていることがわかる。&lt;/p&gt;
&lt;p&gt;複数ファイルやディレクトリを含んだzipファイルを対象にする場合は&lt;code&gt;mz_zip_reader_extract_to_file&lt;/code&gt;の第2引数で何番目の中身を展開するかという指定ができる。&lt;/p&gt;
&lt;p&gt;その際にはファイルがいくつあるかを調べたり、N番目のファイルの詳細を調べたりする関数を使って欲しいものを見つける。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat); &lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>自作gemがちょっとダウンロードされていて謎</title><link>https://blog.piyo.tech/posts/2014-08-04-200000/</link><pubDate>Sun, 03 Aug 2014 20:02:12 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-04-200000/</guid><description>&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-07-06-193000"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-07-06-193000" alt="マークダウンに見出し番号をつけるRuby Gem書いた - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-07-06-193000"&gt;マークダウンに見出し番号をつけるRuby Gem書いた - ぴよログ&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/https://blog.piyo.tech/posts/2014-07-06-193000" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/https://blog.piyo.tech/posts/2014-07-06-193000" alt="はてなブックマーク - マークダウンに見出し番号をつけるRuby Gem書いた - ぴよログ" title="はてなブックマーク - マークダウンに見出し番号をつけるRuby Gem書いた - ぴよログ" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;前にちょろっと作ったgemのダウンロード数を見てみたらこんなことになっていた。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/4a9e9bf8-56e9-4ff1-bdba-5572f9b09df5/c79a8109d5b1be55f523d55e3d541769/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-08-01-13-31.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://rubygems.org/gems/markdown_section_numbering"&gt;markdown_section_numbering | RubyGems.org | your community gem host&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;rubygemsの検索でmarkdownとやっても全然出てこないし、どこで見つけるんでしょうね？&lt;/p&gt;</description></item><item><title>smart-cursor-color</title><link>https://blog.piyo.tech/posts/2014-08-02-200000/</link><pubDate>Sat, 02 Aug 2014 20:00:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-02-200000/</guid><description>&lt;p&gt;Emacsをマルチフレームにするとカーソルの色が真っ黒になって見えなくなることがあってイラっとしたので、&lt;code&gt;smart-cursor-color-mode&lt;/code&gt;っていうelispを入れてそもそもカーソルの色をスマートにしてみた。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/7696122/smart-cursor-color"&gt;7696122/smart-cursor-color&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これを入れるとカーソルの色が現在位置している文字の色に合わせて変わってくれるようになる。多分真っ黒になって見えない現象は回避できている気がする。もちろんその分の処理があるので少しだけ重くなる感じもあるが今のところ気にならない。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;赤系&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/17fb405c-786b-4c39-a6fb-8c138b7ed9ab/15b6c0dc79682a6790d1a6722ba940c3/deep/0/56-smart-cursor-color.el--@-mestalla.local----24.3.1.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;紫系&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/e31fb04a-29be-4895-8a53-d32d70b11716/37668888f6603908f74d9b5d002fa5c1/deep/0/56-smart-cursor-color.el--@-mestalla.local----24.3.1.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>ace-jump-modeをHyperキーと絡めてタイプ数減らすやつ</title><link>https://blog.piyo.tech/posts/2014-08-01-200000/</link><pubDate>Fri, 01 Aug 2014 20:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-08-01-200000/</guid><description>&lt;p&gt;そのまんまこの記事のことを実践しただけなんだけど、すごくいい。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://d.hatena.ne.jp/rkworks/20120520/1337528737"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://d.hatena.ne.jp/rkworks/20120520/1337528737" alt="Emacsで1～3ストロークで画面上の任意の場所に移動するための設定 - non-nil" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://d.hatena.ne.jp/rkworks/20120520/1337528737"&gt;Emacsで1～3ストロークで画面上の任意の場所に移動するための設定 - non-nil&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/rkworks/20120520/1337528737" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/rkworks/20120520/1337528737" alt="はてなブックマーク - Emacsで1～3ストロークで画面上の任意の場所に移動するための設定 - non-nil" title="はてなブックマーク - Emacsで1～3ストロークで画面上の任意の場所に移動するための設定 - non-nil" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;例えばこんなケースを想像して欲しい。Emacsでソースコードを書いていてカーソルは画面の一番上あたりにあり、次に編集したい箇所が画面の一番下あたりだったとする。&lt;/p&gt;
&lt;p&gt;どうやって移動するだろうか？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;矢印キーで移動する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-n&lt;/code&gt;で移動する&lt;/li&gt;
&lt;li&gt;goto-lineで行番号を指定して移動する&lt;/li&gt;
&lt;li&gt;インクリメンタル検索で移動する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;選択肢はいくつかある。これまでの僕だったらインクリメンタル検索を使っていたと思う。&lt;/p&gt;
&lt;p&gt;今日導入したace-jump-modeは上のどの選択肢にも勝る。特に最初に載せたページの設定を済ませておくと本当にタイプ数が少なくて済む。&lt;/p&gt;
&lt;p&gt;ace-jump-modeは編集中のバッファの画面中に表示されている部分を対象に、キーボードでジャンプできるようにする機能だ。流れとしてはこんな感じ。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ace-jump-modeを有効にする&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;移動したい箇所にある文字を1文字入力する&lt;/li&gt;
&lt;li&gt;画面上に移動に使うキーが表示されるのでそのキーを入力&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hyperキーを組み合わせた設定では上のステップのうち1と2を同時に行ってしまう。例えば&lt;code&gt;H-a（Hyperキーを押しながらa）&lt;/code&gt;はace-jump-modeを有効にしたあと&lt;code&gt;a&lt;/code&gt;に移動したい、という指定をしたときの同じ挙動になる。そのため、最低2回の入力で目的地にカーソルを持っていけるということになるわけだ。&lt;/p&gt;
&lt;p&gt;言葉で説明するのはとても難しいのでデモを用意した。&lt;/p&gt;
&lt;p&gt;なおHyperキーには参考サイトと同じく右コマンドを割り当てている。&lt;/p&gt;
&lt;iframe width="420" height="315" src="//www.youtube.com/embed/5pQXhFnArQs" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;</description></item><item><title>XcodeでC言語のメモリリークを検出</title><link>https://blog.piyo.tech/posts/2014-07-31-200000/</link><pubDate>Thu, 31 Jul 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-31-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/d8c748f7-a779-48ad-a982-86726a95ea08/7613c9c070df996f243e667fa6b5d18f/deep/0/Profile-'MemLeak'.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;久しぶりにmallocするプログラムを書いているのでメモリリークが怖い。そこでXcodeのInstrumentsによるメモリリークの検出が本当にできるかどうかを簡単な例で試しておくことにした。これでいざというときに使える。&lt;/p&gt;
&lt;p&gt;まず普通に構造体を定義する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/* Sample.h */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#ifndef __MemLeak__Sample__
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define __MemLeak__Sample__
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; _sample_
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;string a;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;string b;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;string c;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;string d;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;string e;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;string f;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;string g;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;string h;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;} Sample, &lt;span style="color:#f92672"&gt;*&lt;/span&gt;SampleP;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#endif &lt;/span&gt;&lt;span style="color:#75715e"&gt;/* defined(__MemLeak__Sample__) */&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;メイン関数では&lt;code&gt;malloc&lt;/code&gt;するだけして解放しないということを1秒毎に繰り返してみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/* main.cpp */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;#34;Sample.h&amp;#34;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;SampleP &lt;span style="color:#a6e22e"&gt;CreateSample&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;sample created&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (SampleP)&lt;span style="color:#a6e22e"&gt;malloc&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(Sample));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; argc, &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; argv[])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt;(true){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; SampleP p &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CreateSample&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, p&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;c.&lt;span style="color:#a6e22e"&gt;c_str&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;sleep&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そしてInstrumentsを&lt;code&gt;コマンド+I&lt;/code&gt;で起動し、Leaksを選ぶ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/f80c7722-c567-472d-b680-e11337d7fbfc/c34a12a19cfb98be696cc08f71dca9a2/deep/0/Profile-'MemLeak'.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;するとプログラムが動き出し、Instrumentsの画面には次々にメモリ確保がなされる様子と時々Leakした様子が表れる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7821f5da-f35c-49f7-ac78-ef7297354973/c3a9f713b1bb9e401f1129daa7c92c21/deep/0/Instruments-%E3%81%A8-MemLeak---main.cpp.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Leakしたオブジェクトの一覧を見てみると、ちゃんと&lt;code&gt;CreateSample&lt;/code&gt;で確保したメモリがリークしてるよと教えてくれている。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/532c4858-f34a-48de-a764-81f4f082583e/2c66dd2bd79dc55e13663b44c76e3250/deep/0/Instruments.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ちゃんとC言語のコードでも動いていることが確認できた。よかった！&lt;/p&gt;</description></item><item><title>Macで数式を書いて他のソフトに貼れるLaTeXiT超すごい</title><link>https://blog.piyo.tech/posts/2014-07-30-200000/</link><pubDate>Wed, 30 Jul 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-30-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/d294522a-4b68-4a9a-a374-71e7be97ff34/ba009bdbb52b33f6432ee02190112d63/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-28-21-14.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;LaTeXiTを導入してみた話は書いたが、ここまですごいとは思わなかった。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-07-29-200000"&gt;MacでTexの数式を！LaTeXiTを使えるようになるまで&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;LaTeXiTで数式を作り他のアプリにはってみる。&lt;/p&gt;
&lt;h2 id="例えばkeynote"&gt;例えばKeynote&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/3399d40f-e035-49f9-81ea-a6728d559e4f/67c7dcdc5be1934f032649adc70262d0/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-28-20-59.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;そうするとベクターデータでKeynoteに数式が貼り付けられる。拡大縮小も自由自在だ。&lt;/p&gt;
&lt;p&gt;次に、LaTeXiTを一旦クリアして今度は先ほどKeynoteに貼り付けた数式をコピペしてみる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b732d930-9995-4bdd-b6cb-9d5c4529a801/8f2d500d4cc459051be12d64a29dbfba/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-28-21-00.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;すると先ほど手入力したものと同じ数式がちゃんとペーストされるのである。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/e5023483-d903-42a6-9bc2-c80cb7406160/b1a064ea64e999b2e357955d94f709a9/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-28-21-03.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="例えばomnigraffle"&gt;例えばOmniGraffle&lt;/h2&gt;
&lt;p&gt;次にOmniGraffleで試してみる。&lt;/p&gt;
&lt;p&gt;LaTeXiTからドロップするとベクター形式で貼り付けられるのはKeynoteと一緒。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/1db1d002-d6c2-4ef6-808f-0a3e6e635d46/e87fab720bec76c3da6222cadf5e0bcf/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-28-21-04.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;次に一旦LaTeXiTを閉じて先ほど貼り付けた数式をダブルクリックしてみる。すると、なんとLaTeXiTが起動するじゃんか！&lt;/p&gt;
&lt;p&gt;その上、変更した分はすぐに反映してくれる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/56afaeac-1c4b-4065-9e0a-b6bc88399fea/928eaca5711353754d340fe9cb898054/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-28-21-07.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;これができるとなると、適当に数式を埋め込んでおいて必要になったときにダブルクリックしてLaTeXiTを起動して編集、なんてことができるようになる。これはいいかも。&lt;/p&gt;
&lt;p&gt;まあ、使う場面はあまりないのだけれど。&lt;/p&gt;
&lt;p&gt;OmniGraffleのように数式側からLaTeXiTを起動できるアプリケーションの条件ってなんだろう？Wordではできなかったし、Keynoteでは矩形選択でしかオブジェクトを選択できなかったのでダブルクリックを試せていないし。&lt;/p&gt;
&lt;p&gt;ちなみにillustratorは表示がおかしくなった。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/5064aba7-ba50-4047-aa5d-ff30560ed9f3/d53a14e4da7af02074db1c4b6124b453/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-28-21-13.png" alt=""&gt;&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4774160458/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/51UNf22nkGL.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;[改訂第6版] LaTeX2ε美文書作成入門&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>MacでTexの数式を！LaTeXiTを使えるようになるまで</title><link>https://blog.piyo.tech/posts/2014-07-29-200000/</link><pubDate>Tue, 29 Jul 2014 20:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-29-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/8cc5f086-3512-46bf-ad07-377cb0339ef5/7dc9e65b27fe72253c903e7bdc2676ab/deep/0/latexit-drag.png" alt=""&gt;&lt;/p&gt;
&lt;h1 id="homebrewでtexをインストール"&gt;HomebrewでTexをインストール&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://sakueji.com/mactex-reinstall/"&gt;MacBookAirにTeXを入れなおした話。| えじの自由帳&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;% brew tap phinze/cask&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;% brew install brew-cask&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;% brew cask install mactex&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/usr/texbin&lt;/code&gt;にパスを通す&lt;/li&gt;
&lt;li&gt;&lt;code&gt;% sudo tlmgr update --self --all&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;% brew cask install mactex&lt;/code&gt;でエラーが出たので、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% brew cask install mactex
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;Warning: Trouble with automatic Tap migration. You may need to run &lt;span style="color:#e6db74"&gt;&amp;#34;brew update &amp;amp;&amp;amp; brew upgrade brew-cask &amp;amp;&amp;amp; brew cleanup &amp;amp;&amp;amp; brew cask cleanup&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Adding caskroom Tap
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;Error: No available cask &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; mactex
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;Error: nothing to install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;言われた通りのコマンドを実行。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% brew update &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; brew upgrade brew-cask &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; brew cleanup &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; brew cask cleanup
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;もう一度トライするとなんとかいけたみたい。Sorryとか言われているけど気にしない！&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;% brew cask install mactex
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;Pruned &lt;span style="color:#ae81ff"&gt;459&lt;/span&gt; dead formulae
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;Warning: Could not tap phinze/cask/brew-cask over caskroom/cask/brew-cask
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;Tapped &lt;span style="color:#ae81ff"&gt;460&lt;/span&gt; formulae
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Removing legacy Tap
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Caveats
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;To use mactex, zsh users may need to add the following line to their
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;~/.zprofile. &lt;span style="color:#f92672"&gt;(&lt;/span&gt;Among other effects, /usr/texbin will be added to the
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;PATH environment variable&lt;span style="color:#f92672"&gt;)&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; eval &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;/usr/libexec/path_helper -s&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Downloading http://mirror.ctan.org/systems/mac/mactex/mactex-20140525.pkg
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;######################################################################## 100.0%%P&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Running installer &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; mactex; your password may be necessary.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;Password:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[==&lt;/span&gt;&amp;gt; installer: Package name is MacTeX-2014
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; installer: Installing at base path /
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; installer: The install was successful.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Sorry, try again.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;🍺 mactex installed to &lt;span style="color:#e6db74"&gt;&amp;#39;/opt/homebrew-cask/Caskroom/mactex/20140525&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;2.3G&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="latexit"&gt;LaTeXiT&lt;/h1&gt;
&lt;p&gt;ここからdmgをダウンロードし、&lt;code&gt;.app&lt;/code&gt;ファイルをアプリケーションにコピー。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.chachatelier.fr/latexit/latexit-downloads.php?lang=en"&gt;LaTeXiT&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;LaTeXit.appを起動して環境設定を開き、プログラムタブを開いてみるとどうやら先程インストールしたMacTexのディレクトリに設定が通っているようだ。&lt;/p&gt;
&lt;p&gt;早速入力欄に数式を打って右下の「LaTeX it!」してみるとこうなった。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9b8d4ffc-d49d-4682-9ccc-4a067d784993/0db814a39783ac50e3f6daab28ca1462/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-28-20-46.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;上にある数式をドラッグアンドドロップで別アプリケーションに持っていくこともできる。これはすごい。&lt;/p&gt;
&lt;p&gt;Texに関しては卒論・修論でこの本にお世話になった。当時は第2版か第3版だった記憶がある。もう第6版にもなっているのね。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4774160458/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/51UNf22nkGL.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;[改訂第6版] LaTeX2ε美文書作成入門&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>ようやくpeco導入！</title><link>https://blog.piyo.tech/posts/2014-07-28-200000/</link><pubDate>Mon, 28 Jul 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-28-200000/</guid><description>&lt;p&gt;pecoはシェルで使えるインクリメンタルな絞り込みツールでzshと組み合わせると最強なツール。半年ぐらい前にpercolを知ってずっと気になっていたものの手を出せなかったが、気晴らしが必要になったのでついに導入した。&lt;/p&gt;
&lt;p&gt;ここをそのまんま参考にしてpecoを導入した。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://shibayu36.hatenablog.com/entry/2014/06/27/223538"&gt;pecoを使い始めた - $shibayu36-&amp;gt;blog;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Go環境がなかったのでpecoはHomebrew経由でインストールした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% brew tap peco/peco
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;% brew install peco
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;先ほどのリンク先にあるように、コマンドの履歴とディレクトリの履歴をpecoれるようにしている。&lt;/p&gt;
&lt;p&gt;ところで僕の環境では2点ハマった箇所があったのでメモしておきたい。&lt;/p&gt;
&lt;h1 id="コマンド履歴が動作しない"&gt;コマンド履歴が動作しない&lt;/h1&gt;
&lt;p&gt;oh-my-zshを使用していると&lt;code&gt;history&lt;/code&gt;コマンドが&lt;code&gt;fc -l 1&lt;/code&gt;というコマンドにエイリアスされている。そのため、&lt;code&gt;peco-select-history()&lt;/code&gt;内の&lt;code&gt;history&lt;/code&gt;の箇所でエラーが出てしまうため何も起こらないという問題が起きていた。&lt;/p&gt;
&lt;p&gt;エイリアスではなく本体を呼ぶためにはバックスラッシュをつけてあげればいいので、zshの設定ファイルで書いた&lt;code&gt;history&lt;/code&gt;の箇所を&lt;code&gt;\history&lt;/code&gt;と書き換えることで動くようにできた。&lt;/p&gt;
&lt;h1 id="cdrがない件"&gt;cdrがない件&lt;/h1&gt;
&lt;p&gt;ディレクトリ移動の履歴をpecoるためにcdrというコマンドを使うんだけど、僕の環境には入っていなかった。結局zshをバージョンアップすればよかった。それについてはこちらにまとめている。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-07-25-193000"&gt;システムのzshにcdrが無かったのでバージョンアップした&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;実は↑の記事には次のようなコメントをいただいている。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;zshのcdrはバージョン4.3.11から標準で入ったようです。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Macに最初から入っているバージョンでもcdrは使えるはずだとのこと。だから僕の環境では何か壊れていたのかもしれない。とにかく入れなおしたらいけたから良しとして深追いはやめておく。&lt;/p&gt;</description></item><item><title>Cocoa Emacsにスペースを1つ残して削除するキーバインドがない</title><link>https://blog.piyo.tech/posts/2014-07-27-200000/</link><pubDate>Sun, 27 Jul 2014 20:00:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-27-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/e4b627b6-821d-4550-a6f1-f250bc104f21/9adbb0efbc75eb9be67017c707c9c189/deep/0/Emacs.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;スペースを1つ残して削除したいときって結構多いんだけど、MacのEmacsでキーバインドが設定されていなくて全然使わなくなっていた。今日コード書いていてイラっとしたので自分でアサインしました。&lt;/p&gt;
&lt;p&gt;スペースを1つ残すってのはどういうことかというと、例えば↓みたいなコードをちょっと編集する場合に、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;h &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; id: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; name: &lt;span style="color:#e6db74"&gt;&amp;#34;hoge&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;phone&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;000-00-00&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こんな風になってしまったとする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;h &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { id: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, name: &lt;span style="color:#e6db74"&gt;&amp;#34;hoge&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;phone&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;000-00-00&amp;#34;&lt;/span&gt;, }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;id&lt;/code&gt;と&lt;code&gt;name&lt;/code&gt;の間のスペースにカーソルを置いた状態でEmacsの&lt;code&gt;just-one-space&lt;/code&gt;を実行すると、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;h &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { id: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, name: &lt;span style="color:#e6db74"&gt;&amp;#34;hoge&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;phone&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;000-00-00&amp;#34;&lt;/span&gt;, }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こんな風になってくれる。地味に便利。&lt;/p&gt;
&lt;p&gt;設定ファイルで標準だと思われる&lt;code&gt;M-SPC（メタ+スペース）&lt;/code&gt;にアサインして設定完了。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-elisp" data-lang="elisp"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;(&lt;span style="color:#a6e22e"&gt;define-key&lt;/span&gt; global-map (kbd &lt;span style="color:#e6db74"&gt;&amp;#34;M-SPC&amp;#34;&lt;/span&gt;) &lt;span style="color:#e6db74"&gt;&amp;#39;just-one-space&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Xcodeでファイルごとにインデント設定を変える</title><link>https://blog.piyo.tech/posts/2014-07-26-203000/</link><pubDate>Sat, 26 Jul 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-26-203000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/6456362f-92db-4740-b285-e167ede8d392/7e1aa119c261b9db4cbcb739df6e33de/deep/0/xcode.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Objective-Cで書くときはインデント幅4を使うんだけど、CとかC++をXcodeで書くときはやっぱり幅2でインデントしたい。Xcode全体の設定を変更してしまうといちいち面倒だし、Objective-C、C++両方のソースが混在しているときどうするのって問題も発生する。&lt;/p&gt;
&lt;p&gt;どうしたもんかと悩んでいたらXcodeの右側に出てるユーティリティにインデントの設定があるじゃんか！ナビゲーターでインデント設定を変更したいファイルを全て選択して、インデント幅を変更してあげればよさそう。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;before&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/bcde82f2-610a-4c1b-bf6a-34f2cc52447b/7ac2cad93760224bcb2c03084894f32d/deep/0/cpptest---main.cpp.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;after&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/fd773aa1-c56f-4f54-8894-d86aa1613654/7867a9d9e3b5b1c19066378b9ba4e438/deep/0/cpptest---main.cpp.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>システムのzshにcdrが無かったのでバージョンアップした</title><link>https://blog.piyo.tech/posts/2014-07-25-193000/</link><pubDate>Fri, 25 Jul 2014 19:30:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-25-193000/</guid><description>&lt;p&gt;pecoを入れてcdを便利するぞ！って意気込んでたら、使っていたzshが古くて&lt;code&gt;cdr&lt;/code&gt;が無いって怒られてテンションが下がったうえ、しばらくその理由に気がつかなくてストレス溜まったのでメモしておく。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% cdr
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;zsh: command not found: cdr
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちなみにシステムに入っているzshのバージョンは5.0.2だった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% /bin/zsh --version
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;zsh 5.0.2 &lt;span style="color:#f92672"&gt;(&lt;/span&gt;x86_64-apple-darwin13.0&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;2014年7月23日現在最新は5.0.5で、&lt;code&gt;cdr&lt;/code&gt;も5.0.2以降で標準に入ったらしい。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sourceforge.net/p/zsh/code/ci/master/tree/ChangeLog"&gt;zsh / Code / [35176b] /ChangeLog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そういうわけで、Homebrewで最新バージョンをいれましょー。&lt;/p&gt;
&lt;p&gt;まずインストール。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% brew install --disable-etcdir zsh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そしたら&lt;code&gt;/etc/shells&lt;/code&gt;を編集。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% sudo vi /etc/shells
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ファイルの最後にこれを追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;/usr/local/bin/zsh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最後にシェルを変更すればOK！&lt;/p&gt;
&lt;p&gt;&lt;code&gt;% chsh -s /usr/local/bin/zsh&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% zsh --version
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;zsh 5.0.5 &lt;span style="color:#f92672"&gt;(&lt;/span&gt;x86_64-apple-darwin13.3.0&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Railsでapp/assets/images以下に置いた画像のパスをモデルで参照する</title><link>https://blog.piyo.tech/posts/2014-07-24-193000/</link><pubDate>Thu, 24 Jul 2014 19:30:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-24-193000/</guid><description>&lt;p&gt;&lt;code&gt;app/assets/images&lt;/code&gt;以下に置いた画像をViewから参照するには&lt;code&gt;asset_path&lt;/code&gt;を使えばいい。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;app/assets/images/title.png&lt;/code&gt;を参照したいのであれば&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; image_tag asset_path(&lt;span style="color:#e6db74"&gt;&amp;#34;title.png&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;としておけばプロダクション環境でもちゃんと参照できる（はず）。&lt;/p&gt;
&lt;p&gt;で、このメソッドをモデルから呼ぶ方法はないのか？ってのを調べた。たとえば、プロフィール画像が設定されていなかったらデフォルト画像を出すみたいなメソッドを用意しておくとViewのコードが煩雑にならないだろうし。&lt;/p&gt;
&lt;p&gt;いや普通はヘルパー使えばいいのかなと思うんだけど、試しに呼んでみたということで。&lt;/p&gt;
&lt;p&gt;実は&lt;code&gt;asset_path&lt;/code&gt;というメソッドは&lt;code&gt;ActionController::Base.helpers&lt;/code&gt;に定義されているので、モデルからは&lt;code&gt;ActionController::Base.helpers.asset_path&lt;/code&gt;として参照できてしまう。&lt;/p&gt;
&lt;p&gt;他にも色々呼べちゃうのでいざというときには覚えておくといいかも？しれない。&lt;/p&gt;</description></item><item><title>C/C++のXML Parserについてよくまとまっているサイト</title><link>https://blog.piyo.tech/posts/2014-07-21-193000/</link><pubDate>Mon, 21 Jul 2014 19:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-21-193000/</guid><description>&lt;p&gt;仕事でC/C++のXMLパーサーにどんなもんがあるか調べていたらよくまとまっているサイトに出くわしたので紹介してみる。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="http://lars.ruoff.free.fr/xmlcpp/" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;Free C/C&amp;#43;&amp;#43; XML Parser Libraries&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;span class="truncate"&gt;lars.ruoff.free.fr&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;リンク先に飛べばよくわかるけれど、これだけのライブラリについてライセンスや特徴をまとめてくれている。&lt;/p&gt;
&lt;h1 id="がっつり目"&gt;がっつり目&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://xml.apache.org/xerces-c/index.html"&gt;Xerces &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.jezuk.co.uk/cgi-bin/view/arabica"&gt;Arabica &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://xmlsoft.org/"&gt;libxml2 &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://libxmlplusplus.sourceforge.net/"&gt;libxml++ &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms763742.aspx"&gt;MSXML &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="あっさり目"&gt;あっさり目&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://expat.sourceforge.net/"&gt;expat &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.grinninglizard.com/tinyxml/"&gt;TinyXml &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.fxtech.com/xmlio/"&gt;Xmlio &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/ja-jp/magazine/cc163436.aspx"&gt;XmlLite &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rapidxml.sourceforge.net/index.htm"&gt;RapidXml &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.applied-mathematics.net/tools/xmlParser.html"&gt;XMLParser library from Frank Vanden Berghen &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/pugixml/"&gt;PugiXML &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.libroxml.net/"&gt;libroxml &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;いくつか試したなかではTinyXmlが軽量で導入もしやすくて使いやすかったが、DOM型のパーサーなので読み込むファイルが大きくなるとメモリ不足に陥ってしまう。そういうときはSAX系のパーサーを使う必要があるのでXmlLiteや、がっつり目のライブラリを使う必要がある。&lt;/p&gt;
&lt;p&gt;Windows + Visual Studioな環境ならMSXMLやXmlLiteがそのまま使えていいかもしれない。&lt;/p&gt;</description></item><item><title>商用利用可能な地図配布サイト見つけた</title><link>https://blog.piyo.tech/posts/2014-07-20-200000/</link><pubDate>Sun, 20 Jul 2014 20:00:04 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-20-200000/</guid><description>&lt;p&gt;地理とか地図に関連する勉強とか、地図データを使った何かを作るときに役に立つサイトを見つけた。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://d-maps.com/index.php?lang=en"&gt;d-maps.com : free maps, free blank maps, free outline maps, free base maps&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;世界・国・州や県などのレベルで、白地図や境界線、川や主要道路の有無などいろいろなパターンの地図が用意されていて、以下の項目を守れば商用利用もできるみたい。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The exact URL where the original map comes from must be mentioned&lt;/li&gt;
&lt;li&gt;The number of used maps is limited to 10 for a publication (Web, DVD, book…)&lt;/li&gt;
&lt;li&gt;The number of used maps is unlimited with BeGraphic GIS use.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例えば僕の住む静岡県だけでも42種類の地図が用意されていた。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/27888e0b-9d74-4633-9133-c9abbabd7085/10e42a107615a8eeef4f34411893f337/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-18-22-09.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;この調子で色々な国に対応しているもんだからすごい。ちなみに静岡県はここから。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://d-maps.com/pays.php?num_pay=541&amp;amp;lang=en"&gt;Shizuoka: Free maps, free blank maps, free outline maps, free base maps&lt;/a&gt;&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4807161148/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/51rCU0aPumL._SL1000_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;新詳高等地図 (Teikoku’s Atlas)&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>form_forのf.selectのhtml_options</title><link>https://blog.piyo.tech/posts/2014-07-19-193000/</link><pubDate>Sat, 19 Jul 2014 19:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-19-193000/</guid><description>&lt;p&gt;Railsのフォームで使う&lt;code&gt;form_for&lt;/code&gt;。レイアウト調整のために各種コントロールにもclassを設定しているのに、あるフォームのドロップダウンリストにスタイルが適用されていないことに気がついた。なんだろうと思ってリファレンスを見てみると、&lt;code&gt;f.select&lt;/code&gt;のシグネチャはこんなんだった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;select(method, choices &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;, options &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {}, html_options &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {}, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;block)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちなみに&lt;code&gt;f&lt;/code&gt;は&lt;code&gt;ActionView::Helpers::FormBuilder&lt;/code&gt;というものらしい。&lt;/p&gt;
&lt;p&gt;で、僕が書いていたフォームはこうなっていた（&lt;code&gt;f.select&lt;/code&gt;の部分を抜粋）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; form_for (&lt;span style="color:#f92672"&gt;...&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;f&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;form&lt;span style="color:#f92672"&gt;-&lt;/span&gt;group
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;label &lt;span style="color:#e6db74"&gt;:my_option&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;選択肢&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;select &lt;span style="color:#e6db74"&gt;:my_option&lt;/span&gt;, &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hoge&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;fuga&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;piyo&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;class&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;form-control&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こう見ると第3引数にクラス指定のハッシュを渡していることがわかるが、先ほどの定義をみればわかる通り、HTML関係のオプションは第4引数に渡さなければならない。&lt;/p&gt;
&lt;p&gt;つまり、指定の仕方が間違っていたということだ。本当は次のようにしなければいけなかった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; form_for (&lt;span style="color:#f92672"&gt;...&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;f&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;form&lt;span style="color:#f92672"&gt;-&lt;/span&gt;group
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;label &lt;span style="color:#e6db74"&gt;:my_option&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;選択肢&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;select &lt;span style="color:#e6db74"&gt;:my_option&lt;/span&gt;, &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hoge&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;fuga&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;piyo&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;, {}, &lt;span style="color:#e6db74"&gt;class&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;form-control&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;第3引数に空ハッシュを渡し、&lt;code&gt;class: &amp;quot;form-control&amp;quot;&lt;/code&gt;が第4引数として扱われるようにすればいい。&lt;/p&gt;
&lt;p&gt;しっかし、この手の引数ネタ、前も引っかかったなー。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-07-01-203000"&gt;Railsのredirect_toでちょっとだけはまる - ぴよログ&lt;/a&gt;&lt;/p&gt;</description></item><item><title>CarrierWaveでアップロードした画像のファイル名を日時にすると困る</title><link>https://blog.piyo.tech/posts/2014-07-18-203000/</link><pubDate>Fri, 18 Jul 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-18-203000/</guid><description>&lt;p&gt;CarrierWaveというgemを使うとRailsアプリケーションに画像アップロード系の機能を割と楽に実装できる。&lt;/p&gt;
&lt;p&gt;アップロード先はサーバーローカルだけでなく、AmazonS3やGoogleなどのクラウド系のストレージにも対応しているし、アップロード時にリサイズ画像を用意したりファイル名を変更したりと色々なカスタマイズができるため、画像アップロード系は大体このgemだけでカバーできるというすぐれものだ。&lt;/p&gt;
&lt;p&gt;ところで、そのファイル名のカスタマイズでちょっとハマったのでメモしておこうと思う。&lt;/p&gt;
&lt;h1 id="使い方おさらい"&gt;使い方おさらい&lt;/h1&gt;
&lt;p&gt;CarrierWaveの使い方をざっとおさらいしておく。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Gemfileに&lt;code&gt;gem &amp;quot;carrierwave&amp;quot;&lt;/code&gt;と書いて&lt;code&gt;bundle install&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;画像を持つモデル（Itemとする）をつくる &lt;code&gt;rails generate model Item image:string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;アップローダーを作る &lt;code&gt;rails generate uploader ItemImage&lt;/code&gt;な&lt;/li&gt;
&lt;li&gt;Itemモデルにアップローダーを関連付ける&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;3.で生成されたアップローダーファイルはこんな感じになる。&lt;code&gt;filename&lt;/code&gt;の部分は追記したところで、日時をファイル名にしている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# encoding: utf-8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ItemUploader&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;CarrierWave&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Uploader&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; storage &lt;span style="color:#e6db74"&gt;:file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;store_dir&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;uploads/&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;model&lt;span style="color:#f92672"&gt;.&lt;/span&gt;class&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_s&lt;span style="color:#f92672"&gt;.&lt;/span&gt;underscore&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;mounted_as&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;model&lt;span style="color:#f92672"&gt;.&lt;/span&gt;id&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;filename&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Time&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;now&lt;span style="color:#f92672"&gt;.&lt;/span&gt;strftime(&lt;span style="color:#e6db74"&gt;&amp;#34;%Y%m%d-%H%M%S&amp;#34;&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.png&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;4.のところではItemモデルにちょっと追記する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Item&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; mount_uploader &lt;span style="color:#e6db74"&gt;:image&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;ItemUploader&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="何が問題だったのか"&gt;何が問題だったのか&lt;/h1&gt;
&lt;p&gt;このやり方だと、**画像を更新しなくてもモデルが持っているファイル名が上書きされてしまう！**というのが問題だった。&lt;/p&gt;
&lt;p&gt;おなじみScaffoldのフォームで見てみる。このようなフォームからItemを生成する。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c4925da9-7390-486c-a2b7-94862c693a4d/dc2e8337e8e1cef10842d4cc79ef457d/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-18-14-32.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;すると、こんな感じでItemが生成される。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/f10abfc8-7ccd-449b-bbf6-ed8bb2a60670/e91db99ec75e85fe0e08aae3e3a2b694/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-18-14-33.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Imageのところに書いてあるPathを&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;タグに渡せばちゃんと画像が表示される。&lt;/p&gt;
&lt;p&gt;そしてEdit。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/a32c71e2-5da9-4801-945e-7d0267bbe6cb/5195ceb5004a5abe0762536cad7604a1/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-18-14-34.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;名前だけ変更してファイルは指定なしで更新してみる。すると、画像ファイルのパスが変わってしまっているのである。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/382b2245-b241-40d1-8cb6-4ada81fcc4da/2067cb15c5c7cc45553a2b8cfa741aae/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-18-14-35.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ところがその先には画像ファイルはなく、画像は以前のパスのところにある。つまり、画像を変更していないのにパスが変わってしまうのである。&lt;/p&gt;
&lt;p&gt;更新がありうる画像ファイルの場合はファイル名を時間に依存したものやランダムなものにするとあとから参照できなくなってしまうことがあるのでダメだよ、というのが今回のお話。&lt;/p&gt;
&lt;h1 id="サンプルコード"&gt;サンプルコード&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/ruby-sandbox/tree/master/carrierwave-sample"&gt;ruby-sandbox/carrierwave-sample at master · xoyip/ruby-sandbox&lt;/a&gt;&lt;/p&gt;</description></item><item><title>knockを入れてスリープからの復帰画面でタイプできなくてログインできなくなる問題を回避</title><link>https://blog.piyo.tech/posts/2014-07-17-200000/</link><pubDate>Thu, 17 Jul 2014 20:00:04 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-17-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0f925b85-43dc-4b2f-b237-abde34bfc7bc/b546ec3985baeb0cb4e4fc6963e68f02/deep/0/knock-keyhole.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Mac使っててなぜかコントロールキーが押しっぱなし状態になってしまう現象がときどき見られる。なぜか、というよりはいろいろなショートカットを駆使しているうちに変なキーの組み合わせを押してしまったせいだとは思うけど。&lt;/p&gt;
&lt;p&gt;こうなってしまうと文字をタイプできなかったり、トラックパッドのタップでコンテキストメニューが出たりしてまともには使えない。一番困るのはスリープからの復帰時のパスワード入力ができずにログインできなくなってしまうことで、根本の直し方がわからない以上強制終了するしかない。&lt;/p&gt;
&lt;p&gt;本当はコントロールキー押しっぱなし状態を解消する必要があるのだけど、せめて強制終了だけはしたくないと思い、パスワードがなくてもログインはできるようにするためにiPhoneからロック解除する「knock」というアプリ入れた。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.knocktounlock.com/"&gt;Knock – unlock your Mac without a password using your iPhone&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このアプリをMacとiPhoneそれぞれに入れてペアリングや設定を済ませておくと、iPhoneをコンコン、っと2回ノックするだけでロック解除できるようになる。&lt;/p&gt;
&lt;p&gt;正直パスワード入力のほうが速いんだけど、キーをタイプできない状態であればこのアプリの機能が活きる。&lt;/p&gt;
&lt;p&gt;とりあえずknockでログインしてなんとか正規のルートで再起動をかける方向で回避しようと思う。&lt;/p&gt;
&lt;p&gt;本当は根本のControl押しっぱなし問題を解決したい…&lt;/p&gt;</description></item><item><title>Railsである時点でのモデルのスナップショットのためにpaper_trailでのバージョニングを行う</title><link>https://blog.piyo.tech/posts/2014-07-16-203000/</link><pubDate>Wed, 16 Jul 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-16-203000/</guid><description>&lt;p&gt;RailsでA、Bというモデルがあるとする。モデルAはモデルBを参照しているが、参照しているモデルBはある瞬間のスナップショットにしたいとする。つまり、モデルAが欲しいのは関連を作ったときのモデルBの情報で、それ以降に変更が加わって新しくなったものではないということだ。&lt;/p&gt;
&lt;p&gt;例として不適切かもしれないが、モデルAをお気に入りモデル、モデルBをツイートとしてみる。あるユーザーがあるツイートをお気に入りに登録すると、お気に入りモデルが新しく作られる。&lt;/p&gt;
&lt;p&gt;擬似コードはこんな感じ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;p @tweet&lt;span style="color:#f92672"&gt;.&lt;/span&gt;body &lt;span style="color:#75715e"&gt;# =&amp;gt; &amp;#34;今日は雨でした&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;@fav &lt;span style="color:#f92672"&gt;=&lt;/span&gt; @user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;favorites&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create(&lt;span style="color:#e6db74"&gt;tweet_id&lt;/span&gt;: @tweed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;id)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;@fav&lt;/code&gt;が作られた時点での&lt;code&gt;@tweet.body&lt;/code&gt;は&lt;code&gt;今日は雨でした&lt;/code&gt;というものだった。このあと&lt;code&gt;@tweet&lt;/code&gt;の投稿者が何らかの理由で元の文章を&lt;code&gt;今日は晴れでした&lt;/code&gt;に変更したとする。&lt;code&gt;@fav&lt;/code&gt;から参照できる&lt;code&gt;@fav.tweet.body&lt;/code&gt;は普通にやっていれば最新の情報である&lt;code&gt;今日は晴れでした&lt;/code&gt;となっているはずだけど、そうではなく&lt;code&gt;@fav&lt;/code&gt;を作った時点での情報、&lt;code&gt;今日は雨でした&lt;/code&gt;が欲しい。&lt;/p&gt;
&lt;p&gt;これが今回の前提。長い。&lt;/p&gt;
&lt;p&gt;このような機能を実現するためにモデルのバージョン管理を行う。ActiveRecordをバージョン管理するためのgemがいくつかあるが、Ruby Toolboxを見る限りでは&lt;code&gt;paper_trail&lt;/code&gt;がよさそうだ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.ruby-toolbox.com/categories/Active_Record_Versioning"&gt;The Ruby Toolbox - Active Record Versioning&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/airblade/paper_trail"&gt;airblade/paper_trail&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="paper_trailの導入"&gt;paper_trailの導入&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;gem 'paper_trail', '~&amp;gt; 3.0.3'&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bundle&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rails generate paper_trail:install&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rake db:migrate&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;3と4でバージョン管理用のテーブルができる。&lt;/p&gt;
&lt;p&gt;そしてバージョン管理したいモデルで&lt;code&gt;has_paper_trail&lt;/code&gt;を呼んであげればOK。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Favorite&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; has_paper_trail
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;paper_trailについて簡単に説明すると、モデルの作成時や変更時に古い情報をyaml化してpaper_trail用のテーブルに入れるという仕組みになっている。&lt;/p&gt;
&lt;h1 id="使ってみる"&gt;使ってみる&lt;/h1&gt;
&lt;p&gt;詳しくはGitHubのREADMEを読んでもらうとして、最初に書いたケースを満たすような使い方を擬似的なコードで紹介する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# user2がtweetする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;@tweet &lt;span style="color:#f92672"&gt;=&lt;/span&gt; user2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;tweets&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create(&lt;span style="color:#e6db74"&gt;body&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;今日は雨でした&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# user1がさっきのtweetをお気に入りにする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;@fav &lt;span style="color:#f92672"&gt;=&lt;/span&gt; user1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;favorites&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create(&lt;span style="color:#e6db74"&gt;tweet_id&lt;/span&gt;:@tweet&lt;span style="color:#f92672"&gt;.&lt;/span&gt;id)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# user2がさっきのtweetの文章を変更する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;@tweet&lt;span style="color:#f92672"&gt;.&lt;/span&gt;body &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;今日は晴れでした&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;@tweet&lt;span style="color:#f92672"&gt;.&lt;/span&gt;save
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Favorite&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; has_paper_trail
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; belongs_to &lt;span style="color:#e6db74"&gt;:user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; belongs_to &lt;span style="color:#e6db74"&gt;:tweet&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;saved_tweet&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; tweet&lt;span style="color:#f92672"&gt;.&lt;/span&gt;version_at(created_at)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;p @fav&lt;span style="color:#f92672"&gt;.&lt;/span&gt;saved_tweet&lt;span style="color:#f92672"&gt;.&lt;/span&gt;body &lt;span style="color:#75715e"&gt;# =&amp;gt; &amp;#34;今日は雨でした&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここでキーとなるのは&lt;code&gt;version_at&lt;/code&gt;という&lt;code&gt;paper_trail&lt;/code&gt;のメソッドで、Time系のオブジェクトを渡すとその時点のモデルを返してくれる。変更がなければ最新の物が返ってくる。これで当初の目的は果たせるようになった。&lt;/p&gt;
&lt;p&gt;別の方法としてTweetモデルをそのままコピーしたimmutableなモデルを用意するという解決策があるかもしれないが、その方法だとFavoriteの数だけimmutableモデルが作られてしまう。データの量や管理の楽さから考えてもバージョン管理のほうが望ましいと思う。&lt;/p&gt;</description></item><item><title>Windows用ランチャー＆スイッチャー Columbus</title><link>https://blog.piyo.tech/posts/2014-07-15-203000/</link><pubDate>Tue, 15 Jul 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-15-203000/</guid><description>&lt;p&gt;Macを使っているときはランチャーに&lt;a href="http://www.alfredapp.com/"&gt;Alfred&lt;/a&gt;、よく使うアプリケーションをアクティブにするのには&lt;a href="https://itunes.apple.com/jp/app/snap/id418073146?mt=12"&gt;Snap&lt;/a&gt;を使っている。&lt;/p&gt;
&lt;p&gt;Snapはこちらを参照。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-02-26-205002"&gt;ホットキーで指定したアプリを起動・アクティブにできるMacアプリSnap - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;また、Windows環境でのランチャーにはbluewindを使っている。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-06-26-203000"&gt;Windows8でランチャソフトbluewindの呼び出しキーを変更する - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;で、WindowsでもSnapのように一発で目的のアプリケーションに切り替えるためのソフトを探していたんだけど、検索してもみつかるのはAlt+Tabでのウィンドウ切替の話ばかり。ようやく見つけたのがColumbusというソフト。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.autohotkey.com/board/topic/108566-columbus-a-fast-program-launcher-and-focus-switcher/"&gt;Columbus - a fast program launcher and focus switcher - Scripts - AutoHotkey Community&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;どうやら公式サイトなどはないようなので自己判断で使ってもらう必要があるけど、使い勝手はかなり便利だった。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Ctrl+Alt+p&lt;/code&gt;でMacでいうスポットライトのようなアプリケーションランチャーがポップアップする。bluewindと違って自分で登録する必要がないのでbluewindユーザーでも使いようがあるかもしれない。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/KZtsweI-1TVZ0UN3cJ75F31EfU5_zFT46h9AtU-Fk42bjiNkKt1AvNCCPuQNqdoQD3pC41t109Ab5Hhb8bb4huGdV0LAYqGx1W8I6NB4UrPTpC1cyt6sxAekiYjQ0LWhzyKTRBfy-NwAKee_Uc_D7Hs6XyZCPK8PdpQZhfPRANBL6MHUFL55-Fo7BcSBEApqzFRCEPkvVUGV69I12GLzK95pjoSgkZ3klu_N_AQmrtg2vdDLj28p0pzgg0HyRryfTHpegqlCZLb-YZdUwraRVacqBMIMMuPt7BIopDu8m44BwDM1UxPTfWuXsfOoHpQzbMivmjx2Bd0SE4FTlkSvlF9gwCIqYGuUgK1m2fSym3KuYnvpxcS325oI_OuNG2OSt5U1eC7ZmPESijkxLLvjUrmbVUva5KsWtRzafQyTkx2EpBsc-xSNwOvZBWkxIsIM5xw3C_wjck4aysBRWuR-1cRYuxKZxeBO8AF3rj9hE12OigKmwl5BnrRjHDZnhTYyQ_8dmX4Qny3X_2U7oMlM6K0OT7PcgLOClS8J82qO-JOimAE00T3F6XKJePAiLtHlGIpE8QcnuwGT74VyMsTxl9VXWxeBoPxZqF2t67N0M_McyaZl1zu5DQefJU3Kjs_QAN13vVOFDPgt_BQm0fXl2EpBNPfPnMR5Cw=w554-h476-no" alt=""&gt;&lt;/p&gt;
&lt;p&gt;で、スイッチャーのほうだけど、こちらは&lt;code&gt;Ctrl+Alt+o&lt;/code&gt;で起動する。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/115481a9-e2d4-4f0a-aee3-d52d415e9087/85b67b2c1c377e98a6a46d915b83d562/deep/0/2014-07-14-20_53_18-New-tab.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;インクリメンタルあいまい検索で起動中のアプリケーションから絞り込んで切替ができる。先ほどの状態から&lt;code&gt;b&lt;/code&gt;とタイプしたときの様子。マッチしたものをスコアが良い順に並べてくれる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/5465e270-1234-43bb-8a46-d05a195cb652/a60c47adcc25b2c06ba441071807c120/deep/0/2014-07-14-20_54_17-%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97---Asr.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;一発で切替というわけにはいかないけれど、Alt+Tab切替よりもかなり速いのでオススメ。&lt;/p&gt;</description></item><item><title>Rails/RSpecでのテストコードとアプリケーションコードの切替 on Emacs</title><link>https://blog.piyo.tech/posts/2014-07-14-200000/</link><pubDate>Mon, 14 Jul 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-14-200000/</guid><description>&lt;p&gt;21世紀にEmacsの話。Railsの開発するときにEmacsでアプリケーションコードとテストコードを移動するのが面倒くさかったので、それを解決するelispを探して入れてみたら思いの外便利だったのでメモっておく。&lt;/p&gt;
&lt;p&gt;それがこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.emacswiki.org/emacs/RspecMode"&gt;EmacsWiki: Rspec Mode&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;パスの通ったところに置いて&lt;code&gt;require&lt;/code&gt;するだけ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;(&lt;span style="color:#a6e22e"&gt;require&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;rspec-mode&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;僕の目的だったテストコードのバッファからアプリケーションコードのバッファに移動したいときは&lt;code&gt;C-c , t&lt;/code&gt;でいける。なんでこれを入れておかなかったのかってぐらい使いやすい。便利。&lt;/p&gt;
&lt;p&gt;ついでにカーソル行のテストを実行したりバッファ中のテストを実行したりもできて結構便利だった。&lt;/p&gt;</description></item><item><title>Visual StudioのファイルをEmacsで開く</title><link>https://blog.piyo.tech/posts/2014-07-13-200000/</link><pubDate>Sun, 13 Jul 2014 20:00:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-13-200000/</guid><description>&lt;p&gt;Visual StudioのソースコードをEmacsで書きたいとき、VS2008のころなんかはVizEmacsとかいう拡張を使ってそれを実現していたけど、どうやらVS組み込みの外部ツール連携機能だけで実現できそうということがわかったのでメモしておく。&lt;/p&gt;
&lt;h1 id="emacsの準備"&gt;Emacsの準備&lt;/h1&gt;
&lt;p&gt;EmacsはNTEmacsを使っているとする。NTEmacsの&lt;code&gt;bin&lt;/code&gt;ディレクトリの中には以下のような実行ファイルが入っていて、起動するときは&lt;code&gt;runemacs.exe&lt;/code&gt;を叩いていると思う。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;emacs.exe&lt;/li&gt;
&lt;li&gt;emacsclientw.exe&lt;/li&gt;
&lt;li&gt;runemacs.exe&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;すでに起動しているEmacsで新しくファイルを開きたい場合には一緒に入っている&lt;code&gt;emacsclientw.exe&lt;/code&gt;を使う。&lt;code&gt;emacsclientw.exe&lt;/code&gt;にファイルパスを渡して実行すると、サーバーとして動いているEmacsでファイルを開いてくれる。&lt;/p&gt;
&lt;p&gt;この機能を使うにはEmacs側でサーバーを実行しておかなければならない。Emacsの設定ファイルに次の行を書いておく必要がある。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;(start-server)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="外部ツールの指定"&gt;外部ツールの指定&lt;/h1&gt;
&lt;p&gt;Visual Studioのメニューから「ツール」→「外部ツール」と進む。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/1028f944-38d5-4f35-91a8-c613fccb474a/ac4388d3a95b4dc6babc80782b117a51/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;「追加」したらタイトル、コマンドには&lt;code&gt;emacsclientw.exeのパス&lt;/code&gt;、引数に&lt;code&gt;$(ItemPath)&lt;/code&gt;を指定する。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/cb541bcb-2feb-4172-874c-40182c8365ec/81949b7575dc7ba0e14400c4d5944145/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;あとはツールメニューの「emacs」から現在開いているファイルをEmacsに送ることができるようになる。&lt;/p&gt;
&lt;h1 id="ショートカットの設定"&gt;ショートカットの設定&lt;/h1&gt;
&lt;p&gt;Emacsユーザーならツールメニューから操作するなんてことは当然できないだろうから、ショートカットを設定したほうがいい。&lt;/p&gt;
&lt;p&gt;「ツール」→「オプション」から「キーボード」を選び、「ツール.外部コマンドN」にショートカットを割り当てる。このときの番号は外部コマンドのうち何番目にあるかによるので、外部コマンド追加ダイアログで確認する必要がある。ちなみに僕はEmacsを意味するイメージで「Alt+E」に割り当てている。便利。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/cf0051c7-452e-4594-aad2-a7bcc0471861/cb5b19ebe66b47370da5cc13cdc18fbd/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88.png" alt=""&gt;&lt;/p&gt;
&lt;h1 id="参考"&gt;参考&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://code.msdn.microsoft.com/windowsdesktop/VisualStudio-tips-b12a8aa6"&gt;エディタにこだわりがある人へ、「Visual Studio のエディタとの連携」&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Railsのrenderでdefined?による分岐</title><link>https://blog.piyo.tech/posts/2014-07-12-193000/</link><pubDate>Sat, 12 Jul 2014 19:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-12-193000/</guid><description>&lt;p&gt;Railsで&lt;code&gt;render partial&lt;/code&gt;でいろいろなViewが使いまわしているViewがあるとき。ある1つのViewのときだけ見た目をちょっと変えるってことをやろうとしたときに、&lt;code&gt;defined?&lt;/code&gt;を使うと便利かもなーというお話。&lt;/p&gt;
&lt;h1 id="前提"&gt;前提&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;users/A.html.haml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;users/B.html.haml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;users/C.html.haml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;users/D.html.haml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;users/_shared.html.haml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上のようなテンプレがあって、A~Dの中身は擬似的に書くとそれぞれこんな感じになっているとする。要は&lt;code&gt;shared&lt;/code&gt;を&lt;code&gt;render&lt;/code&gt;している。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-haml" data-lang="haml"&gt;-# A~D
%h1 A~C固有のタイトル
%div A~C固有の情報
= render partial: &amp;#34;shared&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;_shared.html.haml&lt;/code&gt;の中身はこんな感じで、Dのときだけは追加の情報を出したいとする。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-haml" data-lang="haml"&gt;%h1 共有部分
%div A~Dで共有
- if Dのときだけ
%div D固有の情報
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="対処法"&gt;対処法&lt;/h1&gt;
&lt;p&gt;renderするときに引数のようなものを&lt;code&gt;locals&lt;/code&gt;によって与えられるのでそれを使うのが楽そう。というわけで、A〜CとDでその内容を変えれば分岐はうまくいきそうだ。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-haml" data-lang="haml"&gt;-# A~C
%h1 A~C固有のタイトル
%div A~C固有の情報
= render partial: &amp;#34;shared&amp;#34;, locals: { show_d: false }
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-haml" data-lang="haml"&gt;-# D
%h1 D固有のタイトル
%div D固有の情報
= render partial: &amp;#34;shared&amp;#34;, locals: { show_d: true }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上のようにshow_dとかいう変数を使ってあげれば、条件はこのように書くことができる。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-haml" data-lang="haml"&gt;- if show_d
%div D固有の情報
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="もうちょっとよくする"&gt;もうちょっとよくする&lt;/h1&gt;
&lt;p&gt;上の方法だとDだけのためにA&lt;del&gt;C側にも変更が必要になって相当鬱陶しい。A&lt;/del&gt;DのうちDだけに変更を加えて同じことを実現できるのが望ましいと思う。&lt;/p&gt;
&lt;p&gt;やり方はA~Cには&lt;code&gt;locals&lt;/code&gt;は使わず、Dは&lt;code&gt;locals:{show_d:true}&lt;/code&gt;を。そして条件分岐のほうでは&lt;code&gt;defined?&lt;/code&gt;を用いる。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-haml" data-lang="haml"&gt;- if defined? show_d
%div D固有の情報
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;こうすると、Dの場合は&lt;code&gt;show_d&lt;/code&gt;があるので実行され、A~Cの場合は&lt;code&gt;show_d&lt;/code&gt;なんて変数がないからこの条件は偽になって実行されない。renderする側の変更箇所が1箇所で済むからこっちのほうが良いと思う。&lt;/p&gt;
&lt;p&gt;でもどことなくイケてないような感じはするんだよね。もっとRailsなやり方があったら知りたい。&lt;/p&gt;</description></item><item><title>平日の計算にweekdays gemがちょっと便利</title><link>https://blog.piyo.tech/posts/2014-07-11-210000/</link><pubDate>Fri, 11 Jul 2014 21:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-11-210000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/79ae1d20-5e79-449f-9eb7-794ab28eac88/e4b43324dcbb60f74e9128910bad0e18/deep/0/coollogo_com-322164916.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Railsで営業日計算に（もしかしたら）使えるgem見つけた。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mdarby/weekdays"&gt;mdarby/weekdays&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;厳密に言うとこのgemは月曜〜金曜を計算しているだけで祝日に対応していないので、実運用するとなると拡張が必要そうだけど、ゼロから作るよりはマシじゃないかなと思う。&lt;/p&gt;
&lt;h1 id="こんな使い方"&gt;こんな使い方&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;weekdays_ago
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;weekdays_from_now
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Date&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;today&lt;span style="color:#f92672"&gt;.&lt;/span&gt;weekday?
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例えば今日（2014年7月11日）でそれぞれを実行してみると、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;weekdays_ago
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# =&amp;gt; 2014-07-04 19:32:48 +0900&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;weekdays_from_now
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# =&amp;gt; 2014-07-16 19:33:10 +0900&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Date&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;today&lt;span style="color:#f92672"&gt;.&lt;/span&gt;weekday?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とまあこんな具合。&lt;/p&gt;
&lt;p&gt;◯営業以内に△△します〜みたいなときに使えるんじゃないかと思う。祝日を外で与えられるようにすればもっと使い勝手がよさそうだから拡張してみようかなー。&lt;/p&gt;</description></item><item><title>CarrierWave使用モデルのシードデータを用意する</title><link>https://blog.piyo.tech/posts/2014-07-10-203000/</link><pubDate>Thu, 10 Jul 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-10-203000/</guid><description>&lt;p&gt;画像アップロード機能を提供するCarrierWaveというgemを使ったRailsアプリケーションのテストについて以前書いた。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-07-04-200000"&gt;RSpecでファイルアップロードのテスト - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今日は同じくCarrierWaveに関連して、アップロードする画像を持つようなモデルのシードデータをどのように作成するかという話をする。&lt;/p&gt;
&lt;h1 id="seedrb"&gt;seed.rb&lt;/h1&gt;
&lt;p&gt;Railsで初期データ作るなら&lt;code&gt;db/seeds.rb&lt;/code&gt;に色々書くと思う。ここに書いたコードはRakeタスクから呼び出せる。RailsをロードしたあとなのでRailsのモデルを直に操作する感じでデータを登録していくことができる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# db/seeds.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Product&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create(name: &lt;span style="color:#e6db74"&gt;&amp;#34;product name&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;price&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Product&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create(name: &lt;span style="color:#e6db74"&gt;&amp;#34;product2 name&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;price&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="画像はどうする"&gt;画像はどうする&lt;/h1&gt;
&lt;p&gt;ここまでは普通にモデルのアトリビュートをハッシュで与えればいいので特に考えなければいけないことはない。&lt;/p&gt;
&lt;p&gt;ところで、↑のProductモデルが画像を持っているとしたらどうだろう？&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Product&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create(name: &lt;span style="color:#e6db74"&gt;&amp;#34;product name&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;price&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;image&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;product_image.jpg&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでは実際の画像ファイルはアップロードされず、シードデータとしては意味をなさない（余談だけどテストの場合はこれでも通ってしまう。DBとしては文字列として持っているだけなので）。&lt;/p&gt;
&lt;p&gt;結論からいうと、画像ファイルのパスをopenしてそれを渡せばOK。&lt;/p&gt;
&lt;p&gt;例えば&lt;code&gt;db/fixtures&lt;/code&gt;というディレクトリを掘ってそこに画像を置いておき、&lt;code&gt;seeds.rb&lt;/code&gt;では&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Product&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; name: &lt;span style="color:#e6db74"&gt;&amp;#34;product name&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;price&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;image&lt;/span&gt;: open &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;root&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/db/fixtures/image01.jpg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;という感じにする。これで&lt;code&gt;rake db:seed&lt;/code&gt;実行するとProductが生成され、指定したアップロード先に画像が配置されていることも確認できる。&lt;/p&gt;</description></item><item><title>久しぶりに使ったのでWindows8セットアップまとめ</title><link>https://blog.piyo.tech/posts/2014-07-09-203000/</link><pubDate>Wed, 09 Jul 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-09-203000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9c88d22b-1e45-435d-a5e8-f4878813d541/eb63c98a3bfbc9f6cc651ae145209d99/deep/0/url.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;1年半ぶりに仕事でWindowsマシンを使うことになったんだけど、以前使っていたころの情報がほとんど残っていなくてセットアップにすごく時間がかかった。セットアップにも時間はかかったけど、そもそも何を入れるべきか、何があったほうがいいのかなんてことを思い出すのにすごく苦労した。&lt;/p&gt;
&lt;p&gt;そこでメモも兼ねてWindows環境のセットアップについて書き残しておこうと思う。&lt;/p&gt;
&lt;h1 id="必需品系"&gt;必需品系&lt;/h1&gt;
&lt;h2 id="visual-studio--office"&gt;Visual Studio / Office&lt;/h2&gt;
&lt;p&gt;開発に使ったりドキュメントいじりに使ったりするので。&lt;/p&gt;
&lt;h2 id="ntemacs"&gt;NTEmacs&lt;/h2&gt;
&lt;p&gt;WindowsでEmacs使うならコレ。設定ファイルなどはGit管理してある上、init-loaderで環境毎の差異を吸収するようにしているので、このバイナリさえダウンロードしてしまえばほとんど設定もなくすぐに使える。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://cha.la.coocan.jp/doc/NTEmacs.html"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://cha.la.coocan.jp/doc/NTEmacs.html" alt="NTEmacs" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://cha.la.coocan.jp/doc/NTEmacs.html"&gt;NTEmacs&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://cha.la.coocan.jp/doc/NTEmacs.html" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://cha.la.coocan.jp/doc/NTEmacs.html" alt="はてなブックマーク - NTEmacs" title="はてなブックマーク - NTEmacs" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h2 id="cygwin"&gt;Cygwin&lt;/h2&gt;
&lt;p&gt;コマンドでできることはなるべくコマンドでやりたいので。Windowsでもコマンドラインを使いたくなることが多い。なのでWindowsでは基本Cygwinを入れる。こいつが結構厄介で、フルインストールすると最後の最後に固まって失敗したりなんかして時間ばかり食う。開発ツール系だけを入れておいて、&lt;code&gt;cyg-apt&lt;/code&gt;あたりで必要に応じてインストールするのが良さそう。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.cygwin.com/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://www.cygwin.com/" alt="Cygwin" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://www.cygwin.com/"&gt;Cygwin&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/https://www.cygwin.com/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/https://www.cygwin.com/" alt="はてなブックマーク - Cygwin" title="はてなブックマーク - Cygwin" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h2 id="git"&gt;Git&lt;/h2&gt;
&lt;p&gt;上述のCygwinにもgitは付属しているが、バージョンが古いことが多い。そのためきちんと本家からインストールしておき、そちらを使うようにしている。ついでにくっついてくるGit Bashもたまには使ったりする。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://git-scm.com/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://git-scm.com/" alt="Git" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://git-scm.com/"&gt;Git&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://git-scm.com/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://git-scm.com/" alt="はてなブックマーク - Git" title="はてなブックマーク - Git" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h1 id="ないと死ぬ系"&gt;ないと死ぬ系&lt;/h1&gt;
&lt;h2 id="どこでもemacs風キーバインド"&gt;どこでもemacs風キーバインド&lt;/h2&gt;
&lt;p&gt;Macだとカーソル移動系のキーバインドはOS標準でEmacsライクで助かっているけど、Windowsではそれが使えないということで死ぬほどストレスになる。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://xkeymacs.sourceforge.jp/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://xkeymacs.sourceforge.jp/" alt="XKeymacs" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://xkeymacs.sourceforge.jp/"&gt;XKeymacs&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://xkeymacs.sourceforge.jp/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://xkeymacs.sourceforge.jp/" alt="はてなブックマーク - XKeymacs" title="はてなブックマーク - XKeymacs" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h2 id="yamy"&gt;yamy&lt;/h2&gt;
&lt;p&gt;これは以前書いたもの。US配列のMacを使っているので日本語キーボードは使えません。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-06-23-215707"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-06-23-215707" alt="日本語キーボードのWindowsでUS配列を使う方法 - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-06-23-215707"&gt;日本語キーボードのWindowsでUS配列を使う方法 - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h2 id="bluewind"&gt;bluewind&lt;/h2&gt;
&lt;p&gt;コマンド型ランチャー。そろそろ使い始めてから8年ぐらい。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.web-ghost.net/bluewind/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://www.web-ghost.net/bluewind/" alt="bluewind＆単機能ツール集 再配布所" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://www.web-ghost.net/bluewind/"&gt;bluewind＆単機能ツール集 再配布所&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://www.web-ghost.net/bluewind/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://www.web-ghost.net/bluewind/" alt="はてなブックマーク - bluewind＆単機能ツール集 再配布所" title="はてなブックマーク - bluewind＆単機能ツール集 再配布所" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h2 id="tmux"&gt;tmux&lt;/h2&gt;
&lt;p&gt;ターミナルマルチプレクサーというジャンルのソフトウェア。セッションへのアタッチ、デタッチなどサーバーにログインしてあれこれする人に特に便利らしいけど、僕は端末の画面を分割したいがために使用する。&lt;/p&gt;
&lt;p&gt;最新のCygwinにはバンドルされているのですぐに使えると思いきや、ちょっとしたハックが必要だった。&lt;code&gt;/tmp/tmux-1001&lt;/code&gt;といったような名前のディレクトリが残っているせいで&lt;code&gt;failed to connect to server: No error&lt;/code&gt;というエラーでtmuxを起動できないという問題があって、この一時ディレクトリを削除しないといけないらしかった。&lt;/p&gt;
&lt;p&gt;調べているとこのようなスレッドを見つけたので見てみると、別に削除してしまえばいいらしい。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://superuser.com/questions/760503/cygwin-tmux-failed-to-connect-to-server-no-error"&gt;“failed to connect to server: No error”&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そういうわけで、僕はシンプルにエイリアスを使って起動前に必ず削除するようにしたら動くようになった。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;alias tmux=&amp;#39;rm -rf /tmp/tmux* &amp;amp;&amp;amp; tmux&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://tmux.sourceforge.net/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://tmux.sourceforge.net/" alt="tmux" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://tmux.sourceforge.net/"&gt;tmux&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://tmux.sourceforge.net/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://tmux.sourceforge.net/" alt="はてなブックマーク - tmux" title="はてなブックマーク - tmux" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h1 id="便利系"&gt;便利系&lt;/h1&gt;
&lt;h2 id="clover"&gt;Clover&lt;/h2&gt;
&lt;p&gt;Chrome風タブ型ファイラー&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ejie.me/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://ejie.me/" alt="Clover Brings Chrome-Style Tabs to Windows Explorer. | 易捷科技 EJIE Technology" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://ejie.me/"&gt;Clover Brings Chrome-Style Tabs to Windows Explorer. | 易捷科技 EJIE Technology&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://ejie.me/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://ejie.me/" alt="はてなブックマーク - Clover Brings Chrome-Style Tabs to Windows Explorer. | 易捷科技 EJIE Technology" title="はてなブックマーク - Clover Brings Chrome-Style Tabs to Windows Explorer. | 易捷科技 EJIE Technology" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h2 id="everything"&gt;Everything&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.voidtools.com/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://www.voidtools.com/" alt="Everything Search Engine" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://www.voidtools.com/"&gt;Everything Search Engine&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://www.voidtools.com/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://www.voidtools.com/" alt="はてなブックマーク - Everything Search Engine" title="はてなブックマーク - Everything Search Engine" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h2 id="hardlinkshellextension"&gt;HardLinkShellExtension&lt;/h2&gt;
&lt;p&gt;Windowsでも実はハードリンクとかシンボリックリンクができるんだけど、コマンドプロンプトを使わなければいけない。この拡張を入れるとエクスプローラーの右ドラッグとかでリンクを作成できるので使い勝手がよい。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://schinagl.priv.at/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://schinagl.priv.at/" alt="Gerhild's &amp; Hermann's Site" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://schinagl.priv.at/"&gt;Gerhild&amp;rsquo;s &amp;amp; Hermann&amp;rsquo;s Site&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://schinagl.priv.at/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://schinagl.priv.at/" alt="はてなブックマーク - Gerhild's &amp; Hermann's Site" title="はてなブックマーク - Gerhild's &amp; Hermann's Site" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h1 id="別になんでもいいんだけどこれ使ってるよ系"&gt;別になんでもいいんだけどこれ使ってるよ系&lt;/h1&gt;
&lt;h2 id="さくらエディタ"&gt;さくらエディタ&lt;/h2&gt;
&lt;p&gt;ちょっとしたファイル編集のときに使うためのエディタ。なんとなくしっくりくるのでこれをずっと使っている。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sakura-editor.sourceforge.net/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://sakura-editor.sourceforge.net/" alt="サクラエディタ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://sakura-editor.sourceforge.net/"&gt;サクラエディタ&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://sakura-editor.sourceforge.net/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://sakura-editor.sourceforge.net/" alt="はてなブックマーク - サクラエディタ" title="はてなブックマーク - サクラエディタ" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h2 id="7zip"&gt;7zip&lt;/h2&gt;
&lt;p&gt;圧縮・展開用。7zとかにも対応していて良い。エクスプローラーのコンテキストメニューから使いやすくて重宝している。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sevenzip.sourceforge.jp/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://sevenzip.sourceforge.jp/" alt="圧縮・解凍ソフト 7-Zip" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://sevenzip.sourceforge.jp/"&gt;圧縮・解凍ソフト 7-Zip&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://sevenzip.sourceforge.jp/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://sevenzip.sourceforge.jp/" alt="はてなブックマーク - 圧縮・解凍ソフト 7-Zip" title="はてなブックマーク - 圧縮・解凍ソフト 7-Zip" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h1 id="設定系"&gt;設定系&lt;/h1&gt;
&lt;h2 id="環境変数home"&gt;環境変数HOME&lt;/h2&gt;
&lt;p&gt;cygwinやEmacsのために環境変数HOMEを設定しておく。&lt;/p&gt;
&lt;h2 id="キーリピート"&gt;キーリピート&lt;/h2&gt;
&lt;p&gt;コントロールパネルのキーボードからキーリピートを短くする。これをしておかないと、xkeymacsでの多めのカーソル移動がだるい。&lt;/p&gt;
&lt;h2 id="起動タスク"&gt;起動タスク&lt;/h2&gt;
&lt;p&gt;タスクスケジューラのログイン時に実行する機能を使って、UACを回避したい常駐型ソフトを管理者権限で自動起動するタスクを作る。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;yamy&lt;/li&gt;
&lt;li&gt;Everything&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;あたりが該当。&lt;/p&gt;</description></item><item><title>t.string urlってやっちゃう</title><link>https://blog.piyo.tech/posts/2014-07-08-200000/</link><pubDate>Tue, 08 Jul 2014 20:00:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-08-200000/</guid><description>&lt;p&gt;URLを入れておきたいカラムなのにRailsのマイグレーションで&lt;code&gt;t.string :url&lt;/code&gt;って書いてvarchar(255)にしちゃって、実際の運用で日本語URLがエンコードされて渡ってきて余裕でオーバーするっていうのはあるあるじゃないですか？それとも初心者あるある？&lt;/p&gt;
&lt;p&gt;URLに文字数制限ってのは確か存在しなくて、IEかなんかでは2083文字までは大丈夫などアプリケーションによって異なるらしい。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://support.microsoft.com/kb/208427/ja"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://support.microsoft.com/kb/208427/ja" alt="Internet Explorer では URL に最大 2,083 文字が使用可能" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://support.microsoft.com/kb/208427/ja"&gt;Internet Explorer では URL に最大 2,083 文字が使用可能&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://support.microsoft.com/kb/208427/ja" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://support.microsoft.com/kb/208427/ja" alt="はてなブックマーク - Internet Explorer では URL に最大 2,083 文字が使用可能" title="はてなブックマーク - Internet Explorer では URL に最大 2,083 文字が使用可能" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;で、僕はこのミスをRSSリーダーのときにやった。RSSフィードを解析すると各記事のタイトルやらURLが取れるんだけど、そのURLの保存先をvarchar(255)にしていてINSERTできないって問題に当たってしまった。&lt;/p&gt;
&lt;p&gt;これを何も考えずに解決するだけであれば簡単で、Railsであれば、&lt;code&gt;t.string :url&lt;/code&gt;を&lt;code&gt;t.text :url&lt;/code&gt;などにしてしまえばOK。文字制限なくなるし。&lt;/p&gt;
&lt;p&gt;あとは&lt;code&gt;t.string :url, limit: 1024&lt;/code&gt;みたいにlimit使うってのもありだけど、なんかうまくいかないこともあったような。&lt;/p&gt;
&lt;p&gt;ついでに話しておくと、MySQLのデフォルトでは768バイト以上の文字列にインデックスを付けることができない。なのでvarchar(256)以上の文字列はインデックスを付けられないようだ。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://d.hatena.ne.jp/tanamon/20090930/1254332746"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://d.hatena.ne.jp/tanamon/20090930/1254332746" alt="MySQLのUNIQUEなINDEXには長さ767byteまでしか使えない件と対策 - tanamonの日記" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://d.hatena.ne.jp/tanamon/20090930/1254332746"&gt;MySQLのUNIQUEなINDEXには長さ767byteまでしか使えない件と対策 - tanamonの日記&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/tanamon/20090930/1254332746" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/tanamon/20090930/1254332746" alt="はてなブックマーク - MySQLのUNIQUEなINDEXには長さ767byteまでしか使えない件と対策 - tanamonの日記" title="はてなブックマーク - MySQLのUNIQUEなINDEXには長さ767byteまでしか使えない件と対策 - tanamonの日記" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;このページの解決策には掲載されていないが、MySQL5.5系だと&lt;code&gt;innodb_large_prefix&lt;/code&gt;というオプションを有効にした上で、ROW_FORMATをDynamicやCompressedに変更したテーブルでのみ3072バイトまで使えるようになる。これを使うとvarchar(1024)とかでもインデックスを付けられるようになってしまう！&lt;/p&gt;
&lt;p&gt;ちなみにこれをRailsのマイグレーションにするにはSQLを直接実行するしかなさそう。こういう風にかいた。&lt;code&gt;change&lt;/code&gt;ではなく、従来型の&lt;code&gt;up&lt;/code&gt;、&lt;code&gt;down&lt;/code&gt;を用いてロールバックもできるように書いている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ChangeRowFormat&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Migration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;up&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; execute &lt;span style="color:#e6db74"&gt;&amp;#39;ALTER TABLE feeds ROW_FORMAT=Dynamic&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;down&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; execute &lt;span style="color:#e6db74"&gt;&amp;#39;ALTER TABLE feeds ROW_FORMAT=Compact&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Railsでマイグレーションを介さずにサーバーでDBを変更してしまったとき</title><link>https://blog.piyo.tech/posts/2014-07-07-203000/</link><pubDate>Mon, 07 Jul 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-07-203000/</guid><description>&lt;p&gt;本番環境で動いているRailsアプリケーションのDBにおいて、問題に緊急対応するために直接&lt;code&gt;ALTER_TABLE&lt;/code&gt;してしまったようなとき、Railsアプリケーション側ではどんな対応をすればいいか、というお話。&lt;/p&gt;
&lt;p&gt;レアケースかもしれないし意外とあるかもしれない。&lt;/p&gt;
&lt;p&gt;僕は実際に1年ほど前に開発していたRSSリーダーのときに経験したことがある。ある日の夜中、サービスにアクセスが集中してデータベースのレスポンスがめちゃくちゃ悪くなったとき、僕は普通に寝ていた。いや、それまでの対応で力尽きていたと言っていい。&lt;/p&gt;
&lt;p&gt;サーバーがうんともすんとも言わないそんな状況の中、ヘルプで入ってくれている人がスキーマを調べてインデックスが足りない（！）ということに気がついたらしい。翌朝起きてみると「とりあえず直接インデックス追加してなんとかしました」という連絡が来ていた。&lt;/p&gt;
&lt;p&gt;インデックス足りないとか！しょぼすぎるミスなのはさておいてひとまず問題は解決した。あれ？でも直接DBいじっちゃったらRails側のマイグレーションと整合性とれないぞ？&lt;/p&gt;
&lt;p&gt;そういうときの対処法です。&lt;/p&gt;
&lt;h1 id="そもそもマイグレーションとは"&gt;そもそもマイグレーションとは？&lt;/h1&gt;
&lt;p&gt;そもそも&lt;code&gt;rake db:migrate&lt;/code&gt;は何をやっているのかというと、&lt;code&gt;db/migrate&lt;/code&gt;以下にあるファイルに書いてあるDBに対する変更処理をファイルの日付順に実施していくというものだ。このとき、DBの&lt;code&gt;schema_migrations&lt;/code&gt;というテーブルにこれまでに適用したマイグレーションの番号（日付の文字列）を持っている。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rake db:migrate&lt;/code&gt;ではこのテーブルを見に行って未適用のマイグレーションを実行するような感じになっている。その都度&lt;code&gt;schema_migrations&lt;/code&gt;は更新される。&lt;/p&gt;
&lt;h1 id="具体的な対応方法"&gt;具体的な対応方法&lt;/h1&gt;
&lt;h2 id="railsアプリケーション側"&gt;Railsアプリケーション側&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;% rails generate migration AddIndexToHoge&lt;/code&gt; みたいなコマンドで新しいマイグレーションを生成する。そして、手作業で変更してしまった処理に相当する処理をマイグレーションファイルには書いておく。&lt;/p&gt;
&lt;p&gt;例えば僕の経験したケースでは、プロダクションのデータベースでインデックスの追加を行った。そういうときはこのような感じのマイグレーションを書く。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AddIndexToHoge&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Migration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;change&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; add_index &lt;span style="color:#e6db74"&gt;:hoges&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:fuga&lt;/span&gt;, name&lt;span style="color:#e6db74"&gt;:&amp;#39;idx_hoge_name&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt;を敢えて指定しているのはプロダクションDBで行った変更で追加したインデックスの名前がRailsのデフォルトとは異なっていたから。&lt;/p&gt;
&lt;p&gt;さて、これでRailsアプリケーション側での準備は整った。&lt;/p&gt;
&lt;h2 id="プロダクションdb側"&gt;プロダクションDB側&lt;/h2&gt;
&lt;p&gt;先ほど作ったマイグレーションの内容はすでに手動で適用済みであるため、もう一度マイグレーションが走るとエラーになってしまう。そこで先程作ったマイグレーションの番号を&lt;code&gt;schema_migrations&lt;/code&gt;に手動で追加してやる。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;gt; INSERT INTO schema_migrations (version) VALUES(20131031113857);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これであたかも&lt;code&gt;rake db:migrate&lt;/code&gt;でマイグレーションを適用したような結果にできる。&lt;/p&gt;
&lt;p&gt;一応これらの対策で、プロダクションDBに対して手動で変更を行ってしまったとしてもRailsアプリケーションの流れに戻せるということになる。&lt;/p&gt;</description></item><item><title>Railsでbootstrap3のgem入れてアイコンフォントが使えないとき</title><link>https://blog.piyo.tech/posts/2014-07-06-203000/</link><pubDate>Sun, 06 Jul 2014 20:30:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-06-203000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/59821fd4-dd33-4a60-88d4-386688f9957b/b67f9b60864f6d7aefdd4b4dfef71e1b/deep/0/bootstrap.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Railsでbootstrap使うときはgemを使ってやっちゃうと楽なんだけど、そもそもそういうgemが多すぎてわけわからないということがある。とりあえず僕はこれを使っている。READMEが短かったから。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/benjamincanac/bootstrap3-rails"&gt;benjamincanac/bootstrap3-rails&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;使い方はREADMEにある通り&lt;code&gt;application.js&lt;/code&gt;と&lt;code&gt;application.css&lt;/code&gt;に&lt;code&gt;require&lt;/code&gt;文を加えればいいだけなのでややこしいことはなにもない。&lt;/p&gt;
&lt;p&gt;ところで毎回bootstrapでつまづくこととしてアイコンフォントが表示されないっていう問題がある。特にRailsだとAsset Pipelineとかが絡んできてややこしい。このgemを使うようになってからも同じことを2回も調べたからここにメモしておくことにする。&lt;/p&gt;
&lt;p&gt;まず、fontファイルをアプリケーションディレクトリ以下に置いてしまうことにする。bundle installした先にも置いてあるが、ここから持ってくるのも1つの手。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/benjamincanac/bootstrap3-rails/tree/master/vendor/assets/fonts"&gt;https://github.com/benjamincanac/bootstrap3-rails/tree/master/vendor/assets/fonts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここにある4つのファイルを&lt;code&gt;vendor/assets/fonts/&lt;/code&gt;ディレクトリ以下に配置する。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;glyphicons-halflings-regular.eot&lt;/li&gt;
&lt;li&gt;glyphicons-halflings-regular.svg&lt;/li&gt;
&lt;li&gt;glyphicons-halflings-regular.ttf&lt;/li&gt;
&lt;li&gt;glyphicons-halflings-regular.woff&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そしてAssets Pipelineのパスに先ほどのディレクトリを追加してやることにする。&lt;code&gt;config/application.rb&lt;/code&gt;に以下の一行を追加すればよい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# config/application.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;assets&lt;span style="color:#f92672"&gt;.&lt;/span&gt;paths &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/vendor/assets/fonts&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでアイコンフォントが表示できるようになったはず。&lt;/p&gt;</description></item><item><title>マークダウンに見出し番号をつけるRuby Gem書いた</title><link>https://blog.piyo.tech/posts/2014-07-06-193000/</link><pubDate>Sat, 05 Jul 2014 10:31:07 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-06-193000/</guid><description>&lt;p&gt;マークダウンでメモを書いたりブログを書いたりしていたけど、kobito-cliでPDF化すると見た目もなかなか良いということもあって、そこそこしっかりしたドキュメントもKobitoでマークダウンするのが最近自分の中での流行りになってきた。&lt;/p&gt;
&lt;p&gt;ただそこそこ量がある報告書っぽい文書となると見出し番号があったほうがわかりやすいというのが正直なところ。見出し番号はマークダウン自身の仕様ではカバーされていない（はず）なので、マークダウンを使うのであれば別の方法と組み合わせる必要がある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pandoc&lt;/li&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;li&gt;手動で番号をつける&lt;/li&gt;
&lt;li&gt;自動で番号をつける&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;pandocを使っていたこともあったが、使い勝手がそんなに良くない（お手軽じゃない）し、見た目もいまいちになりがちなのでトータルでKobitoに劣る。&lt;/p&gt;
&lt;p&gt;CSSを使うという手は十分にありえる。kobito-cliからブラウザで開いたときに指定されているCSSに追記するなり差し替えるなりして、見出しに番号を振るようにするのは有り。&lt;/p&gt;
&lt;p&gt;手動/自動で番号をつける、というのは、&lt;code&gt;## ◯◯について&lt;/code&gt;となっているところを&lt;code&gt;## 2.1 ◯◯について&lt;/code&gt;などと数字を直接書いてしまう方法だけど、手動でこれをやるのはかなり辛いため現実的ではない。&lt;/p&gt;
&lt;p&gt;今回は以上の4種類の方法の中から自動で番号を振るという方法を取ることにしてみた。もっといい方法があったら知りたい。&lt;/p&gt;
&lt;h1 id="gem"&gt;Gem&lt;/h1&gt;
&lt;p&gt;そのライブラリをRubyで書いてGemとして配布するようにした。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://rubygems.org/gems/markdown_section_numbering"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://rubygems.org/gems/markdown_section_numbering" alt="markdown_section_numbering | RubyGems.org | your community gem host" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://rubygems.org/gems/markdown_section_numbering"&gt;markdown_section_numbering | RubyGems.org | your community gem host&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;ちなみにGitHubはこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/markdown_section_numbering"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://github.com/pi-chan/markdown_section_numbering" alt="xoyip/markdown_section_numbering" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://github.com/pi-chan/markdown_section_numbering"&gt;xoyip/markdown_section_numbering&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h1 id="使い方"&gt;使い方&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;% gem install markdown_section_numbering&lt;/code&gt;でインストールできる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;markdown_section_numbering&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;markdown &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;lt;&amp;lt;MD
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;foo bar
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## c&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; list
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; list
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; list
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;MD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;puts &lt;span style="color:#66d9ef"&gt;MarkdownSectionNumbering&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;convert(markdown)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコードを実行すると、↓のように変換されたマークダウンが得られる。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# 1 a
## 1.1 b
foo bar
## 1.2 c
- list
- list
- list
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;見出し番号の付け直しにも対応していて、すでに見出し番号がついているこのようなマークダウンを渡すと、&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# foo
# 1 a
## 1.1 b
## bar
## 1.2 c
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;新しい見出し番号が付いたマークダウンが返ってくるようになっている。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# 1 foo
# 2 a
## 2.1 b
## 2.2 bar
## 2.3 c
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これによって編集中でもとりあえずの見出し番号をつけて見やすくできるし、変更があれば再び見出し番号を付け直せばいいだけだから割と使い勝手も悪くないんじゃないかと個人的には思っている。&lt;/p&gt;
&lt;h1 id="現実的な使い方"&gt;現実的な使い方&lt;/h1&gt;
&lt;p&gt;ライブラリ化をしたはいいが、毎回コマンドを叩くというもの現実的ではない。そんな面倒なプロセスであれば使わなくなってしまう。僕の場合はAutomatorで作ったサービスと連携して、ショートカット一発で呼び出せるようにしていて、流れとしてはこんな感じになっている。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;マークダウンの文書を全選択&lt;/li&gt;
&lt;li&gt;指定したショートカットキーでサービス起動&lt;/li&gt;
&lt;li&gt;選択中の文字列が結果で置き換わる&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="スクリプトを書く"&gt;スクリプトを書く&lt;/h2&gt;
&lt;p&gt;Automatorからこのライブラリを呼び出すためのスクリプトを書いておく。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;markdown_section_numbering&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;input &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $stdin&lt;span style="color:#f92672"&gt;.&lt;/span&gt;read
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;puts &lt;span style="color:#66d9ef"&gt;MarkdownSectionNumbering&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;convert(input)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;標準出力を受け取ってライブラリに渡し、結果を出力するだけのコード。&lt;/p&gt;
&lt;h2 id="サービスを作る"&gt;サービスを作る&lt;/h2&gt;
&lt;p&gt;Automator.appを起動し、サービスを作る。&lt;/p&gt;
&lt;p&gt;左側のアクション一覧のライブラリ→ユーティリティから「シェルスクリプトを実行」を右側にドラッグ&amp;amp;ドロップする。そしてシェルスクリプトのところにさっき作ったスクリプトを呼び出すように書いてあげればよい。&lt;/p&gt;
&lt;p&gt;他の設定も含めると最終的にはこのような感じになる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/4c58d216-f8e3-449d-9451-8ff4e9790250/5700152399b586a7c9882a0db2e8e3c6/deep/0/%E7%95%AA%E5%8F%B7%E4%BB%98%E3%81%8D%E3%83%9E%E3%83%BC%E3%82%AF%E3%82%BF%E3%82%99%E3%82%A6%E3%83%B3.workflow-%E3%81%A8--markdown-numbering.rb--@-mestalla.local----24.3.1.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;これで保存して終了すればOK。&lt;/p&gt;
&lt;p&gt;テキストを選択した状態でメニューバーからサービスを起動すると、選択中のマークダウンを見出し番号つきのものに変換した上で元のテキストを置き換えてくれるというわけだ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0cb01756-3fb4-40da-8974-de2bd4e89440/79e5305301c66ba7552857877ca4d761/deep/0/%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="ショートカットをアサインする"&gt;ショートカットをアサインする&lt;/h2&gt;
&lt;p&gt;システム環境設定→キーボード→ショートカットからサービスにショートカットを割り当てることができるようになる。メニューから選ぶよりかは楽になる。&lt;/p&gt;
&lt;p&gt;Gemを書いたお話と、Automatorで便利に使う方法を紹介しました。&lt;/p&gt;</description></item><item><title>RSpecでファイルアップロードのテスト</title><link>https://blog.piyo.tech/posts/2014-07-04-200000/</link><pubDate>Fri, 04 Jul 2014 20:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-04-200000/</guid><description>&lt;p&gt;これを参考にしてCarrierWaveを使った画像アップロード機能を実装してみた。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.workabroad.jp/tech/1118"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://www.workabroad.jp/tech/1118" alt="Rails 超お手軽な画像アップローダー CarrierWave の使い方 | Workabroad.jp" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://www.workabroad.jp/tech/1118"&gt;Rails 超お手軽な画像アップローダー CarrierWave の使い方 | Workabroad.jp&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://www.workabroad.jp/tech/1118" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://www.workabroad.jp/tech/1118" alt="はてなブックマーク - Rails 超お手軽な画像アップローダー CarrierWave の使い方 | Workabroad.jp" title="はてなブックマーク - Rails 超お手軽な画像アップローダー CarrierWave の使い方 | Workabroad.jp" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;↑のサイトではCapybaraを使ったインテグレーションテストの書き方は載っているけど、コントローラのテスト方法が載っていなかったのでちょっとだけ詰まった。&lt;/p&gt;
&lt;p&gt;言い換えると、今回はファイルを添付してアップロードするフォームのテストを書くというのと同義。&lt;/p&gt;
&lt;h1 id="サンプル"&gt;サンプル&lt;/h1&gt;
&lt;h2 id="フォーム"&gt;フォーム&lt;/h2&gt;
&lt;p&gt;Userモデルには名前とプロフィール画像があって、更新フォームで名前とか画像をセットできることにする。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-haml" data-lang="haml"&gt;= form_for(@user, html:{ method: :put, role: &amp;#34;form&amp;#34; }) do |f|
.form-group
= f.label :image, &amp;#34;プロフィール画像&amp;#34;
= f.file_field :image, class:&amp;#34;form-control&amp;#34;
.form-group
= f.label :name, &amp;#34;名前&amp;#34;
= f.text_field :name, :autofocus =&amp;gt; true, class:&amp;#34;form-control&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;こんなフォーム。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/95711f83-7338-417d-8156-09777acebbf0/4c011f8a336784686c92fd1275aa1034/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-03-12-06.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="コントローラ"&gt;コントローラ&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UsersController&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ApplicationController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;edit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;update&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; @user &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;User&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find(params&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:id&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; @user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;update(user_params)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; redirect_to edit_user_url(@user)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; render &lt;span style="color:#e6db74"&gt;:edit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;user_params&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; params&lt;span style="color:#f92672"&gt;.&lt;/span&gt;require(&lt;span style="color:#e6db74"&gt;:user&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;permit(&lt;span style="color:#e6db74"&gt;:name&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:image&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;updateメソッドがあって、&lt;code&gt;name&lt;/code&gt;と&lt;code&gt;image&lt;/code&gt;を更新できるように&lt;code&gt;permit&lt;/code&gt;している。&lt;/p&gt;
&lt;h2 id="テスト要画像の用意"&gt;テスト要画像の用意&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;#{Rails.root}/spec/fixtures&lt;/code&gt;にテスト要のファイルを配置する。今回は画像ファイルなので、適当なファイルを&lt;code&gt;sample.png&lt;/code&gt;という名前で置いておくことにした。&lt;/p&gt;
&lt;h2 id="コントローラのテスト"&gt;コントローラのテスト&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;RSpec&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;describe &lt;span style="color:#66d9ef"&gt;UsersController&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:type&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;:controller&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; describe &lt;span style="color:#e6db74"&gt;&amp;#34;PUT update&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; before &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# テストユーザーでログインしておく&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; @user &lt;span style="color:#f92672"&gt;=&lt;/span&gt; login_user
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 先ほどのファイル&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; @file &lt;span style="color:#f92672"&gt;=&lt;/span&gt; fixture_file_upload(&lt;span style="color:#e6db74"&gt;&amp;#34;sample.png&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;image/png&amp;#34;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; it &lt;span style="color:#e6db74"&gt;&amp;#34;アップロードが正常に終わり、@user.image?がtrueを返す&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; put &lt;span style="color:#e6db74"&gt;&amp;#39;update&amp;#39;&lt;/span&gt;, id: @user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;id, &lt;span style="color:#e6db74"&gt;user&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; id: @user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;id, name: &lt;span style="color:#e6db74"&gt;&amp;#34;あたらしいなまえ&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;image&lt;/span&gt;: @file
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; expect(@user)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to be_image
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;fixture_file_upload&lt;/code&gt;で&lt;code&gt;fixtures&lt;/code&gt;ディレクトリに置いたファイルをロードできる。そして、コントローラの&lt;code&gt;update&lt;/code&gt;へのPUTリクエストをファイルを含めて呼び出すことでアップロードの完了を確認している。&lt;/p&gt;
&lt;p&gt;最後のこの部分&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;expect(@user)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to be_image
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;が直感的ではないけど、RSpecのルールに従って書くとそうなるというだけで、↓のように書いても問題はない。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;expect(@user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;image?)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to eq(&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="fixture_file_upload"&gt;fixture_file_upload&lt;/h2&gt;
&lt;p&gt;ちなみに&lt;code&gt;fixture_file_upload&lt;/code&gt;っていうメソッドは&lt;code&gt;ActionPack&lt;/code&gt;の中で定義されていて、見たところファイルアップロードのテストに使う&lt;code&gt;Rack::Test::UploadedFile&lt;/code&gt;を少し便利に使うために見える。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# actionpack-4.1.0/lib/action_dispatch/testing/test_process.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;module&lt;/span&gt; ActionDispatch
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;module&lt;/span&gt; TestProcess
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fixture_file_upload&lt;/span&gt;(path, mime_type &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;, binary &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;class&lt;span style="color:#f92672"&gt;.&lt;/span&gt;respond_to?(&lt;span style="color:#e6db74"&gt;:fixture_path&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;class&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fixture_path
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;class&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fixture_path, path)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Rack&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Test&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;UploadedFile&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(path, mime_type, binary)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Deviseで生成したユーザーの更新フォームに自前のフィールドを追加する</title><link>https://blog.piyo.tech/posts/2014-07-03-203000/</link><pubDate>Thu, 03 Jul 2014 20:30:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-03-203000/</guid><description>&lt;p&gt;Rails4+Deviseの話。Deviseでユーザーを作るとデフォルトでユーザー情報更新フォームがついてくる。これはbootstrapでスタイル付けしてあるものだけど、基本はこんな感じになる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/455c845e-4317-4db3-b820-5abbb8b0e5a8/6b5152606ca677e35124221da8fd0364/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-07-01-12-49.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;このUserモデルに対して別のフィールドをいくつか追加した上で、同じフォームで更新可能にするにはどうしたらいいのか、というのが今日のテーマ。&lt;/p&gt;
&lt;p&gt;例えば名前とか、表示名とか、住所とか、そういう情報がアプリケーションに依っては必要になってくると思う。&lt;/p&gt;
&lt;p&gt;今回はnameというカラムをUserに持たせることにする。なお、&lt;code&gt;add_column :users, :name, :string&lt;/code&gt;みたいなマイグレーションは既に済んでいるとする。&lt;/p&gt;
&lt;h1 id="deviseのカスタムviewを用意する"&gt;DeviseのカスタムViewを用意する&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% rails generate devise:views
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドによってアプリケーションディレクトリ内にdevise用のビューが生成される。ちなみに先ほどのスクリーンショットは生成したビューを日本語化したもの。&lt;/p&gt;
&lt;p&gt;これをやっておくことでDeviseのコントローラが表示に使うビューを自由に変更できる。&lt;/p&gt;
&lt;h1 id="registrationsedithtmlhamlを編集する"&gt;registrations/edit.html.hamlを編集する&lt;/h1&gt;
&lt;p&gt;erbの人は随時読み替えてもらえばOK。&lt;code&gt;app/views/devise/registrations/edit.html.haml&lt;/code&gt;に&lt;code&gt;name&lt;/code&gt;用のフィールドを追加する。&lt;/p&gt;
&lt;p&gt;例えばこんな感じで3行ほど追加する。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-haml" data-lang="haml"&gt; %h2
アカウント情報更新
= form_for(resource, :as =&amp;gt; resource_name, :url =&amp;gt; registration_path(resource_name), :html =&amp;gt; { :method =&amp;gt; :put, role:&amp;#34;form&amp;#34; }) do |f|
= devise_error_messages!
-# この3行を追加 ##################################################
.form-group
= f.label :name, &amp;#34;名前&amp;#34;
= f.text_field :name, :autofocus =&amp;gt; true, class:&amp;#34;form-control&amp;#34;
-# ##############################################################
.form-group
= f.label :email, &amp;#34;Eメール&amp;#34;
= f.email_field :email, class:&amp;#34;form-control&amp;#34;
- if devise_mapping.confirmable? &amp;amp;&amp;amp; resource.pending_reconfirmation?
.form-control
Currently waiting confirmation for: #{resource.unconfirmed_email}
.form-group
= f.label :password, &amp;#34;パスワード&amp;#34;
%i (パスワードを変更しない場合は空欄のままにしてください)
= f.password_field :password, :autocomplete =&amp;gt; &amp;#34;off&amp;#34;, class:&amp;#34;form-control&amp;#34;
.form-group
= f.label :password_confirmation, &amp;#34;パスワード（再入力）&amp;#34;
= f.password_field :password_confirmation, class:&amp;#34;form-control&amp;#34;
.form-group
= f.label :current_password, &amp;#34;現在のパスワード&amp;#34;
%i (更新するために現在のパスワードが必要です。)
= f.password_field :current_password, class:&amp;#34;form-control&amp;#34;
.form-group
= f.submit &amp;#34;更新&amp;#34;, class:&amp;#34;btn btn-primary&amp;#34;
%h3 退会
%p
退会してユーザー情報を削除しますか？ #{button_to &amp;#34;退会する&amp;#34;, registration_path(resource_name), :data =&amp;gt; { :confirm =&amp;gt; &amp;#34;よろしいですか？&amp;#34; }, :method =&amp;gt; :delete, class:&amp;#34;btn btn-danger&amp;#34;}
= link_to &amp;#34;戻る&amp;#34;, :back
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;さあこれでフォームができたからもう動くだろうと思ってみると実際にはそうはいかない。Rails4から導入されているStrong Parametersの概念により、許可されていない&lt;code&gt;name&lt;/code&gt;を更新できないというエラーが発生してしまうからだ。&lt;/p&gt;
&lt;h1 id="devise用のコントローラを作る"&gt;Devise用のコントローラを作る&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;name&lt;/code&gt;の更新を許可するため、Deviseのコントローラを継承したものを用意する必要がある。このコントローラでは、更新のための&lt;code&gt;update&lt;/code&gt;アクションでのみ&lt;code&gt;name&lt;/code&gt;パラメータを追加で&lt;code&gt;permit&lt;/code&gt;するという処理を行い、それ以外はベースクラスである&lt;code&gt;Devise::RegistrationsController&lt;/code&gt;でDevise従来の処理を行う。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# app/controllers/users/registrations_constroller.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Users&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;RegistrationsController&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Devise&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;RegistrationsController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; before_action &lt;span style="color:#e6db74"&gt;:configure_permitted_parameters&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;only&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:update&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;configure_permitted_parameters&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; devise_parameter_sanitizer&lt;span style="color:#f92672"&gt;.&lt;/span&gt;for(&lt;span style="color:#e6db74"&gt;:account_update&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;u&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; u&lt;span style="color:#f92672"&gt;.&lt;/span&gt;permit(&lt;span style="color:#e6db74"&gt;:name&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;:email&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:password&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:password_confirmation&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:current_password&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;パラメータの許可は&lt;code&gt;devise_parameter_sanitizer&lt;/code&gt;というDevise用のオブジェクトを経由して行われていて、この部分で&lt;code&gt;:name&lt;/code&gt;も許可対象として指定してあげれば良い。&lt;/p&gt;
&lt;p&gt;そして&lt;code&gt;config/routes.rb&lt;/code&gt;を編集し、新しく作った&lt;code&gt;Users::RegistrationsController&lt;/code&gt;を使うようにルートを書き換えればよい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# before&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;devise_for &lt;span style="color:#e6db74"&gt;:users&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# after&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;devise_for &lt;span style="color:#e6db74"&gt;:users&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;controllers&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;registrations&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;users/registrations&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;完成！&lt;/p&gt;</description></item><item><title>RailsでDeviseを使ったときのログイン周りの画面遷移</title><link>https://blog.piyo.tech/posts/2014-07-02-203000/</link><pubDate>Wed, 02 Jul 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-02-203000/</guid><description>&lt;p&gt;Deviseを使ってユーザー認証機能を作ったときに、もうちょっとよくするための方法メモ。Deviseは普通の実装するとログイン後は&lt;code&gt;/&lt;/code&gt;にリダイレクトされる。それを別のURLにする方法はここに書いた。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-12-24-212603"&gt;Deviseでログイン後のURLを変える方法 - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;では、ログインに必要なページのURLに直接アクセスがあったときはどうするか。流れとしてはこうなるのが望ましい。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ログインが必要なページにアクセスがある&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;ユーザーにログインフォームを見せる&lt;/li&gt;
&lt;li&gt;ログインが完了したら最初にアクセスしたURLへリダイレクト&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ログインが必要かどうかはコントローラレベルで制御する。これはまあよくやるやつ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# application_controller.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ApplicationController&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActionController&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sign_in_required&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; redirect_to new_user_session_url &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; user_signed_in?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# hoge_controller.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;HogeController&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ApplicationController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; before_action &lt;span style="color:#e6db74"&gt;:sign_in_required&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;index&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;全てのコントローラで共有するために、ApplicationControllerに&lt;code&gt;sign_in_required&lt;/code&gt;というメソッドを定義する。これにはログインしていなければログインページヘリダイレクトする、と書かれている。この&lt;code&gt;sign_in_required&lt;/code&gt;は各コントローラの&lt;code&gt;before_action&lt;/code&gt;で使い、指定したアクションを要ログインにできる。&lt;/p&gt;
&lt;p&gt;ここまでの実装だと1と2までは実現できているが、最初に開こうとしたURLへのリダイレクトは実現されておらず、ユーザーとしては非常に面倒くさい。リダイレクト部分を実現するためには最初のURLを覚えておいて、ログイン後のURLを&lt;code&gt;/&lt;/code&gt;ではなく別のURLに差し替えてあげる必要がある。&lt;/p&gt;
&lt;p&gt;そこでApplicationControllerをさらに拡張する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ApplicationController&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActionController&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; before_action &lt;span style="color:#e6db74"&gt;:store_location&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sign_in_required&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; redirect_to new_user_session_url &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; user_signed_in?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;store_location&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/users/sign_in&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/users/sign_up&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/users/password/new&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/users/sign_out&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;xhr?)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; session&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:previous_url&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fullpath
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;after_sign_in_path_for&lt;/span&gt;(resource)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; session&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:previous_url&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; root_path
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;store_location&lt;/code&gt;でURLを覚えておき、&lt;code&gt;after_sign_in_path_for&lt;/code&gt;で覚えておいたURLを返すということをしている。そして&lt;code&gt;store_location&lt;/code&gt;を全てのアクションの【前】に呼び出している。&lt;/p&gt;
&lt;p&gt;詳しいことは↓に書かれているが、ここの例では&lt;code&gt;store_location&lt;/code&gt;を&lt;code&gt;after_filter&lt;/code&gt;に指定、つまり各アクションの後に呼んでいる。今回の例ではアクション中にログインページにリダイレクトされてしまうため、覚えておくURLが適切なものではなくなってしまう。そこで&lt;code&gt;before_action&lt;/code&gt;を指定することでなんとか実現している。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/plataformatec/devise/wiki/How-To:-Redirect-back-to-current-page-after-sign-in,-sign-out,-sign-up,-update"&gt;How To: Redirect back to current page after sign in, sign out, sign up, update · plataformatec/devise Wiki&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Railsのredirect_toでちょっとだけはまる</title><link>https://blog.piyo.tech/posts/2014-07-01-203000/</link><pubDate>Tue, 01 Jul 2014 20:30:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-07-01-203000/</guid><description>&lt;p&gt;普通にRails書いていてどうもうまくいかないところがあってはまったのでメモしておく。&lt;/p&gt;
&lt;p&gt;フォーム埋めて&lt;code&gt;create&lt;/code&gt;アクションにPOSTしたあと、モデルのsaveが成功したら&lt;code&gt;index&lt;/code&gt;アクションへリダイレクト、失敗したらもう1回&lt;code&gt;new&lt;/code&gt;をレンダリングというよくあるケース。これで保存に成功してindexにリダイレクトしたとき、なぜかURLに&lt;code&gt;?notice=success&lt;/code&gt;がくっついてしまうということがあった。&lt;/p&gt;
&lt;p&gt;実際に書いたコード（とほぼ同じもの）はこちら。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;create&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; @entry &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Entry&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(permitted_params)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; @entry&lt;span style="color:#f92672"&gt;.&lt;/span&gt;save
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; redirect_to &lt;span style="color:#e6db74"&gt;action&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:index&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;notice&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; render &lt;span style="color:#e6db74"&gt;:new&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実は上のコードだと問題があるが、気を抜いていたので見落としてしまった。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;redirect_to&lt;/code&gt;はこのようにハッシュの引数を2つ受け取る。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;redirect_to(options &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {}, response_status &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;さきほどのケースでは暗黙のうちに&lt;code&gt;action&lt;/code&gt;も&lt;code&gt;notice&lt;/code&gt;も1つ目のハッシュであると解釈されてしまった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;redirect_to({&lt;span style="color:#e6db74"&gt;action&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:index&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;notice&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rubyではメソッドの引数になるハッシュの波カッコは省略できるし、メソッドの引数も省略できることもあるのでどちらが優先されるのかが一見するとわかりにくい。&lt;/p&gt;
&lt;p&gt;正しく動かすには以下のようにする必要がある。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;create&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; @entry &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Entry&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(permitted_params)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; @entry&lt;span style="color:#f92672"&gt;.&lt;/span&gt;save
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; redirect_to({&lt;span style="color:#e6db74"&gt;action&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:index&lt;/span&gt;}, &lt;span style="color:#e6db74"&gt;notice&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; render &lt;span style="color:#e6db74"&gt;:new&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一応これでうまくいった。&lt;/p&gt;</description></item><item><title>Pry 0.10.0でundefined method `pager'</title><link>https://blog.piyo.tech/posts/2014-06-30-200000/</link><pubDate>Mon, 30 Jun 2014 20:00:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-30-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b1517cbc-ca4e-4e78-9299-2b22177be595/6c99722eb274398e93986dc786423a68/deep/0/pry_logo.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Rails4でデバッグ用にPryを入れようと思ってGemfileにこんな風に書いた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;group &lt;span style="color:#e6db74"&gt;:development&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;pry&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;pry-rails&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;pry-byebug&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;pry-stack_explorer&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで&lt;code&gt;rails console&lt;/code&gt;を起動してゴニョゴニョしているとなんだか見慣れないエラーが…&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;(pry) output error: #&amp;lt;NoMethodError: undefined method `pager&amp;#39; for nil:NilClass&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Railsのせいかどうかを確認するためにPry単体で起動してみてもダメだった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% pry
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&amp;gt; str &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hogehoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;pry&lt;span style="color:#f92672"&gt;)&lt;/span&gt; output error: &lt;span style="color:#75715e"&gt;#&amp;lt;NoMethodError: undefined method `pager&amp;#39; for nil:NilClass&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;その上最悪なのは、こういうのを調べるときはいつもPryを使うんだけど、Pryの出力が壊れているからそういうわけにもいかないということ。&lt;/p&gt;
&lt;p&gt;少し前に書いたサンプルアプリケーションでは動いていた気がするからPryのバージョンじゃね？と当たりをつけ、Gemfileを少し書き換えた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;group &lt;span style="color:#e6db74"&gt;:development&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;pry&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;lt; 0.10.0&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;pry-rails&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;pry-byebug&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;pry-stack_explorer&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで&lt;code&gt;bundle update pry&lt;/code&gt;を行うと、例えばバージョン&lt;code&gt;0.9.12.6&lt;/code&gt;あたりがインストールされることになる。&lt;/p&gt;
&lt;p&gt;同じようにPry単体で実行してみると、、、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% pry
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&amp;gt; str &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hogehoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hogehoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちゃんと出力されている。0.10.0の不具合だったようだ。&lt;/p&gt;
&lt;p&gt;使う分にはとりあえずこれでOK。気が向いたらissueでも覗いてみようと思う。&lt;/p&gt;</description></item><item><title>Windows用スニペットアプリ</title><link>https://blog.piyo.tech/posts/2014-06-29-203000/</link><pubDate>Sun, 29 Jun 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-29-203000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/50f3d5e6-7660-414f-97e5-9bedfd38d9c8/9963d890c48ea8dacbda8e0d48d1185f/deep/0/autotext.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;MacではDashでスニペットを管理している。Macでは他にもTextExpanderなどが有名だが、Windowsでは何があるのかを気にしたことがなかった。&lt;/p&gt;
&lt;p&gt;最近Windowsを使い始めたときに調べてみると、PhraseExpressというのが同じような感じで使えそうだということがわかった。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.phraseexpress.com/"&gt;Autotext - Text Expander for Windows - Snippets Organizer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;とりあえずミニマムなユースケースで紹介。&lt;/p&gt;
&lt;p&gt;僕は自分のメールアドレスをタイプするのすら面倒で、Macでは&lt;code&gt;;ml&lt;/code&gt;というキーワードをタイプすると自分のgmailのアドレスに展開されるようにしている。サービスのログインなんかでメールアドレスはよく使うのでこれが以外と便利。&lt;/p&gt;
&lt;p&gt;これと同じような設定をこのPhrase Expressでやってみた。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/13ee0514-1161-44d1-aa87-8ec9a4411d22/718557d4b421ec2a09bc699ac2585014/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88.png" alt=""&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Expert modeのほうがわかりやすい&lt;/li&gt;
&lt;li&gt;gmailという名前を付けたスニペット&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Autotext&lt;/code&gt;がキーワード&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Prefix&lt;/code&gt;はAny、&lt;code&gt;Postfix&lt;/code&gt;はNone（これにより&lt;code&gt;;ml&lt;/code&gt;だけで展開可能）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一応これで使えるようになった。&lt;/p&gt;
&lt;p&gt;Dashと違いホットキーやPrefix、Postfixを絡められるので、複雑な条件での展開も可能だが、そこまでやる必要はないんじゃないかと思う。どちらにしろDashでは使えないし。&lt;/p&gt;</description></item><item><title>yamy使用中にAlt+Tabのウィンドウ切り替えが動かない</title><link>https://blog.piyo.tech/posts/2014-06-28-200000/</link><pubDate>Sat, 28 Jun 2014 20:00:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-28-200000/</guid><description>&lt;p&gt;先日からセットアップを続けているWindowsマシンで&lt;code&gt;Alt&lt;/code&gt;+&lt;code&gt;Tab&lt;/code&gt;のウィンドウ切り替えが使えなくなっていた。どうせ常駐ソフトだろうということで、キー配列を変更する「yamy」だろと思ったら正にその通りだった。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-06-23-215707"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-06-23-215707" alt="日本語キーボードのWindowsでUS配列を使う方法 - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-06-23-215707"&gt;日本語キーボードのWindowsでUS配列を使う方法 - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;どうやらオリジナルバージョンに存在する不具合らしい。パッチバージョンがあるのでそちらに置き換えれば問題なく動くようになった。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://callcc.net/archive/yamy-0.03-alt-tab.zip"&gt;http://callcc.net/archive/yamy-0.03-alt-tab.zip&lt;/a&gt;&lt;/p&gt;</description></item><item><title>MySQLのデータベース接続確立エラー</title><link>https://blog.piyo.tech/posts/2014-06-27-200000/</link><pubDate>Fri, 27 Jun 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-27-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/bcc63845-2ebd-4111-b077-24e06f4fe6e8/898559d460cc26d09aa2123af312efb5/deep/0/logomysql.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;AWSのt1.microとかWindowsAzureの仮想マシンとかでWordPressを動かしているとき、割と頻繁に「データベース接続確立エラー」というエラーを見かけることがあった。&lt;/p&gt;
&lt;p&gt;ログを見るとなんらかの理由で再起動がかかったあとで起動に失敗しているようだ。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;140627 00:52:45 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
140627 0:52:45 [Note] Plugin &amp;#39;FEDERATED&amp;#39; is disabled.
140627 0:52:45 InnoDB: The InnoDB memory heap is disabled
140627 0:52:45 InnoDB: Mutexes and rw_locks use GCC atomic builtins
140627 0:52:45 InnoDB: Compressed tables use zlib 1.2.3
140627 0:52:45 InnoDB: Using Linux native AIO
140627 0:52:45 InnoDB: Initializing buffer pool, size = 128.0M
InnoDB: mmap(137363456 bytes) failed; errno 12
140627 0:52:45 InnoDB: Completed initialization of buffer pool
140627 0:52:45 InnoDB: Fatal error: cannot allocate memory for the buffer pool
140627 0:52:45 [ERROR] Plugin &amp;#39;InnoDB&amp;#39; init function returned error.
140627 0:52:45 [ERROR] Plugin &amp;#39;InnoDB&amp;#39; registration as a STORAGE ENGINE failed.
140627 0:52:45 [ERROR] Failed to initialize plugins.
140627 0:52:45 [ERROR] Aborting
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;メモリの問題のように見えるので&lt;code&gt;free&lt;/code&gt;コマンドでメモリを調べてみたところ、スワップ領域がゼロになっていた。このあたりのリンクを参考にスワップ領域を割り当てると、&lt;code&gt;mysqld&lt;/code&gt;は問題なく起動してくれた。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blog.hereticsintheworld.com/4165.html"&gt;Amazon EC2 の t1.microインスタンスでMySQLがよく落ちる – blog.hereticsintheworld&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://qiita.com/unosk/items/984b336a292fc1dcf03c"&gt;Azure仮想マシンへのSwap領域の割り当て - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Windows8でランチャソフトbluewindの呼び出しキーを変更する</title><link>https://blog.piyo.tech/posts/2014-06-26-203000/</link><pubDate>Thu, 26 Jun 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-26-203000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/d7d46d05-cff7-4a15-885c-6274361ecc71/da93e1e9172f4a8b56300b8d83b2f708/deep/0/imgres.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;WindowsXP〜Windows7までコマンドライン型のbluewindというランチャを愛用していたが、ここ2年間はほとんどMacを使用していたためそもそもWindowsを使っていなかった。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.web-ghost.net/bluewind/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://www.web-ghost.net/bluewind/" alt="bluewind＆単機能ツール集 再配布所" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://www.web-ghost.net/bluewind/"&gt;bluewind＆単機能ツール集 再配布所&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://www.web-ghost.net/bluewind/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://www.web-ghost.net/bluewind/" alt="はてなブックマーク - bluewind＆単機能ツール集 再配布所" title="はてなブックマーク - bluewind＆単機能ツール集 再配布所" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;最近Windowsを使う機会が再来したため環境のセットアップを行っていたところ、bluewindの安定版（1.60r1）では設定画面から呼び出しキーを変更できないという問題が確認された。デフォルト設定では「Win+Space」になっているが、僕は「Ctrl+Space」で呼び出したい。設定変更ができないのでは困る。&lt;/p&gt;
&lt;p&gt;そこで、設定ファイルを直接書き換えることにした。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bluewind.exe&lt;/code&gt;が置いてあるフォルダに&lt;code&gt;Users/XXXXX&lt;/code&gt;というユーザー設定用のフォルダがある。その中にある&lt;code&gt;bluewind.ini&lt;/code&gt;をテキストエディタで開き、次のような記述がある場所を探す。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Call_key&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;32&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Call_Mod&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Call_S&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;Win+Space&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Call_key&lt;/code&gt;と&lt;code&gt;Call_Mod&lt;/code&gt;がキーとモディファイアで、&lt;code&gt;Call_S&lt;/code&gt;が文字列表記のことのようだ。&lt;/p&gt;
&lt;p&gt;「Win+Space」を「Ctrl+Space」にしたいので&lt;code&gt;Call_key&lt;/code&gt;はそのままにし、&lt;code&gt;Call_Mod&lt;/code&gt;を「Ctrl」を意味する「2」に変更し、文字列もそれに合わせて変更した。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 変更後&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Call_key&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;32&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Call_Mod&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Call_S&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;Ctrl+Space&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;bluewindを再起動すればこのキーで呼び出しできるようになる。&lt;/p&gt;</description></item><item><title>巨大なファイルをダウンロードするときに便利なFirefox拡張</title><link>https://blog.piyo.tech/posts/2014-06-24-200000/</link><pubDate>Tue, 24 Jun 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-24-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0a05f7cf-2bd5-4026-a266-eb883cda2d6c/831ad4bac3fb81e08626df0a54802be0/deep/0/%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;数GBにもなる巨大なファイルをダウンロードするときがたまにある。例えば今の会社などはMicrosoftのサブスクリプションに入っているため、Officeなどのソフトウェアをダウンロードで手に入れることになる。こういった場合には数GBのファイルを数10分、時には1時間以上かけて行うことになる。&lt;/p&gt;
&lt;p&gt;そのような長い時間ダウンロードしっぱなしでいると、たまにネットワークの状態が悪くなったりマシンがスリープに入ったりしてダウンロードが中断してしまい、また最初からダウンロードのやり直しになってしまうことがある。&lt;/p&gt;
&lt;p&gt;これは大変嘆かわしいことで、ソフトをインストールしないと仕事にならないのにまた同じ時間待つのかよ、といった事態になる。&lt;/p&gt;
&lt;p&gt;それを回避する1つの方法がブラウザのダウンロード系アドオンを使うことだ。それがこのFirefox拡張、DownThemAll。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://addons.mozilla.org/ja/firefox/addon/downthemall/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://addons.mozilla.org/ja/firefox/addon/downthemall/" alt="DownThemAll! :: Add-ons for Firefox" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://addons.mozilla.org/ja/firefox/addon/downthemall/"&gt;DownThemAll! :: Add-ons for Firefox&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/https://addons.mozilla.org/ja/firefox/addon/downthemall/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/https://addons.mozilla.org/ja/firefox/addon/downthemall/" alt="はてなブックマーク - DownThemAll! :: Add-ons for Firefox" title="はてなブックマーク - DownThemAll! :: Add-ons for Firefox" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;僕は普段使いのブラウザはChromeだが、大きなファイルをダウンロードするときだけはこのアドオンのためにFirefoxを使うことにしている。&lt;/p&gt;
&lt;p&gt;このツールを使うとネットワークのせいで中断することはほとんどないし、中断したり再開したりすることもできる。僕はその用途でしか使わないが実は機能も豊富のようで、画像の一括ダウンロードとかミラーリングなどもできるらしい。&lt;/p&gt;
&lt;p&gt;今日もVisual Studioのインストールディスクイメージをダウンロードするのに活躍してもらった。ありがとうDownThemAll。&lt;/p&gt;
&lt;p&gt;とは言ったものの、Chromeで似たようなものがあればそっちに乗り換えたい。&lt;/p&gt;</description></item><item><title>日本語キーボードのWindowsでUS配列を使う方法</title><link>https://blog.piyo.tech/posts/2014-06-23-215707/</link><pubDate>Mon, 23 Jun 2014 21:57:07 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-23-215707/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/5a06b5a7-a181-4c70-9718-c7152be308fd/86254829ea1affde0a3e3f864a67ee79/deep/0/uskey.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;僕は普段からUS配列のMacを使っている。プログラムを書くにあたってはUS配列のほうが優れていると思っている。&lt;/p&gt;
&lt;p&gt;ところで、仕事でWindowsを使うことになったので今日はそのセットアップをしていた。Windowsについているキーボードが日本語配列なのだが、Windowsでも同じようにUS配列を使いたいし、使えないとプログラムを書けない。何かしら方法があるだろうとタカをくくっていたが全然見つからない。どうしよう。&lt;/p&gt;
&lt;p&gt;「Windows キーボード US 配列」などと検索したが、WindowsでUSキーボードを認識させる話や、日本語キーボードがUSキーボードとして認識されてしまう話ばかりで、配列を変更する話が全然見当たらない。&lt;/p&gt;
&lt;p&gt;どうにかこうにか頑張って、&lt;code&gt;yamy&lt;/code&gt;という「窓使いの憂鬱」というソフトウェアの後継ソフトに出会うことができた。使い方がわかりづらかったが、すでに素晴らしいエントリがあったのでこちらを参考にした。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://d.hatena.ne.jp/kaosf/20111122/1321969965"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://d.hatena.ne.jp/kaosf/20111122/1321969965" alt="Windows 7 で yamy を使ってキー配列を変更 (Windows XP での窓使いの憂鬱の後継) - kaosfield blog" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://d.hatena.ne.jp/kaosf/20111122/1321969965"&gt;Windows 7 で yamy を使ってキー配列を変更 (Windows XP での窓使いの憂鬱の後継) - kaosfield blog&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/kaosf/20111122/1321969965" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/kaosf/20111122/1321969965" alt="はてなブックマーク - Windows 7 で yamy を使ってキー配列を変更 (Windows XP での窓使いの憂鬱の後継) - kaosfield blog" title="はてなブックマーク - Windows 7 で yamy を使ってキー配列を変更 (Windows XP での窓使いの憂鬱の後継) - kaosfield blog" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;同じような検索で情報を見つけられない人がいるかもしれないので僕も書いておくことにした。&lt;/p&gt;
&lt;p&gt;まずyamyのダウンロードはこちらで行う。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sourceforge.jp/projects/yamy/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://sourceforge.jp/projects/yamy/" alt="Yet Another Mado tsukai no Yuutsu プロジェクト日本語トップページ - SourceForge.JP" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://sourceforge.jp/projects/yamy/"&gt;Yet Another Mado tsukai no Yuutsu プロジェクト日本語トップページ - SourceForge.JP&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://sourceforge.jp/projects/yamy/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://sourceforge.jp/projects/yamy/" alt="はてなブックマーク - Yet Another Mado tsukai no Yuutsu プロジェクト日本語トップページ - SourceForge.JP" title="はてなブックマーク - Yet Another Mado tsukai no Yuutsu プロジェクト日本語トップページ - SourceForge.JP" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;ダウンロードしたyamyを適当に展開し、exeと同じディレクトリに&lt;code&gt;.mayu&lt;/code&gt;というファイルを作成し、次の内容にする。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;include &amp;#34;109.mayu&amp;#34;
include &amp;#34;104on109.mayu&amp;#34;
def subst *RightSquareBracket = *Enter
def subst *E0英数 = *E0英数
mod control += E0英数
key *E0英数 = *LControl
def subst *変換 = *変換
def subst *E0無変換 = $ToggleIME
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ファイルの内容は先程の記事からの引用だが、次のようなキー変更をするものだそうだ。&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;日本語 109 キーボードを US 配列にする&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;US 配列にした上で ] キーを Enter キーにする (US 配列ではこの位置が Enter なので)&lt;/li&gt;
&lt;li&gt;CapsLock を Left Control にする&lt;/li&gt;
&lt;li&gt;US 配列にしたせいで Space になってしまう無変換キーを IME 起動キーにする&lt;/li&gt;
&lt;li&gt;US 配列にしたせいで Space になってしまう変換キーを変換キーに戻す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こうしておけば&lt;code&gt;yamy&lt;/code&gt;を起動している間はUS配列で使うことができるようになる。素晴らしい。&lt;/p&gt;</description></item><item><title>SwiftのUnderscore.js風ライブラリ見つけた</title><link>https://blog.piyo.tech/posts/2014-06-22-200000/</link><pubDate>Sun, 22 Jun 2014 20:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-22-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/6da613a5-f8e6-4a53-b3c5-9fd6e7ad87bf/a35c78e93b75ddee6201db532e1fcefa/deep/0/687474703a2f2f692e696d6775722e636f6d2f7a6238386a46552e706e67.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;前にObjective-C向けのを見つけてこんなのを書いた。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-04-27-204024"&gt;Underscore.js風Objective-Cライブラリ「_.m」 - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Swiftにも早速似たようなのが出てきたようだ。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dollarswift.org/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://www.dollarswift.org/" alt="Dollar.$wift by ankurp" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://www.dollarswift.org/"&gt;Dollar.$wift by ankurp&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h1 id="サンプルで比較"&gt;サンプルで比較&lt;/h1&gt;
&lt;p&gt;例としてfindのサンプルを。&lt;/p&gt;
&lt;h2 id="swift"&gt;Swift&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;.find([&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;], iterator: { $0 == &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;=&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="objective-c"&gt;Objective-C&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;N&lt;span style="color:#f92672"&gt;*&lt;/span&gt; even &lt;span style="color:#f92672"&gt;=&lt;/span&gt; _.find(AI(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;), &lt;span style="color:#f92672"&gt;^&lt;/span&gt;B(N&lt;span style="color:#f92672"&gt;*&lt;/span&gt; num){ &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; num.I &lt;span style="color:#f92672"&gt;%&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Objective-Cのほうは&lt;code&gt;AI&lt;/code&gt;とかいうマクロで配列を表現したり、ブロックの部分が書きにくかったりするので少々複雑に見える。Swiftのほうがやはりシンプルに書けるようだ。&lt;/p&gt;
&lt;h1 id="実装を比較"&gt;実装を比較&lt;/h1&gt;
&lt;p&gt;findの実装も見比べてみる。&lt;/p&gt;
&lt;h2 id="swift-1"&gt;Swift&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;func&lt;/span&gt; find&amp;lt;T: Equatable&amp;gt;(array: T[], iterator: (T) -&amp;gt; Bool) -&amp;gt; T? {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; elem &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; array {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; result = iterator(elem)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; result {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; elem
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="objective-c-1"&gt;Objective-C&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;+ (&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;(&lt;span style="color:#f92672"&gt;^&lt;/span&gt;)(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt; list, _FindBlock iterator))&lt;span style="color:#a6e22e"&gt;find&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;^&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt; list, _FindBlock iterator) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;__block&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;id&lt;/span&gt; result;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; _.any(list, &lt;span style="color:#f92672"&gt;^&lt;/span&gt;B(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt; value, ... &lt;span style="color:#75715e"&gt;/* KEY, LIST */&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (iterator(value)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; value;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; false;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; result;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Objective-Cつらい。&lt;/p&gt;</description></item><item><title>MonoDevelopがバージョン4になって割とまともになった…！</title><link>https://blog.piyo.tech/posts/2014-06-21-193000/</link><pubDate>Sat, 21 Jun 2014 19:30:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-21-193000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/90d8bb84-f1a3-46ee-803e-a49a38b80055/e30c90c6e789b6ae58de708ab5d1a7c2/deep/0/Unity.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;8ヶ月ぐらい前にMonoDevelopがクソっていう記事をかいた。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-10-18-215707"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2013-10-18-215707" alt=" MonoDevelopは重いし日本語周りが全然まともに使えない上、右クリックメニューに至っては何も文字がない…！ｗｗ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2013-10-18-215707"&gt; MonoDevelopは重いし日本語周りが全然まともに使えない上、右クリックメニューに至っては何も文字がない…！ｗｗ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;ところが先日Unityを久しぶりにインストールし直したら、一緒にインストールされたMonoDevelop 4.0.1が大幅にまともになっていたので一応フォローしておこうと思う。&lt;/p&gt;
&lt;p&gt;さっきの記事で書いたようなメニュー表記とか右クリックメニューの問題はほぼ無さそうに見える。最低限の動きはするので、一見すると「あ、別にこれ使ってもいいな」と思わせてくれる作りになっている。&lt;/p&gt;
&lt;p&gt;当たり前だが、入力補助は外部のエディターを使うよりも優秀なので、Unity開発においてはMonoDevelopを使うのが正しい選択肢になったのかもしれない。&lt;/p&gt;
&lt;p&gt;良かった良かった。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4797376473/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/51b4nl-sEDL._SL1000_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;Unity4ゲームコーディング&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>Kobitoのコマンドライン「kobito-cli」がめちゃ便利</title><link>https://blog.piyo.tech/posts/2014-06-20-200000/</link><pubDate>Fri, 20 Jun 2014 20:00:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-20-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/2d3ef6d7-f6e3-4089-9ef5-86df0246ec04/da9f7a02b658f59554a7f8e783332420/deep/0/%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;タイトルそのままなんだけど、これめちゃくちゃ便利。個人的には&lt;code&gt;kobito pdf&lt;/code&gt;、&lt;code&gt;kobito print&lt;/code&gt;が便利。これでマークダウンでプレビューしながらドキュメント書いてPDFに整形も簡単にできるし。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/suin/kobito-cli"&gt;suin/kobito-cli&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="usage"&gt;Usage&lt;/h1&gt;
&lt;p&gt;これUsageそのまんま転載なんだけど、使い方もシンプルで良い。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Usage:
kobito [command]
Available Commands:
ls :: List all items
show [item id] :: Show item
html [item id] :: Show item as HTML
print [item id] :: Print out item
link [markdown file] :: Link markdown file to Kobito
version :: Print kobito cli tools version
pdf [item id] | pdf [item id] [pdf file name] :: Save item as PDF
password :: Show Kobito password
sticker :: Do you want Kobito sticker?
help [command] :: Help about any command
Use &amp;#34;kobito help [command]&amp;#34; for more information about that command.
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="ls"&gt;ls&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% kobito ls
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;ITEM_ID TITLE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;109&lt;/span&gt; ほげほげほげ
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;105&lt;/span&gt; タイトルタイトル
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;110&lt;/span&gt; ああああああああああああああ
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;107&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;35&lt;/span&gt; ◯◯について
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="show"&gt;show&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% kobito show &lt;span style="color:#ae81ff"&gt;105&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;タイトルタイトル
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# マークダウンのテキストが&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## そのまま標準出力に表示されます&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="html"&gt;html&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;% kobito html &lt;span style="color:#ae81ff"&gt;105&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&amp;lt;!DOCTYPE HTML&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&amp;lt;html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &amp;lt;head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &amp;lt;meta http-equiv&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;content-type&amp;#34;&lt;/span&gt; content&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/html; charset=UTF-8&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &amp;lt;title&amp;gt;Kobito Memo&amp;lt;/title&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &amp;lt;script type&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt; src&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;highlight.pack.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &amp;lt;script&amp;gt;hljs.initHighlightingOnLoad&lt;span style="color:#f92672"&gt;()&lt;/span&gt;;&amp;lt;/script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &amp;lt;script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; setTitleForAllAnchors&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; Array.prototype.map.call&lt;span style="color:#f92672"&gt;(&lt;/span&gt;document.getElementsByTagName&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;a&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; a.title &lt;span style="color:#f92672"&gt;=&lt;/span&gt; a.href;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;})&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; window.addEventListener&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;DOMContentLoaded&amp;#39;&lt;/span&gt;, setTitleForAllAnchors, false&lt;span style="color:#f92672"&gt;)&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &amp;lt;/script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &amp;lt;link type&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/css&amp;#34;&lt;/span&gt; rel&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; href&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;github.min.css&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &amp;lt;link type&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/css&amp;#34;&lt;/span&gt; rel&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; href&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;markdown.css&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &amp;lt;link type&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/css&amp;#34;&lt;/span&gt; rel&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; href&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;file:///Users/hiromasa/Library/Kobito/CSS/custom-style.css?time=1403160361.055531&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &amp;lt;/head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;&amp;lt;h1&amp;gt;タイトルタイトル&amp;lt;/h1&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;&amp;lt;h1&amp;gt;マークダウンのテキストが&amp;lt;/h1&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;&amp;lt;h2&amp;gt;そのまま標準出力に表示されます&amp;lt;/h2&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;&amp;lt;/html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="print"&gt;print&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% kobito print &lt;span style="color:#ae81ff"&gt;105&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# SafariでHTMLとして開いたあと印刷ダイアログを表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="pdf"&gt;pdf&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% kobito pdf &lt;span style="color:#ae81ff"&gt;105&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# カレントディレクトリに「タイトルタイトル.pdf」&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="パイプリダイレクト"&gt;パイプ、リダイレクト&lt;/h1&gt;
&lt;p&gt;文字列を渡すとKobitoのエントリーになるみたい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% kobito &amp;lt; hoge.rb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# hoge.rbの内容がKobitoのエントリーになる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% tail development.log | kobito
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ログの最後の10行Kobitoのエントリーになる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Rubyで文字列を正規表現にマッチする単位で分割する方法</title><link>https://blog.piyo.tech/posts/2014-06-18-190000/</link><pubDate>Wed, 18 Jun 2014 19:00:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-18-190000/</guid><description>&lt;p&gt;タイトルがわかりづらいけど、この文字列を&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;str &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ab#cde# ##...fgh.i##&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こうしたい、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ab&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;#&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;cde&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;#&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34; &amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34; &amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;#&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;#&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;fgh&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;i&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;#&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;#&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;という話。&lt;/p&gt;
&lt;p&gt;文字列はひとまとめ、それ以外はバラバラにという感じで。&lt;/p&gt;
&lt;p&gt;分割というとまず&lt;code&gt;String#split&lt;/code&gt;が思いつく。&lt;code&gt;String#split&lt;/code&gt;は普通に使うと区切り文字で分割した文字列の配列を返してくれる。そのため上のような結果が欲しい場合には使えない。区切り文字にした文字が消えてしまうからね。&lt;/p&gt;
&lt;p&gt;ところでドキュメントを読んだらこんな風にかいてあった。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If pattern is a Regexp, str is divided where the pattern matches. Whenever the pattern matches a zero-length string, str is split into individual characters. If pattern contains groups, the respective matches will be returned in the array as well.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;括弧によるグルーピングがあればマッチしたグループも結果の配列に入ってくれるらしい。これはいけるんじゃないか？と思ったので試してみた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;regexp &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/([\w]+|#|\.| )/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;str &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ab#cde# ##...fgh.i##&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;str&lt;span style="color:#f92672"&gt;.&lt;/span&gt;split(regexp)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# =&amp;gt; [&amp;#34;&amp;#34;, &amp;#34;ab&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;#&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;cde&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;#&amp;#34;, &amp;#34;&amp;#34;, &amp;#34; &amp;#34;, &amp;#34;&amp;#34;, &amp;#34; &amp;#34;, &amp;#34;&amp;#34;, &amp;#34;#&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;#&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;.&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;.&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;.&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;fgh&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;.&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;i&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;#&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;#&amp;#34;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;##...&lt;/code&gt;みたいな部分が分割されまくってて空文字列がたくさんはいっているけど、それを除くと欲しい単位で分割されているように見える。ここから空文字列を取り除く。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;regexp &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/([\w]+|#|\.| )/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;str &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ab#cde# ##...fgh.i##&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;str&lt;span style="color:#f92672"&gt;.&lt;/span&gt;split(regexp)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;select {&lt;span style="color:#f92672"&gt;|&lt;/span&gt;s&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;s&lt;span style="color:#f92672"&gt;.&lt;/span&gt;empty? }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# =&amp;gt; [&amp;#34;ab&amp;#34;, &amp;#34;#&amp;#34;, &amp;#34;cde&amp;#34;, &amp;#34;#&amp;#34;, &amp;#34; &amp;#34;, &amp;#34; &amp;#34;, &amp;#34;#&amp;#34;, &amp;#34;#&amp;#34;, &amp;#34;.&amp;#34;, &amp;#34;.&amp;#34;, &amp;#34;.&amp;#34;, &amp;#34;fgh&amp;#34;, &amp;#34;.&amp;#34;, &amp;#34;i&amp;#34;, &amp;#34;#&amp;#34;, &amp;#34;#&amp;#34;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;できた！&lt;/p&gt;</description></item><item><title>1日に数回起動するようなスクリプトをHerokuで動かす荒業</title><link>https://blog.piyo.tech/posts/2014-06-17-203000/</link><pubDate>Tue, 17 Jun 2014 20:30:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-17-203000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/82ef52fb-28b4-4936-9d4d-8b7fa624ce64/4c6510a1e26c30b1a0b46bc2b60330b1/deep/0/Heroku-Scheduler.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;HerokuにはSchedulerっていうAddonがあって、それを使うと10分毎、1時間毎、1日毎という単位で好きなコマンドを動かすことができる。&lt;/p&gt;
&lt;p&gt;ちょっとしたスクリプトを動かすためだけにサーバーを立てるのは面倒だから、そこをHerokuにしてしまおうという荒業を考えた。&lt;/p&gt;
&lt;h1 id="rackアプリケーションの作成"&gt;Rackアプリケーションの作成&lt;/h1&gt;
&lt;p&gt;まず、Herokuのドキュメントを参考にしてほぼ最小限のRackアプリケーションを作る。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devcenter.heroku.com/articles/rack#pure-rack-apps"&gt;Deploying Rack-based Apps | Heroku Dev Center&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# config.ru&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;run lambda { &lt;span style="color:#f92672"&gt;|&lt;/span&gt;env&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;, {&lt;span style="color:#e6db74"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;text/plain&amp;#39;&lt;/span&gt;}, &lt;span style="color:#66d9ef"&gt;StringIO&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello World!&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;]&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Gemfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;source &lt;span style="color:#e6db74"&gt;&amp;#39;https://rubygems.org&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;rack&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;rake&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# ← rakeタスクを使うので書いておく&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このあと&lt;code&gt;$ bundle install&lt;/code&gt;を行って&lt;code&gt;Gemfile.lock&lt;/code&gt;を生成し、それらをローカルのGitリポジトリにコミットしておく。&lt;/p&gt;
&lt;h1 id="herokuアプリケーションの作成"&gt;Herokuアプリケーションの作成&lt;/h1&gt;
&lt;p&gt;Herokuの設定は済んでいるものとする。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ heroku create myapp
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;などとしてアプリケーションを作成する。&lt;/p&gt;
&lt;p&gt;あとは&lt;code&gt;$ git push heroku master&lt;/code&gt;としてソースコードをpushしてやればよい。Rackアプリケーションを検出してよしなにやってくれる。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;heroku open&lt;/code&gt;コマンドでアプリケーションページを開いてみると、Hello World!と表示されているのがわかると思う。&lt;/p&gt;
&lt;h1 id="rakeタスクを追加する"&gt;Rakeタスクを追加する&lt;/h1&gt;
&lt;p&gt;さて、ここが本来動かしたいスクリプトを書く場面になるが、シンプルにRakefileを作って直接スクリプトを書くことにする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Rakefile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;task &lt;span style="color:#e6db74"&gt;:hoge&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#34;hoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# do everything you want&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例えば上のようなRakefileを作ったとする。ローカルの環境で&lt;code&gt;$ rake hoge&lt;/code&gt;とやると、標準出力に&lt;code&gt;hoge&lt;/code&gt;と表示されるはずだ。そしてこれをコミットしてherokuにデプロイする。&lt;/p&gt;
&lt;p&gt;デプロイが終わったら次のコマンドを実行してみる。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ heroku run rake hoge
hoge # &amp;lt;= output
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;hogeと表示されるはず。これでHerokuの環境でもRakeタスクを実行できるようになった。&lt;/p&gt;
&lt;h1 id="スケジューラの導入"&gt;スケジューラの導入&lt;/h1&gt;
&lt;p&gt;Heroku Schedulerについてはドキュメントや他の記事を見てもらったほうが早いのでここではざっと説明するだけにする。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devcenter.heroku.com/articles/scheduler"&gt;Heroku Scheduler | Heroku Dev Center&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;まずコマンドラインから&lt;code&gt;addons:add&lt;/code&gt;でスケジューラを使う旨を伝え、&lt;code&gt;addons:open&lt;/code&gt;で管理画面を開く。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ heroku addons:add scheduler
$ heroku addons:open scheduler
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;初期画面はこんな感じになる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/dfa724b5-d8aa-4f91-b166-3aa65a46e15d/0ab5e476f99a5082acff9944936932f3/deep/0/Heroku-Scheduler.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;左下の&lt;code&gt;Add Job...&lt;/code&gt;から新規追加を行う。このとき、コマンドの部分を先ほどのRakeタスクと同じにすればOK。先ほどの例でと&lt;code&gt;rake hoge&lt;/code&gt;となる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/ddf36a7b-de07-4bad-8903-20422b5ceb8c/cdc259ce7948664328e1a94f42a21005/deep/0/Heroku-Scheduler.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;先ほどの例のような&lt;code&gt;puts&lt;/code&gt;するだけのタスクでは何の意味もないが、例えば何かの更新を定期的にチェックして、特定の条件でメールを送るというようなことができるようになる。&lt;/p&gt;
&lt;h1 id="herokuの無料枠"&gt;Herokuの無料枠&lt;/h1&gt;
&lt;p&gt;Herokuでは750時間分の無料枠が用意されているが、Webサーバーとして24時間動いていることを考えると、&lt;code&gt;24x31=744時間&lt;/code&gt;の無料枠はあのHelloWorldに使われてしまっていることになる。&lt;/p&gt;
&lt;p&gt;となると残りは6時間だが、この6時間はHerokuのコンソールを動かしたときやスケジューラを動かしたときに消費される。定期的に実行するタスクが重すぎるようだと無料枠を越えてしまい課金されるので注意が必要となる。&lt;/p&gt;
&lt;p&gt;1日1回動かすタスクであれば、360分/31日=約10分程度のタスクであれば無料の範囲で収まると考えてよさそう。&lt;/p&gt;</description></item><item><title>RubyでLoadErrorをキャッチする</title><link>https://blog.piyo.tech/posts/2014-06-16-200000/</link><pubDate>Mon, 16 Jun 2014 20:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-16-200000/</guid><description>&lt;p&gt;&lt;code&gt;require&lt;/code&gt;が失敗したときに発生する&lt;code&gt;LoadError&lt;/code&gt;例外をキャッチすべくこのようなコードを書いたが、うまくいかなかった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;begin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#34;hogehoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;rescue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#34;LoadError!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#34;Install hogehoge gem before running this code.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; exit
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# do something&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;どうやら&lt;code&gt;rescue&lt;/code&gt;節に何も指定しなかった場合、StandardErrorの例外のみをキャッチするらしい。&lt;code&gt;LoadError&lt;/code&gt;は&lt;code&gt;ScriptError&lt;/code&gt;のサブクラスであり、StandardErrorとは異なる継承ツリーにいる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/6701a09c-0c8b-4e6e-b168-1862dcba16f6/edf2b647f18fa625d9269e754646f8b0/deep/0/LoadError.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;先ほどのコードを次のように変更すれば&lt;code&gt;LoadError&lt;/code&gt;をキャッチできるようになるというわけ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;begin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#34;hogehoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;rescue&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;LoadError&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#34;LoadError!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#34;Install hogehoge gem before running this code.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; exit
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# do something&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>iOSで説明画面を表示するCocoaPodsライブラリ</title><link>https://blog.piyo.tech/posts/2014-06-15-193000/</link><pubDate>Sun, 15 Jun 2014 19:30:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-15-193000/</guid><description>&lt;p&gt;起動時に領域に対してちょっとした説明をしてくれるアプリをちょいちょい見かけるが、そんな機能を簡単に実装するためのiOSライブラリを見つけた。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/workshirt/WSCoachMarksView"&gt;workshirt/WSCoachMarksView&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;どんなものかはまずデモを見てもらえばわかるはず。&lt;/p&gt;
&lt;h1 id="デモ"&gt;デモ&lt;/h1&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/zKp2p83DeNkeJaj63V8du3EdIljuyNmtXhE5aGdsTi8M5JaPkchXuogAwuEeC1ArT4xoE1k1W8P77lCGkmPAzIoI2BaxvG4LlWSrxt-yQMr2dcvwurQX_yJ-CSNZ5PTJLrpeVrXmYXDkkoV3d-2wGrDiep4NiCdVav4PFt7pO4rfR4ReenY9qDM-nG5tAPeO5NOObukKm2OFygyG4_Ra9pkWiwv0Y2Q0-hXFBpocfS2AaoHCNZ-H7yjMYDa-GwyaOwcd8XlK-LAN4-w0W3CRLvDGm5nwrHJ82Tg1lAYPk6cRdJyb4S7RB60VrZSD5t4h8XIHmZ4qivJJfWu7nqwM9JhImvF7FHvsbRQatg54Jk7w-4NYT9Y_IliWNYf76v68FrQ-T8a_vpWcV9QZKzVj9TPrY9w0C-nSNitLmKMMRnrtt7Z-Xffepz0L_9U4e6dGBudCr905r9FTVepo4NZ9HquyV4S2uIo_J0VyxLH-dkjKtqXUnSVk6IpFwnoIdtKWzuBuJvU-SKR82GSKbl5iv2ZKZMtbkBAXAqmzLK6z5imB2k0-EweYied-dnMAyIGpMJmp9RrrdFcAWpxO_URR9GJplz8_QNy8p5e6Bi4Fg4tkQRTof_DgnUyxh0X8Dp-juFDQ5AZh9xpbyu8UwxuC5Iym_xu5jBht2Q=w159-h293-no" alt=""&gt;&lt;/p&gt;
&lt;h1 id="導入と実装方法"&gt;導入と実装方法&lt;/h1&gt;
&lt;p&gt;CocoaPodsに対応しているのでいつものようにインストールする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Podfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;WSCoachMarksView&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% pod install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実装のサンプルとして、ボタンが3つあるこんな画面に対して上から順に説明を表示することを考える。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/22baf295-00e2-4ab6-9276-8ae26e157015/3cad0c8adff477bcd149a55b84bff5b0/deep/0/CoachMark---Main.storyboard.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;それぞれのボタンはViewControllerクラスに関連づけてある。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;UIKit/UIKit.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ViewController&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;UIViewController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;IBOutlet&lt;/span&gt; UIButton &lt;span style="color:#f92672"&gt;*&lt;/span&gt;hogeButton;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;IBOutlet&lt;/span&gt; UIButton &lt;span style="color:#f92672"&gt;*&lt;/span&gt;fugaButton;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;IBOutlet&lt;/span&gt; UIButton &lt;span style="color:#f92672"&gt;*&lt;/span&gt;piyoButton;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;で、例えばこのViewControllerが表示されるときに説明画面を起動する場合は、&lt;code&gt;viewDidLoad&lt;/code&gt;で次のような実装を書く。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; [super viewDidLoad];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Do any additional setup after loading the view, typically from a nib.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; NSArray &lt;span style="color:#f92672"&gt;*&lt;/span&gt;marks &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;@[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;@{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;rect&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [NSValue valueWithCGRect:_hogeButton.frame],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;caption&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;Do hogehoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;@{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;rect&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [NSValue valueWithCGRect:_fugaButton.frame],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;caption&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;Do fugafuga&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;@{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;rect&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [NSValue valueWithCGRect:_piyoButton.frame],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;caption&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;Do piyopiyo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;]&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; WSCoachMarksView &lt;span style="color:#f92672"&gt;*&lt;/span&gt;coachView &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[WSCoachMarksView alloc] initWithFrame:self.view.bounds coachMarks:marks];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; [self.view addSubview:coachView];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; [coachView start];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;WSCoachMarksView&lt;/code&gt;は表示する文字列（&lt;code&gt;NSString*&lt;/code&gt;）とハイライト表示する領域(&lt;code&gt;CGRect&lt;/code&gt;)のディクショナリの配列を、初期化時に受け取る。あとは&lt;code&gt;addSubview&lt;/code&gt;して&lt;code&gt;start&lt;/code&gt;するだけで、配列の順番にハイライトを移動しながらメッセージを表示してくれるというわけ。これでできたのが最初に貼ったデモだ。&lt;/p&gt;
&lt;p&gt;凝ったことをするには足りないが、ちょっとした説明を入れたいという場合には重宝しそう。&lt;/p&gt;
&lt;p&gt;なお、普通に実装すると毎回表示されていまいユーザーにとっては鬱陶しいものとなるので、初回だけ表示するなどのを工夫を自分で実装しなければいけない。&lt;code&gt;NSUserDefaults&lt;/code&gt;などを使えば大した手間ではないからいいけど、そこまで気が利いてるといいよねー。&lt;/p&gt;</description></item><item><title>Vagrantアップデート後のvagrant upでエラー</title><link>https://blog.piyo.tech/posts/2014-06-14-193000/</link><pubDate>Sat, 14 Jun 2014 19:30:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-14-193000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/438a59de-25c9-461f-b9f1-672ca1060477/bd72e2c40b67db9fd5eb65e3c500ee6a/deep/0/Vagrant-Cloud.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;先日1年以上ぶりにVagrantに触れた。これを書いて以来かな？&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-04-16-150000"&gt;Chef Solo入門のまとめ - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;さすがにバージョンが古くなっているだろうということで公式サイトからツールをダウンロードして更新した。&lt;/p&gt;
&lt;p&gt;その後ドキュメントに従って、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% vagrant init hashicorp/precise64
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;でVagrantfileを生成し、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% vagrant up
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;で仮想マシンを立ち上げようとしたところで次のようなエラーが起きた。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;undefined method `distro_dispatch&amp;#39; vagrant up
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Vagrantは作業ディレクトリとして&lt;code&gt;$(HOME)/.vagrant.d&lt;/code&gt;を使うらしい。このディレクトリに以前のバージョンのVagrantが使っていたものが色々残っていて、そのうちの何かが影響していて上のエラーを起こしていたらしい。&lt;/p&gt;
&lt;p&gt;以前のバージョンのときの作業内容などは全て消えてもよかったので、&lt;code&gt;$(HOME)/.vagrant.d&lt;/code&gt;を削除したら&lt;code&gt;vagrant up&lt;/code&gt;できるようになった。よかった。&lt;/p&gt;</description></item><item><title>iOS端末に紐付けたIDでログインするアプリの実装アイデア</title><link>https://blog.piyo.tech/posts/2014-06-13-200000/</link><pubDate>Fri, 13 Jun 2014 20:00:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-13-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/a736de95-65e2-40cc-84f0-978f368d0cee/64e8ba5a356935c49e2c23d3292f6572/deep/0/Parse.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;iOSのアプリでサーバーサイドと連携するにも関わらず明示的なユーザー登録を必要としないアプリがある。例えばnanapiのアンサーなどがそれにあたる。&lt;/p&gt;
&lt;p&gt;ひとつ端末でしか使わないという世界観でアプリを作ればユーザーに明示的にログインさせる必要はないのでユーザー体験もよくなる。&lt;/p&gt;
&lt;p&gt;そのようなアプリケーションを実装するときの1アイデアを試してみたのでここに書き残しておく。&lt;/p&gt;
&lt;h1 id="端末固有のid"&gt;端末固有のID&lt;/h1&gt;
&lt;p&gt;ユーザーを特定するためには固有のIDが必要になる。しかし、端末固有のUDIDはiOS6から使えなくなったし、本当にハードウェア固有のIDを使ってしまうと端末を変更したときの移行処理がややこしくなってしまう気がする。&lt;/p&gt;
&lt;p&gt;なお、固有識別子の話はこちらに詳しい。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://quesera2.hatenablog.jp/entry/2014/03/03/001232"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://quesera2.hatenablog.jp/entry/2014/03/03/001232" alt="iOSでの端末固有識別子の話。 - なるようになるといいね" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://quesera2.hatenablog.jp/entry/2014/03/03/001232"&gt;iOSでの端末固有識別子の話。 - なるようになるといいね&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://quesera2.hatenablog.jp/entry/2014/03/03/001232" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://quesera2.hatenablog.jp/entry/2014/03/03/001232" alt="はてなブックマーク - iOSでの端末固有識別子の話。 - なるようになるといいね" title="はてなブックマーク - iOSでの端末固有識別子の話。 - なるようになるといいね" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;↑の投稿にもあるように、UUIDを使うのがいい気がする。初回起動時の自動ユーザー登録の際にUUIDを発行して何らかの形で保存。次回以降の起動したときは保存しておいたUUIDでログイン、といった流れになる。&lt;/p&gt;
&lt;h1 id="keychain"&gt;Keychain&lt;/h1&gt;
&lt;p&gt;では生成したUUIDはどこに保存するのがよいか。すぐに思い浮かぶのは&lt;code&gt;NSUserDefaults&lt;/code&gt;だが、これでは2つ問題がある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;セキュリティ面で問題がある（かもしれない）&lt;/li&gt;
&lt;li&gt;データが永続化できない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;1つ目はパスワードなどの機密情報を平文で保存することになるので望ましくないという、まあよくある話だし重要な点。&lt;/p&gt;
&lt;p&gt;2つ目はデータの永続化。&lt;code&gt;NSUserDefaults&lt;/code&gt;はアプリをアンインストールしたときに一緒に消えてしまうため、再インストールしたときにその情報は消えてしまう。こうなってしまうと、これまでと同じユーザーとしてログインすることはできなくなってしまう。&lt;/p&gt;
&lt;p&gt;Keychainがこれらの問題を解決してくれる。セキュリティ的にも良いし、アプリが消えてもデータを残せる。Keychainについてはこちらが詳しい。が、、、&lt;/p&gt;
&lt;p&gt;&lt;a href="http://cocoadays.blogspot.jp/2011/02/ios-keychain-services.html"&gt;Cocoaの日々: [iOS] Keychain Services とは&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;いかんせんCベースの生APIを叩くのは骨が折れる。幸い、ラッパーライブラリがいくつかあるのでそれを使えば良い。見た中では&lt;code&gt;NSUserDefaults&lt;/code&gt;ライクにこれが一番よさそうかな。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://d.hatena.ne.jp/KishikawaKatsumi/20111120/1321773263"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://d.hatena.ne.jp/KishikawaKatsumi/20111120/1321773263" alt="KeyChain のデータを操作するラッパークラス UICKeyChainStore を書きました。 - 24/7 twenty-four seven" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://d.hatena.ne.jp/KishikawaKatsumi/20111120/1321773263"&gt;KeyChain のデータを操作するラッパークラス UICKeyChainStore を書きました。 - 24/7 twenty-four seven&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/KishikawaKatsumi/20111120/1321773263" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/KishikawaKatsumi/20111120/1321773263" alt="はてなブックマーク - KeyChain のデータを操作するラッパークラス UICKeyChainStore を書きました。 - 24/7 twenty-four seven" title="はてなブックマーク - KeyChain のデータを操作するラッパークラス UICKeyChainStore を書きました。 - 24/7 twenty-four seven" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h1 id="サンプル"&gt;サンプル&lt;/h1&gt;
&lt;p&gt;ユーザー管理にはParse.comを使ってみることにした。データストアの検証も兼ねてね。Parse.com自体のユーザー登録やセットアップについては割愛するし、サンプルなのでネットワークがないなどのエラー処理は書いていない。省エネ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AppDelegate.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;#34;User.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;Parse/Parse.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@implementation&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AppDelegate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;application:&lt;/span&gt;(UIApplication &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)application &lt;span style="color:#a6e22e"&gt;didFinishLaunchingWithOptions:&lt;/span&gt;(NSDictionary &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)launchOptions
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Override point for customization after application launch.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; [Parse setApplicationId:&lt;span style="color:#e6db74"&gt;@&amp;#34;YOUR_ID&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; clientKey:&lt;span style="color:#e6db74"&gt;@&amp;#34;YOUR_KEY&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; [PFAnalytics trackAppOpenedWithLaunchOptions:launchOptions];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; [User signIn]; &lt;span style="color:#75715e"&gt;// ← これ！！！
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; YES;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;起動時に&lt;code&gt;[User signIn]&lt;/code&gt;とやらを呼んでいて、この&lt;code&gt;User&lt;/code&gt;クラスは自前のクラスとなっている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// User.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;#34;User.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;Parse/Parse.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;UICKeyChainStore.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;kKeyForName &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;UserName&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;kKeyForPassword &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;UserPassword&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@implementation&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;User&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;+ (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;signUp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; PFUser &lt;span style="color:#f92672"&gt;*&lt;/span&gt;user &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [PFUser user];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; user.username &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[NSUUID UUID] UUIDString];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; user.password &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[NSUUID UUID] UUIDString];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; [user signUpInBackgroundWithBlock:&lt;span style="color:#f92672"&gt;^&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt; succeeded, NSError &lt;span style="color:#f92672"&gt;*&lt;/span&gt;error) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;error) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; [UICKeyChainStore setString:user.username forKey:kKeyForName];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; [UICKeyChainStore setString:user.password forKey:kKeyForPassword];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; }];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;+ (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;signIn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;userName &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [UICKeyChainStore stringForKey:kKeyForName];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;userPassword &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [UICKeyChainStore stringForKey:kKeyForPassword];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(userName &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; userPassword){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; [PFUser logInWithUsernameInBackground:userName password:userPassword];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; }&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; [self signUp];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;signIn&lt;/code&gt;ではKeychainに値を取りに行き、ユーザー名とパスワードがあればその値を使って&lt;code&gt;PFUser&lt;/code&gt;を作ってログインし、なければ&lt;code&gt;signUp&lt;/code&gt;を呼ぶ。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;signUp&lt;/code&gt;では&lt;code&gt;[[NSUUID UUID] UUIDString]&lt;/code&gt;でユーザー名とパスワードを生成、サインアップが成功したらKeychainに値を保存しておく、という流れになる。&lt;/p&gt;
&lt;p&gt;このような方法を取ることで、起動した時点でユーザー登録が完了してログインした状態にできるし、アプリを一旦削除しても入れなおせば再び使い始められるアプリができた。&lt;/p&gt;
&lt;p&gt;実装の仕方はこれだけではないかもしれないけれど、まあまあの線じゃないかなと個人的には思っている。&lt;/p&gt;
&lt;p&gt;あとは機種変更時の移行を実現できれば、スマートフォンのみを使ったログインなしで使えるサービスにできそうだ。&lt;/p&gt;</description></item><item><title>Objective-Cの定数を1ファイルにまとめる</title><link>https://blog.piyo.tech/posts/2014-06-12-200000/</link><pubDate>Thu, 12 Jun 2014 20:00:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-12-200000/</guid><description>&lt;p&gt;Objective-Cがオワコン化する前にちょっとためになるかもしれないやつを書いておく。&lt;/p&gt;
&lt;p&gt;iOSアプリ内で使う定数を1ファイルでまとめて管理するいい方法がないかを調べたときにどこかで見つけたもので、マクロの有無で宣言と定義を分けるという方法があった。&lt;/p&gt;
&lt;p&gt;この方法を使うことで変数宣言と定義を1ファイルにまとめることができるようになった。変更箇所が一箇所で済むので少し便利になる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Constants.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#undef _EXTERN
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#undef _INITIALIZE_AS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#ifdef XOYIP_DEFINE_GLOBALS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define _EXTERN
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define _INITIALIZE_AS(x) =x
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#else
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#if defined(__cplusplus)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define _EXTERN extern &amp;#34;C&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#else
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define _EXTERN extern
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define _INITIALIZE_AS(x)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;_EXTERN NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; kAccessToken &lt;span style="color:#a6e22e"&gt;_INITIALIZE_AS&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;@&amp;#34;YOUR_ACCESS_TOKEN&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;_EXTERN NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;_EXTERN NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Constants.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define XOYIP_DEFINE_GLOBALS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;#34;Constant.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Railsでモデルの一覧を取ってくる</title><link>https://blog.piyo.tech/posts/2014-06-11-200000/</link><pubDate>Wed, 11 Jun 2014 20:00:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-11-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c8beeb36-3895-4492-b910-e9a4417654b7/3b5bbe1ab3190583c6d16adc5be9c635/deep/0/rails1.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;アプリケーションの中にあるModelのレコードを数を調べたかったので、それをプログラムから動的に行う方法を考えてみた。&lt;/p&gt;
&lt;p&gt;ActiveRecord::Baseのサブクラスを取ってくればいいはずだ！ということで、&lt;code&gt;ActiveRecord::Base.subclasses&lt;/code&gt;を使うことにした。確認には&lt;code&gt;rails console&lt;/code&gt;を使った。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% rails c
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;ActiveRLoading development environment &lt;span style="color:#f92672"&gt;(&lt;/span&gt;Rails 4.1.0&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;Frame number: 0/5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&amp;gt; ActiveRecord::Base.subclasses
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;User &lt;span style="color:#f92672"&gt;(&lt;/span&gt;call &lt;span style="color:#e6db74"&gt;&amp;#39;User.connection&amp;#39;&lt;/span&gt; to establish a connection&lt;span style="color:#f92672"&gt;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;2&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;User&lt;/code&gt;というModelが取れたことはわかる。でも実はこのアプリケーションには他にもモデルがあるはずなのに、この方法では取れてこないようだ。&lt;/p&gt;
&lt;p&gt;Railsのdevelopment環境ではデフォルトでModelがキャッシュされないようになっている（当たり前だよね、毎回新しく読みなおすようになっていないと変更が即座に反映されないから）。そのためか、最初に呼び出すまでObjectSpaceに存在しないらしく、&lt;code&gt;subclasses&lt;/code&gt;メソッドでも取れてこないようだ。&lt;/p&gt;
&lt;p&gt;というわけで、強制的にロードしてやる！&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Dir&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;glob(&lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(&lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;root, &lt;span style="color:#e6db74"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;models&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;**&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;*.rb&amp;#34;&lt;/span&gt;))&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each {&lt;span style="color:#f92672"&gt;|&lt;/span&gt;f&lt;span style="color:#f92672"&gt;|&lt;/span&gt; require f}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;subclasses
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# =&amp;gt; [User (...), Hoge, Piyo] という感じで得られる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;レコード数を調べるとしたらコレでOK。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Dir&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;glob(&lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(&lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;root, &lt;span style="color:#e6db74"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;models&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;**&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;*.rb&amp;#34;&lt;/span&gt;))&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each {&lt;span style="color:#f92672"&gt;|&lt;/span&gt;f&lt;span style="color:#f92672"&gt;|&lt;/span&gt; require f}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;subclasses&lt;span style="color:#f92672"&gt;.&lt;/span&gt;map(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:count&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;inject(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:+&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# =&amp;gt; 1024 などなど&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;production環境では予めModelもロードされているので2行目のコードだけで調べられるはず。&lt;/p&gt;</description></item><item><title>MPMoviePlayerViewControllerが再生完了時に勝手に閉じて困る</title><link>https://blog.piyo.tech/posts/2014-06-09-203000/</link><pubDate>Mon, 09 Jun 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-09-203000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/4544f3ad-325b-4214-ac6b-f2b075ee2133/b49fb60373e925de5dce3bb7bd2aead4/deep/0/url.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;iOSには動画再生用に&lt;code&gt;MPMovierPlayerViewController&lt;/code&gt;っていうクラスがあって、URLを渡して表示するだけでめちゃくちゃ簡単に動画再生機能を実装できる。すごく便利。&lt;/p&gt;
&lt;p&gt;その分自由度が低くてちょっとした挙動を変えるのが大変だったりする。&lt;/p&gt;
&lt;p&gt;まず、普通に動画を再生するならこういう風に実装する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;playVideo:&lt;/span&gt;(NSURL&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)url
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; MPMoviePlayerViewController &lt;span style="color:#f92672"&gt;*&lt;/span&gt;vc &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[MPMoviePlayerViewController alloc] initWithContentURL:url];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; [self presentViewController:vc animated:YES completion:nil];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これだけのコードで再生できるから結構驚き。&lt;/p&gt;
&lt;p&gt;ところで、この方法では再生完了時に&lt;code&gt;MPMoviePlayerViewController&lt;/code&gt;が勝手に閉じられてしまう。再生が終わったらそのまま待つのがいいんじゃないの、と個人的には思ったため回避方法を探すことにした。&lt;/p&gt;
&lt;p&gt;どうやら内部では&lt;code&gt;NSNotificationCenter&lt;/code&gt;を用いて動画終了時に通知を出し、その通知を受け取ったら閉じるというセレクタを呼んでいるらしい。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://josebolanos.wordpress.com/2011/09/28/dismissing-mpmovieplayerviewcontroller-the-right-way/"&gt;Dismissing MPMoviePlayerViewController the right way | I&amp;rsquo;m the one who codes!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;勝手に閉じないようにするにはプレーヤーの表示前に&lt;code&gt;NSNotificationCenter&lt;/code&gt;から関連するものを削除してあげればよい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;playVideo:&lt;/span&gt;(NSURL&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)url
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; MPMoviePlayerViewController &lt;span style="color:#f92672"&gt;*&lt;/span&gt;vc &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[MPMoviePlayerViewController alloc] initWithContentURL:url];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; [[NSNotificationCenter defaultCenter] removeObserver:vc
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; name:MPMoviePlayerPlaybackDidFinishNotification
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; object:vc.moviePlayer];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; [self presentViewController:vc animated:YES completion:nil];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでOKと思いきやそうもいかない。なんと&lt;code&gt;MPMoviePlayerViewController&lt;/code&gt;がデフォルトで用意しているcloseボタンまで効かなくなってしまう。もちろんこんな挙動は困る。&lt;/p&gt;
&lt;p&gt;回避するには、さっき削除した&lt;code&gt;MPMoviePlayerPlaybackDidFinishNotification&lt;/code&gt;に対応するセレクタを自前で定義し、ユーザーがボタンを操作したときには閉じるという処理にしておけばいい。&lt;/p&gt;
&lt;p&gt;最終的なコードは次のようになる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;playVideo:&lt;/span&gt;(NSURL&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)url
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; MPMoviePlayerViewController &lt;span style="color:#f92672"&gt;*&lt;/span&gt;vc &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[MPMoviePlayerViewController alloc] initWithContentURL:url];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; [[NSNotificationCenter defaultCenter] removeObserver:vc
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; name:MPMoviePlayerPlaybackDidFinishNotification
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; object:vc.moviePlayer];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; [[NSNotificationCenter defaultCenter] addObserver:self
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; selector:&lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(videoFinished:)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; name:MPMoviePlayerPlaybackDidFinishNotification
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; object:vc.moviePlayer];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; [self presentViewController:vc animated:YES completion:nil];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)videoFinished:(NSNotification&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)notification{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; value &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[notification.userInfo valueForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (value &lt;span style="color:#f92672"&gt;==&lt;/span&gt; MPMovieFinishReasonUserExited) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; [self dismissMoviePlayerViewControllerAnimated];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>UICollectionViewControllerでの3列、4列のグリッド表示</title><link>https://blog.piyo.tech/posts/2014-06-08-200000/</link><pubDate>Sun, 08 Jun 2014 20:00:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-08-200000/</guid><description>&lt;p&gt;UICollectionViewControllerを使ったグリッド表示がいい感じになるようパラメータを手探りで調整したのでその結果をメモしておこうと思う。&lt;/p&gt;
&lt;h1 id="まずは結果から"&gt;まずは結果から&lt;/h1&gt;
&lt;h2 id="3列"&gt;3列&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/1b2abc69-34a3-4c98-98b1-48bfaf31f880/4169b87be55a0a647da8b3593068ef0c/deep/0/3col.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="4列"&gt;4列&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/474f9147-d40b-44a0-9bd2-09dea093d967/e4b474dd13db395b4023c0e75ae1f4a2/deep/0/4col.png" alt=""&gt;&lt;/p&gt;
&lt;h1 id="パラメータ"&gt;パラメータ&lt;/h1&gt;
&lt;h2 id="3列-1"&gt;3列&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c2a9315f-0d0e-4669-bc0a-edbf7bb1bd1e/8b01a50b9f53a9b870ccb451f6460df9/deep/0/PressToRecord---Main.storyboard.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="4列-1"&gt;4列&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9543b469-901d-49f2-a913-96ace8d25913/4e7c22ae2286405e40c1671f2e42377b/deep/0/PressToRecord---Main.storyboard.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>iOS7時代のステータスバー非表示方法</title><link>https://blog.piyo.tech/posts/2014-06-07-190000/</link><pubDate>Sat, 07 Jun 2014 19:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-07-190000/</guid><description>&lt;p&gt;このあたりの処理はやり方がコロコロ変わるようなので検索しても情報が古くて困る。2014/06/07時点、Xcode5.1.1、iOS7.1 SDK時点での情報を書いておく。&lt;/p&gt;
&lt;p&gt;正解はステータスバーを表示したくないViewControllerで&lt;code&gt;prefersStatusBarHidden&lt;/code&gt;をオーバーライドする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;prefersStatusBarHidden&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; YES;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで非表示になる。やったね！&lt;/p&gt;</description></item><item><title>Obj-Cで非同期処理の完了を待ちたいならブロック渡してコールバックだよね</title><link>https://blog.piyo.tech/posts/2014-06-06-200000/</link><pubDate>Fri, 06 Jun 2014 20:00:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-06-200000/</guid><description>&lt;p&gt;Swiftは出たけどまだまだObjective-Cはオワコンってことにはならないと思うからObjective-Cの話を。&lt;/p&gt;
&lt;p&gt;Objective-Cで非同期処理をしてその結果を受けてなんかしたい、ってときが結構あるんだけど待ち方がいまいちよくわからなかったことがあった。今思えば基本的なやり方だけどちゃんと残しておこう。&lt;/p&gt;
&lt;p&gt;ちなみにテストなら前に書いたこれでよさそう。アプリケーションコードでやるとスレッド周りで整合性取れなくなるのか正しく動かなかった。それ以上は踏み込んで調べてはいない。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-05-01-191106"&gt;Objective-Cで非同期処理のテスト（依存ライブラリなし版） - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;でもよく考えたら非同期処理が終わったことを同期的に知りたいというケースは実はそんなに無い気がしてきたので、最初の非同期処理が終わったあとにやりたい処理も非同期にしてしまえばいい。つまりブロック渡してコールバック。&lt;/p&gt;
&lt;p&gt;例として&lt;code&gt;ALAssetsLibrary&lt;/code&gt;を使うケースを考える。&lt;code&gt;ALAssetsLibrary&lt;/code&gt;を使うクラスは自前のクラスにラップして使うとする。仮に名前を&lt;code&gt;AssetsManager&lt;/code&gt;とかなんとかいう名前にし、&lt;code&gt;load&lt;/code&gt;という読み出し用のメソッドがあるとする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AssetsManager.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;load&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;- (UIImage&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;latestImage&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;+ (AssetsManager&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;defaultManager&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// Singleton
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AssetsManager.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;load&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; _assets &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSMutableArray new];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; _assetsLibrary &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [ALAssetsLibrary new];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; [_assetsLibrary enumerateGroupsWithTypes:ALAssetsSavedPhotos usingBlock:&lt;span style="color:#f92672"&gt;^&lt;/span&gt;(ALAssetsGroup &lt;span style="color:#f92672"&gt;*&lt;/span&gt;group, &lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;stop) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// do something with group
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; } failureBlock:&lt;span style="color:#f92672"&gt;^&lt;/span&gt;(NSError &lt;span style="color:#f92672"&gt;*&lt;/span&gt;error) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この&lt;code&gt;load&lt;/code&gt;を&lt;code&gt;ViewController.m&lt;/code&gt;をから呼び出し、完了後にUIImageViewを更新するみたいな流れを考える。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ViewController.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;updateImage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; [[AssetsManager defaultManager] load];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; self.imageView.image &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [AssetsManager defaultManager] latestImage];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ところがこれでは&lt;code&gt;enumerateGroupsWithTypes&lt;/code&gt;メソッドの呼び出し後すぐに画像更新の行に到達してしまうためうまくいかない。想定通りの挙動にするためには&lt;code&gt;enumerateGroupsWithTypes&lt;/code&gt;が本当に終わったということを知る必要があるが、終わるのを待つよりもスマートな方法は完了時の処理をブロックで渡してやることになる。&lt;/p&gt;
&lt;p&gt;コードで書くとこうなる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AssetsManager.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;void&lt;/span&gt; (&lt;span style="color:#f92672"&gt;^&lt;/span&gt;CompletionBlock)(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;loadWithCompletionBlock:&lt;/span&gt;(CompletionBlock)block; &lt;span style="color:#75715e"&gt;// 引数としてブロックを渡す
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;- (UIImage&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;latestImage&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;+ (AssetsManager&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;defaultManager&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// Singleton
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AssetsManager.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;loadWithCompletionBlock:&lt;/span&gt;(CompletionBlock)block
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; _assets &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSMutableArray new];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; _assetsLibrary &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [ALAssetsLibrary new];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; [_assetsLibrary enumerateGroupsWithTypes:ALAssetsSavedPhotos usingBlock:&lt;span style="color:#f92672"&gt;^&lt;/span&gt;(ALAssetsGroup &lt;span style="color:#f92672"&gt;*&lt;/span&gt;group, &lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;stop) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// do something with group
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; block(); &lt;span style="color:#75715e"&gt;// ←この行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; } failureBlock:&lt;span style="color:#f92672"&gt;^&lt;/span&gt;(NSError &lt;span style="color:#f92672"&gt;*&lt;/span&gt;error) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; }];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そしてこの新しくなった&lt;code&gt;load&lt;/code&gt;を使う側はこうなる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ViewController.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;updateImage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; [[AssetsManager defaultManager] loadWithCompletionBlock:&lt;span style="color:#f92672"&gt;^&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; self.imageView.image &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [AssetsManager defaultManager] latestImage];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; }];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでうまくいく。&lt;/p&gt;</description></item><item><title>past the lifetime of its owning ALAssetsLibrary</title><link>https://blog.piyo.tech/posts/2014-06-05-200000/</link><pubDate>Thu, 05 Jun 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-05-200000/</guid><description>&lt;p&gt;&lt;code&gt;ALAssetsLibary&lt;/code&gt;で取得した&lt;code&gt;ALAssets*&lt;/code&gt;のオブジェクトを使おうとするとこんなエラーメッセージが出ることがある。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;invalid attempt to access &amp;lt;ALAssetPrivate: 0x16eb5630&amp;gt; past the lifetime of its owning ALAssetsLibrary
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;起動時にALAssetを読み込んでおき、あとで使うために&lt;code&gt;NSMutableArray&lt;/code&gt;か何かで保持しておくとする。そのとき例えばこういうコードを書く。すると↑のようなエラーが出て写真などの情報を取ってこれないという事態になる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;loadAssets&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; _assets &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSMutableArray new];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; ALAssetsLibrary &lt;span style="color:#f92672"&gt;*&lt;/span&gt;assetsLibrary &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[ALAssetsLibrary alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:&lt;span style="color:#f92672"&gt;^&lt;/span&gt;(ALAssetsGroup &lt;span style="color:#f92672"&gt;*&lt;/span&gt;group, &lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;stop) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;group) &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:&lt;span style="color:#f92672"&gt;^&lt;/span&gt;(ALAsset &lt;span style="color:#f92672"&gt;*&lt;/span&gt;result, NSUInteger index, &lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;stop) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; [self.assets addObject:result];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; } failureBlock:nil];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;どうやらこのエラーは使おうとしている&lt;code&gt;ALAssets*&lt;/code&gt;を返してくれた&lt;code&gt;ALAssetsLibrary&lt;/code&gt;が既にいなくなっているというような意味合いらしい。先ほどのコードでは&lt;code&gt;ALAssetsLibrary&lt;/code&gt;がメソッドのローカルスコープにあり、そのスコープ外では&lt;code&gt;ALAssets*&lt;/code&gt;を使えないようだ。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ALAssetsLibrary&lt;/code&gt;をプロパティとして持つことでこの問題は回避できる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ViewController&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;strong&lt;/span&gt;) ALAssetsLibrary &lt;span style="color:#f92672"&gt;*&lt;/span&gt;assetsLibrary;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)loadAssets {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; _assets &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSMutableArray new];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; _assetsLibrary &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[ALAssetsLibrary alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 略
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>SwiftからObjective-Cを呼ぶ方法。CocoaPodsも。</title><link>https://blog.piyo.tech/posts/2014-06-04-200000/</link><pubDate>Wed, 04 Jun 2014 07:10:52 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-04-200000/</guid><description>&lt;p&gt;SwiftとObjective-Cは相互に呼び合えるらしい。Objective-CからSwiftはすでに記事があった。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qiita.com/moriturus/items/47e7cdaa7cc858c5fe23"&gt;SwiftのコードをObjective-Cから呼んでみた - Qiita&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;もしSwiftからObjective-Cのコードを呼べるのであれば、大抵のCocoaPodsライブラリは使い回せることになるので開発者としては大変嬉しい。せっかくなので検証にもCocoaPodsで入れたライブラリを使ってみることにした。&lt;/p&gt;
&lt;h2 id="swiftのプロジェクトを作る"&gt;Swiftのプロジェクトを作る&lt;/h2&gt;
&lt;p&gt;普通に新規作成→Swiftを選んでプロジェクトを作る。なんでもいいのでSingle View Applicationあたりにしておく。&lt;/p&gt;
&lt;h2 id="cocoapodsでライブラリを入れる"&gt;CocoaPodsでライブラリを入れる。&lt;/h2&gt;
&lt;p&gt;今回は&lt;code&gt;SVProgressHUD&lt;/code&gt;を使うことにした。独立しているので簡単に呼び出したりしやすい。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/samvermette/SVProgressHUD"&gt;samvermette/SVProgressHUD&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;インストールプロセスは特に変わらない。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;SVProgressHUD&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% pod install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;インストール後は&lt;code&gt;xcworkspace&lt;/code&gt;を開くのも一緒。&lt;/p&gt;
&lt;h2 id="bridging-headerを作る"&gt;Bridging-Headerを作る&lt;/h2&gt;
&lt;p&gt;Swiftで使いたいコードのヘッダーをインポートしておくためのBriding-Headerというものを作っておく必要がある。&lt;/p&gt;
&lt;p&gt;このBriding-Headerを作るには単にヘッダーファイルを自分で持ってくるだけではどうやらいけないらしい（このあたりの仕様はまだよくわかっていません）のでXcodeに生成させる。&lt;/p&gt;
&lt;p&gt;New Fileメニューから&lt;code&gt;Cocoa Class&lt;/code&gt;を選び、言語をObjective-Cにしてクラスを生成する。&lt;/p&gt;
&lt;p&gt;途中でbridging header作る？って聞かれるから&lt;code&gt;YES&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/a09ccf73-1465-4387-b973-a51a3a2c8207/52cea54f6b83496d694abca4e86a5823/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-06-03-13-13.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;すると、こういうファイルがクラスファイルと一緒にできる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/a836803d-7192-446d-9fba-e2d899afd805/691ad6b1a4ebdc6fe62a0c113e02d503/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-06-03-13-13.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;このファイルに次の一行を追加する。また、生成されたクラスは今回は不要なので削除してしまう。自前のObjective-Cクラスを追加するときなんかはそのまま使えばいい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;SVProgressHUD.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでSwiftから呼ぶ準備が整った。&lt;/p&gt;
&lt;h2 id="swiftから呼び出す"&gt;Swiftから呼び出す&lt;/h2&gt;
&lt;p&gt;ボタンを押してプログレスの表示を切り替えるという何の実用性もないサンプルアプリケーションを考える。&lt;/p&gt;
&lt;p&gt;スタートボタンとストップボタンと&lt;code&gt;ViewController.swift&lt;/code&gt;ファイルをStoryboardから紐付けておき、それらのアクションの中でSVProgressHUDを呼び出す。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBAction&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;(sender : AnyObject) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; SVProgressHUD.showWithStatus(&lt;span style="color:#e6db74"&gt;&amp;#34;loading...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBAction&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stop&lt;/span&gt;(sender : AnyObject) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; SVProgressHUD.dismiss()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;SVProgressHUDのメソッドを直接呼ぶことができ、きちんと動作した。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/38c0290b-f295-4194-9115-73250a05cb6b/4bc364e319297da34f29daa013b4e847/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-06-03-13-47.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>Xcode 6 beta 入れた</title><link>https://blog.piyo.tech/posts/2014-06-03-065140/</link><pubDate>Tue, 03 Jun 2014 06:51:40 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-03-065140/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/225108a5-f17c-42a9-a9b6-63bd91e8ab35/f32c0149729e84f3af0383d3b638328b/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-06-03-5-43.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;公開されたbeta版をインストールして触ってみた。WWDCの基調講演は見ていないし、ちゃんとしたドキュメントも読んでおらず、Swiftってのが使えるようになるんだー程度の認識しかない状態で触ってみて気づいたことを書いていく。&lt;/p&gt;
&lt;h1 id="playground"&gt;playground&lt;/h1&gt;
&lt;p&gt;起動するといきなり見慣れないplaygroundというものが目につく。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b3b614a8-1943-4901-86e0-161967319713/e382b43ed696218e73ee8ff55be01f33/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-06-03-5-59.png" alt=""&gt; 
起動するといきなりエディタが開く。SwiftのiBookを参考にしながら適当にサンプルコードを打っていくと評価結果がウィンドウ右側のカラムにあらわれるという感じらしい。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/f74f306b-079a-40db-a174-a80c8768758b/abc23a6ee621f9afc13a5a7f7126d523/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-06-03-6-13.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ちなみにSwiftのiBookはこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://itunes.apple.com/gb/book/swift-programming-language/id881256329?mt=11"&gt;iTunes - Books - The Swift Programming Language by Apple Inc.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Swiftでちょっと試したいコードを動かせる場所という認識でいいのか。iBookを進める環境としては良さそう。&lt;/p&gt;
&lt;h1 id="storyboard"&gt;storyboard&lt;/h1&gt;
&lt;p&gt;なんか雰囲気が違う。&lt;/p&gt;
&lt;p&gt;このスクリーンショットはiPhoneアプリケーション用のstoryboardだけど、置いてあるViewControllerの画面がこれまでの長方形じゃない。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/eb1b4052-a49a-49b4-b117-aa425e8e6233/01e3d96d4cdaa4f09212d67cef12a254/deep/0/SwiftExample---Main.storyboard---Edited.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;そして、画面下にはこんな表示が。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/f37806e9-dc08-4059-b0af-eab55365a572/8f334f36a36f652e131169804139a95f/deep/0/SwiftExample---Main.storyboard---Edited.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;右側にあるのはXcode5までと同様AutoLayoutだけど、真ん中に&lt;code&gt;w Any h Any&lt;/code&gt;との表示が。どんなレイアウトにも対応できる相対レイアウトで作るのが基本になった、というような感じに見て取れる（予想）。&lt;/p&gt;
&lt;p&gt;とりあえずスクリーンショットのような状態でiPhoneシミュレータを起動したらこうなった。多分配置の指定が絶対値になっているからだと思う。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/330b9cc5-20bb-4153-bcde-3fe9e54b6207/c6e9053fa2a1213853172fb744123dc6/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-06-03-6-27.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ラベルとボタンとにちゃんとHorizontal Centerの条件をつけたら大丈夫だった。やはりConstraintsをしっかり使っていく必要がありそう。&lt;/p&gt;
&lt;h1 id="swift"&gt;Swift&lt;/h1&gt;
&lt;p&gt;新言語Swiftが今回のWWDCの一番の目玉だと思う。Objective-Cより軽量な言語でアプリケーションを書けるようになるというわけ。&lt;/p&gt;
&lt;p&gt;プロジェクトを新規作成を選ぶと今まではなかった言語の選択肢があるのがわかる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/2d516042-74f3-425c-ab4a-c02e273aad51/7ff3b31969ac7581ca5fda14ab9a26eb/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-06-03-6-15.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ファイル構成はこんな感じ。&lt;code&gt;.h&lt;/code&gt;、&lt;code&gt;.m&lt;/code&gt;が&lt;code&gt;.swift&lt;/code&gt;1つに置き換わったような感じ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/13e8e248-d042-410d-b0ef-1bce31114f57/178e1f6ef3ea00e19afef020cf19439b/deep/0/SwiftExample.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;storyboardとコードの連携はSwiftでも使えるようだ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/72921924-9c32-485a-b1d5-3d50ac68a08c/4625c07947392d70c38a84ad6a031361/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-06-03-6-34.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;例えば、↑のstoryboardのサンプルで「ボタンを押したらUILabelのテキストを変更する」という機能を持つViewControllerのコードは以下のようになる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UIKit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ViewController&lt;/span&gt;: UIViewController {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBOutlet&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; sampleLabel : UILabel
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@IBAction&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;buttonTapped&lt;/span&gt;(sender : AnyObject) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; sampleLabel.text = &lt;span style="color:#e6db74"&gt;&amp;#34;button tapped&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.viewDidLoad()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Do any additional setup after loading the view, typically from a nib.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;didReceiveMemoryWarning&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.didReceiveMemoryWarning()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Dispose of any resources that can be recreated.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;（あ、シンタックスハイライトってどうなるんだ。はてなブログさんの対応に期待）&lt;/p&gt;
&lt;p&gt;Objective-Cと比べるとシンタックスが違うだけでやっていることは同じように見える。ここだけ見るとSwiftを使うメリットはあまりないような気がする。この点についてはドキュメントを全て読んだわけではないし、もっと複雑なアプリケーションを書くときに違いが出てくるかもしれないからまだ断言はできない。&lt;/p&gt;
&lt;p&gt;少なくともObjective-CやC系の言語に馴染めないという人にとっての心理的な抵抗は減るんじゃないかな。&lt;/p&gt;
&lt;h1 id="view-debugging"&gt;View Debugging&lt;/h1&gt;
&lt;p&gt;View Debuggingという機能が追加された。実行時の見た目を簡単にデバッグするという話らしい。&lt;/p&gt;
&lt;p&gt;サンプルアプリケーション程度のものだと有り難みがわからないが、パッと見ではViewのサイズやConstraints、対応するコードへのジャンプができるようだ。&lt;/p&gt;
&lt;p&gt;ChromeのWeb Inspectorあたりに似ている感じがしたが、実際はどうだろうか。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/dd0a8d30-a164-416d-aff8-ec4cd8dbde4c/ed14b7b7c15a8f5566ddd589cd742fcb/deep/0/SwiftExample.png" alt=""&gt;&lt;/p&gt;
&lt;h1 id="関連リンク"&gt;関連リンク&lt;/h1&gt;
&lt;p&gt;使っていかないと感触がわからないことが多すぎてはっきりとしたことは書けないというオチ。ごめんなさい。&lt;/p&gt;
&lt;p&gt;公式のリリースノートはこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://developer.apple.com/library/prerelease/ios/documentation/DeveloperTools/Conceptual/WhatsNewXcode/00-Introduction/Introduction.html"&gt;What&amp;rsquo;s New in Xcode: What’s New in Xcode&lt;/a&gt;&lt;/p&gt;</description></item><item><title>PDFの余白を切り取るpdfscissorsが便利</title><link>https://blog.piyo.tech/posts/2014-06-02-190000/</link><pubDate>Mon, 02 Jun 2014 19:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-02-190000/</guid><description>&lt;p&gt;余白がたくさんあるPDFを印刷すると余白ばかり大きくてメインのコンテンツ部分が小さくなってしまいとても残念なことになる。そういうときはpdfcissorsというソフトで余白をカットしてしまえばいい。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/cea22a33-cb86-4181-84ec-de012d9b533e/4941319c57ca1b727a250625f3dfe029/deep/0/pdfscissors.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sites.google.com/site/pdfscissors/"&gt;pdfscissors&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;JavaアプリケーションなのでJavaが必要だったりUIがダサかったりするが仕方ない。&lt;/p&gt;
&lt;p&gt;今回切り取りに使ったのはAppleのiPhoneユーザーガイド。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://manuals.info.apple.com/MANUALS/1000/MA1565/ja_JP/iphone_user_guide_j.pdf"&gt;PDFです→iphone_user_guide_j.pdf&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="手順"&gt;手順&lt;/h1&gt;
&lt;p&gt;pdfscissorsを起動したらウィンドウ左上のボタンからPDFファイルを開く。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/966a6702-1a0e-4492-9f42-bdd78546c860/5499721424d171a88f541a5deb396a87/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-31-21-48.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;そうするとちょっと待ってという表示がでる。この後書くが、このときに全てのページを重ねあわせたものを作っている。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7291a7f6-d682-4634-932d-24e8d2285fcd/7977dc7c108b3d60e0f6867f3c744989/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-31-21-46.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;読み込みが完了すると全てのページを重ねあわせた表示（Stacked View）が表示される。こんな感じで結構すごい。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9cddb7c5-78dd-43a2-a891-6779f7ff4ce9/cc1626434dbd334f48c2d1d571ad0e7b/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-31-21-47.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;全てのページを重ねあわせてくれるので、ドキュメント全体を通して余白担っている部分がわかるというわけ。あとは、このソフトの機能で切り取ってあげればいい。&lt;/p&gt;
&lt;p&gt;矩形選択機能を選んで、、、&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/659b886e-c797-4232-b148-4069b24ff95d/2251136a2160f0fa32bc37d3fba21916/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-31-21-53.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;切り取り後に含めたい部分を囲む。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/d136368d-5fb4-4f82-8d9e-2c4b2cb40372/d4be5c539a7de8cb986b1049b8bfb15c/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-31-21-53.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;あとは保存ボタンから保存すればOK。&lt;/p&gt;
&lt;h1 id="できあがり"&gt;できあがり&lt;/h1&gt;
&lt;p&gt;ちゃんと余白が切り取られている。切り取ったあとのものを印刷すると元のデーたよりも見やすくできると思う。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9478915e-64ef-4955-9171-1867d8084d07/8c1ac4079c4f48aaf186312a3a1f3a54/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-31-21-56.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>iOSで動画ファイルを連続・リピート・シャッフル再生したいとき</title><link>https://blog.piyo.tech/posts/2014-06-01-203000/</link><pubDate>Sun, 01 Jun 2014 20:30:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-06-01-203000/</guid><description>&lt;p&gt;動画ファイルをiTunes経由でiPhoneやiPadに入れるとデフォルトではホームビデオという種類だとして取り込まれる。これを閲覧するには「ビデオ」というアプリを使う。&lt;/p&gt;
&lt;p&gt;このアイコンのやつね。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c6a8c94a-8d90-40d6-ac4f-b32cb34ec792/20ec151c0c603c98a481d2b71ce11231/deep/0/ios-7-video-icon-pn.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;だけど、このビデオアプリには動画を単体で再生する機能しかついておらず、複数の動画を連続再生したりリピートやシャッフル再生したりできない。&lt;/p&gt;
&lt;p&gt;この仕様だと複数の動画を子どもにしばらく見せておきたいときなどに困るのでどうにかならないかと調べたら、標準の「ミュージック」アプリでも再生できるようにする方法があった。しかもこの方法を使うとプレイリストにすることもできるので大変捗る。&lt;/p&gt;
&lt;p&gt;方法は簡単で、iTunesで動画を右クリックして「情報を見る」→「オプション」タブの「メディアの種類」を「ミュージックビデオ」にするだけでいい。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/a206b83c-c3ef-4de3-ab07-8056ca66ddda/f854042741754e0e19da129b8c666969/deep/0/OtherViews.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;この状態でデバイスとの同期を行えば「ミュージック」アプリ内で再生できるようになる。&lt;/p&gt;
&lt;p&gt;注意点としては、ミュージックアプリ内では動画の全画面再生ができないことが挙げられる。若干不満はあるかもしれないが、サードパーティの動画アプリを使うほどでもないな、というときはこの方法がおすすめ。&lt;/p&gt;</description></item><item><title>UIViewのカテゴリでtouchesBeganなどを定義するとどうなるのか？</title><link>https://blog.piyo.tech/posts/2014-05-31-203000/</link><pubDate>Sat, 31 May 2014 20:30:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-31-203000/</guid><description>&lt;p&gt;Objective-Cではカテゴリを使って既存のクラスに新しいメソッドを追加したかのように振る舞わせることができる。&lt;/p&gt;
&lt;p&gt;では、カテゴリで新しいメソッドではなく、既存の（というかオーバーライドして使うようなもの）を定義するとどういう挙動になるのか。気になって調べてみた。&lt;/p&gt;
&lt;p&gt;例えばUIViewでタッチを検出して処理を行いたい場合はそのビューのサブクラスを作って&lt;code&gt;touchesBegan&lt;/code&gt;や&lt;code&gt;touchesEnded&lt;/code&gt;を実装すればよいし、ViewControllerでも同じようなことができる。&lt;/p&gt;
&lt;p&gt;この&lt;code&gt;touchesBegan&lt;/code&gt;などのメソッドをカテゴリで実装してやる。実装は単にタッチ開始や終了を自身のアドレス付きでログに出すものとなっている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// UIView+Touch.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;UIKit/UIKit.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UIView&lt;/span&gt; (Touch)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// UIView+Touch.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;#34;UIView+Touch.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@implementation&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UIView&lt;/span&gt; (Touch)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;touchesBegan:&lt;/span&gt;(NSSet &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)touches &lt;span style="color:#a6e22e"&gt;withEvent:&lt;/span&gt;(UIEvent &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)event {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;touchesBegan:[%p]&amp;#34;&lt;/span&gt;, self);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;touchesEnded:&lt;/span&gt;(NSSet &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)touches &lt;span style="color:#a6e22e"&gt;withEvent:&lt;/span&gt;(UIEvent &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)event {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;touchesEnded:[%p]&amp;#34;&lt;/span&gt;, self);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そして、こんな感じで適当にビューを作る。置いたのはすべてUIView。UILabelなんかでもいいんだけど、一部のUIコンポーネントは&lt;code&gt;userInteractionEnabled&lt;/code&gt;をYESにしないといけないのが面倒なのでサンプルではUIVIewにした。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/623ddcb0-0498-4a81-934b-675edd579bcc/5e3d5d25c9656b3c8e4ee5174a7f5219/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-30-21-14.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;起動して次の順番でそれぞれのビューをタップする。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;UIView 1&lt;/li&gt;
&lt;li&gt;UIView 2&lt;/li&gt;
&lt;li&gt;UIView 3&lt;/li&gt;
&lt;li&gt;背景部分のView&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;ログにはそれらのViewの&lt;code&gt;touchesBegan&lt;/code&gt;や&lt;code&gt;touchesEnded&lt;/code&gt;からの出力が出ている。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;2014-05-30 21:17:36.592 OverrideInCategory[56354:60b] touchesBegan:[0x8f3b190]
2014-05-30 21:17:36.641 OverrideInCategory[56354:60b] touchesEnded:[0x8f3b190]
2014-05-30 21:17:37.585 OverrideInCategory[56354:60b] touchesBegan:[0x8f3aac0]
2014-05-30 21:17:37.675 OverrideInCategory[56354:60b] touchesEnded:[0x8f3aac0]
2014-05-30 21:17:38.639 OverrideInCategory[56354:60b] touchesBegan:[0x8f3b7e0]
2014-05-30 21:17:38.757 OverrideInCategory[56354:60b] touchesEnded:[0x8f3b7e0]
2014-05-30 21:17:39.953 OverrideInCategory[56354:60b] touchesBegan:[0x8f3b130]
2014-05-30 21:17:40.061 OverrideInCategory[56354:60b] touchesEnded:[0x8f3b130]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;先ほど定義した&lt;code&gt;UIView+Touch&lt;/code&gt;のヘッダーはどこにも&lt;code&gt;#import&lt;/code&gt;はしていないが、全てのViewに対して&lt;code&gt;touchesBegan&lt;/code&gt;などが有効になっている。こういう言語仕様になっているということを知らなかったので、へぇーという感じ。&lt;/p&gt;</description></item><item><title>CocoaPodsの公開方法がpod trunkに変わった</title><link>https://blog.piyo.tech/posts/2014-05-30-200000/</link><pubDate>Fri, 30 May 2014 20:00:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-30-200000/</guid><description>&lt;p&gt;CocoaPodsの公開方法、以前は公式のSpecsリポジトリ（&lt;a href="https://github.com/CocoaPods/Specs"&gt;CocoaPods/Specs&lt;/a&gt;）をForkし、自分podspecを追加してからプルリクエストという流れだった。この方式ではプルリクエストがマージされないと公開されなかった。&lt;/p&gt;
&lt;p&gt;ところが、2014年5月中旬ぐらいに全自動で公開までいける仕組みに変わったらしい。新しい情報が検索でヒットしないせいか、プルリクエスト寸前まで行って気がついた。&lt;/p&gt;
&lt;p&gt;プルリクエストのコメントになんて書くのが普通なのかなとCocoaPods/Specsのプルリクを調べにいったら、ライブラリ公開のプルリクに対するコメントで&lt;code&gt;We have just launched ‘Trunk’うんぬん&lt;/code&gt;などと書かれていたのを見つけたおかげ。&lt;/p&gt;
&lt;p&gt;（今日配信の&lt;a href="http://rebuild.fm/45/"&gt;Rebuild: 45&lt;/a&gt;でも触れられていた。先にこっちを聴いていれば従来方式で途中まで頑張る必要なかったのに…！）&lt;/p&gt;
&lt;h1 id="pod-trunkで公開"&gt;pod trunkで公開&lt;/h1&gt;
&lt;p&gt;再度調べたら素晴らしいエントリを見つけた。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.hypermkt.jp/cocoapods-trunk%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%9F%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AE%E8%BF%BD%E5%8A%A0%E6%96%B9%E6%B3%95/"&gt;CocoaPods Trunkを利用したライブラリの追加方法 | hypermkt blog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;こちらの通りに進めれば簡単にライブラリをCocoaPodsで公開できた。&lt;/p&gt;
&lt;p&gt;なおこの方法で公開するとすぐに@CocoaPodsFeedというTwitterアカウントにポストされる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p&gt;[CFPressHoldButton] Press and hold button for iOS &lt;a href="https://t.co/JoNTAjWuRS"&gt;https://t.co/JoNTAjWuRS&lt;/a&gt;&lt;/p&gt;&amp;mdash; CocoaPods New Pods (@CocoaPodsFeed) &lt;a href="https://twitter.com/CocoaPodsFeed/statuses/472267121766838272"&gt;May 30, 2014&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;</description></item><item><title>カテゴリを使って既存クラスにプロパティを追加する</title><link>https://blog.piyo.tech/posts/2014-05-29-213121/</link><pubDate>Thu, 29 May 2014 21:31:21 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-29-213121/</guid><description>&lt;p&gt;Objective-Cではカテゴリを使って既存のクラスを拡張してメソッドを追加できるが、メソッドだけでなくプロパティを追加することもできる。&lt;/p&gt;
&lt;p&gt;例えばこんな風に&lt;code&gt;UIView&lt;/code&gt;のカテゴリを新規作成し、ヘッダーにプロパティを定義する。今回は&lt;code&gt;NSString&lt;/code&gt;にした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// UIView+PropertySample.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;UIKit/UIKit.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UIView&lt;/span&gt; (PropertySample)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt;) NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;value;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これだけ書くと以下のような警告が出る。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Property &amp;#39;value&amp;#39; requires method &amp;#39;value&amp;#39; to be defined - use @dynamic or provide a method implementation in this category
Property &amp;#39;value&amp;#39; requires method &amp;#39;setValue:&amp;#39; to be defined - use @dynamic or provide a method implementation in this category
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;@dynamicを使うか、&lt;code&gt;value&lt;/code&gt;と&lt;code&gt;setValue:&lt;/code&gt;を定義しろと言われている。&lt;code&gt;@dynamic&lt;/code&gt;はアクセサを自動生成しないという指定だった気がするから、今回は&lt;code&gt;@dynamic&lt;/code&gt;を書いた上で、&lt;code&gt;value&lt;/code&gt;/&lt;code&gt;setValue:&lt;/code&gt;を定義した。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// UIView+PropertySample.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;#34;UIView+PropertySample.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;objc/runtime.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@implementation&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UIView&lt;/span&gt; (PropertySample)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@dynamic&lt;/span&gt; value;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;setValue:&lt;/span&gt;(NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)value
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; objc_setAssociatedObject(self, _cmd, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;- (NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; objc_getAssociatedObject(self, &lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(setValue:));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;objc_getAssociatedObject&lt;/code&gt;と&lt;code&gt;objc_setAssociatedObject&lt;/code&gt;という関数を使うために&lt;code&gt;objc/runtime.h&lt;/code&gt;をインポートしておく。&lt;/p&gt;
&lt;p&gt;これらの関数は既存のオブジェクトに他のオブジェクトを関連付けるというもので、ここではプロパティを擬似的に表現するために使っている。&lt;/p&gt;
&lt;p&gt;ポイントはsetterの&lt;code&gt;_cmd&lt;/code&gt;とgetterの&lt;code&gt;@selector(setValue:)&lt;/code&gt;。同じオブジェクトに複数のオブジェクトを関連付けられるため、どの関連付けに対するset/getなのかを明確にするためのキーが必要になる。ここでは&lt;code&gt;setValue:&lt;/code&gt;のアドレスを用いている。キーには一意なポインタが必要であり、セレクタを使うのは理にかなっているような気がする。&lt;/p&gt;
&lt;p&gt;ひとまずこれでカテゴリに使ったプロパティの追加ができた。&lt;/p&gt;</description></item><item><title>REPLエディタ Light Tableを試す</title><link>https://blog.piyo.tech/posts/2014-05-28-221042/</link><pubDate>Wed, 28 May 2014 22:10:42 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-28-221042/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/fcb0463c-9c72-40b7-ad2e-e1a7b06d25f5/7d23edcfc73cac3990467d0958d698e2/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-28-22-08.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Facebookでこんなのが流れてたので思わずインストールしてしまったテキストエディタ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.facebook.com/permalink.php?story_fbid=792468014104919&amp;amp;id=565244630160593"&gt;エンジニアライズ - 【開発意欲を刺激するエディタの紹介】 http://www.lighttable.com/&amp;hellip;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;LightTableはプログラマを中心に新たに注目されているエディタです。リアルタイムかつインラインで式を評価し、表示するのがこのエディタの特徴です。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;だそうで、Pryを使って色々と確認しながらコードを書くことも多いからこれはいいかもなと。&lt;/p&gt;
&lt;p&gt;公式チュートリアル（英語）があるけど文字ばかりで読みづらかったんで、少ない日本語の情報を便りにセットアップした。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qiita.com/tenten0213/items/5f7f103da8f6569697f6"&gt;LightTableでRuby、Nokogiriを使ってリアルタイムスクレイピング - Qiita&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="導入編"&gt;導入編&lt;/h1&gt;
&lt;h2 id="インストール"&gt;インストール&lt;/h2&gt;
&lt;p&gt;まずここからバイナリをダウンロード。これは普通のアプリケーションと同じ。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.lighttable.com/"&gt;Light Table&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="コマンドビューのホットキー変更"&gt;コマンドビューのホットキー変更&lt;/h2&gt;
&lt;p&gt;コマンドビューって呼ぶのかどうかはわからないけど、Sublimeでいうコマンドパレットの呼び出しのホットキーが&lt;code&gt;Ctrl+Space&lt;/code&gt;とかいうふざけた組み合わせにアサインされている。このコマンドは普通はSpotlightに使われているし、僕の場合はAlfredに割り当てている。&lt;/p&gt;
&lt;p&gt;じゃあキーを変更しようと思ってもメニューに見当たらないし、コマンドビューも開けない、詰んだ、、と思ったら、&lt;code&gt;View&lt;/code&gt;→&lt;code&gt;Commands&lt;/code&gt;というメニューがあった。ここからコマンドビューを起動し、&lt;code&gt;key&lt;/code&gt;あたりの単語で絞り込みをかけるとこうなる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/abf98ab1-83dd-469d-be2d-3cd131db2699/fb145fb7b089decfb1696df868097732/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-28-21-32.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;そして&lt;code&gt;Settings: User keymap&lt;/code&gt;を開く。&lt;/p&gt;
&lt;p&gt;ここにキー設定を追加するわけだけど、僕には独特な書き方に見える。これはよくあるフォーマットなのか？&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;{:+ {:app {&amp;#34;shift-pmeta-p&amp;#34; [:show-commandbar-transient]}
:editor {&amp;#34;alt-w&amp;#34; [:editor.watch.watch-selection]
&amp;#34;alt-shift-w&amp;#34; [:editor.watch.unwatch]}}}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;実際に追加したのは、&lt;code&gt;&amp;quot;shift-pmeta-p&amp;quot; [:show-commandbar-transient]&lt;/code&gt;の部分。Sublime Textのコマンドパレットと同じく&lt;code&gt;Shift+Command+p&lt;/code&gt;を割り当てることにした。&lt;/p&gt;
&lt;h2 id="ruby用のreplを入れる"&gt;Ruby用のREPLを入れる&lt;/h2&gt;
&lt;p&gt;デフォルトではRubyのリアルタイム評価には対応しておらずプラグインが必要らしい。&lt;/p&gt;
&lt;p&gt;プラグインを入れるには、コマンドビューに&lt;code&gt;plugin&lt;/code&gt;とタイプし&lt;code&gt;Plugins: Show plugin manager&lt;/code&gt;を選ぶと開くプラグインマネージャーから行うようだ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/719ab7bc-fd5c-4d05-a0cb-e6f8c18be4f6/b54f9e5369e8ddb2388c8711e25e13dd/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-28-21-37.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;こんな具合の画面になるから、検索欄にrubyとタイプしてリターン。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c8b13345-78bf-47fd-ab32-52b1ef08e93b/ef6e0a5517c34309689af630629700f8/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-28-21-38.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Ruby Instarepl&lt;/code&gt;というものがあるはずなのでそれをインストールする。&lt;/p&gt;
&lt;h2 id="必要なgemを入れる"&gt;必要なgemを入れる&lt;/h2&gt;
&lt;p&gt;参照したQiitaの記事によると依存するgemがあるらしいのでそれらをインストールする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% gem install eventmachine
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;% gem install json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;% gem install method_source
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;本当に必要かどうかは検証していない。&lt;/p&gt;
&lt;h1 id="使ってみる"&gt;使ってみる&lt;/h1&gt;
&lt;h2 id="デモ"&gt;デモ&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/trxTAJc_CEiQQB2InVhAuCMFxU2JqY6tGvMxGVRlUB7P6V431psrQx8PTULcDmMtlllYhUJr0ONJ-D-dJriEtytUKekM_TrJRD_1bF1_kvoaUZzmEsxta_zvnD-v8NZnk8I6r0gE5KyY1OeI7AQnBm35Vr1o9e6N8Tz3ESkkw2Npwkv9nBY2PoLRUrxi5OVPbB9_nixzIjCIEsj6iYJa_AtObhskXD-DqEHjdXaNikJkJWSy_P88DvRA0OifgfJ9ipC0g5OnxotE30nrftq2UktwE0k6aymihVgSan6M3F1g0o2Bt2fa_4BDA10-c866BRXQ6X6HkdSxEmY15gy-zCSN3OvoN4ihqRoATYOw-I7SXiURJ3ClZQJLKgG1eaDXrqex5vVLa4ROjJcmM-XgcKJ4SLE87LNRKELrm-xMe8zwiU9gOwNJENtd63w1JovhwJqJyoyK4X4fz4WJVRJd_Gsbxu2cRgq8OhBdfmfIW1ApE-0Ggso_Ddllm9T-bzrPsMD_6s5nfW0NN9JIbgl2vI5MxsMkKPgfCKyjvxMd9Opo-QObBEtyfW9ZA7EqHsbTfz6nBC2YZB94H5gABDwyPe8JHcvrUgZmqS2n0eDd9H2dgrcTinNHnM0vwVKwnXrn5pqXsmH1TZfZCZtPpGhZjn2JkwOcMkxokQ=w421-h315-no" alt=""&gt;&lt;/p&gt;
&lt;h2 id="感想"&gt;感想&lt;/h2&gt;
&lt;p&gt;Pryなどの対話側の環境と比較すると、そもそもがエディタだから長めのコードが書きやすいし、以前の式を再評価したり少しだけ変更したりといったことが格段にやりやすい。ただし、リアルタイムに評価してくれるLiveモードでは評価済みの行を変更しても再評価はしてくれないような感じがした。その場合はCommand+Returnでマニュアル評価ができるし、そもそもそれで十分だと感じだ。&lt;/p&gt;
&lt;p&gt;&lt;del&gt;不満点が1つだけある。それはコードの評価結果をコピーする手段がないこと。いや、実際にはそういうことはできるようになっていて、操作方法がわかりにくいだけかもしれないけれど。&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;&lt;del&gt;これがネックでREPLとしても実用にはできなそうな気がしている。&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;訂正&lt;/strong&gt;：マウスで選択してCommand+Cで普通にいけた(id:gnety さんありがとうございます)。&lt;/p&gt;
&lt;p&gt;そうそう、エディタとしては完成度がまだまだだからEmacsを置き換えるには及ばない。というかEmacs上でRubyを実行する方法を調べたほうがいいのかもしれない。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description></item><item><title>OpenURIでhttpからhttpsのリダイレクトを一時的に許すgem作った</title><link>https://blog.piyo.tech/posts/2014-05-27-203000/</link><pubDate>Tue, 27 May 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-27-203000/</guid><description>&lt;p&gt;RubyではOpenURIを使うとウェブページを開くことができる。OpenURIでは引数に与えたURIのプロトコルがHTTPリダイレクト先がHTTPSの場合、エラーが発生するという作りになっている。&lt;/p&gt;
&lt;p&gt;ところで、HTTPからHTTPSへのリダイレクトは意外とたくさんある。&lt;/p&gt;
&lt;p&gt;例えばGoogleで短縮URL。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://goo.gl/84556T"&gt;http://goo.gl/84556T&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;リダイレクト先はここ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/open_uri_allow_redirect"&gt;https://github.com/pi-chan/open_uri_allow_redirect&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;% irb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;irb&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;:001:0&amp;gt; require &lt;span style="color:#e6db74"&gt;&amp;#34;open-uri&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;irb&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;:002:0&amp;gt; open &lt;span style="color:#e6db74"&gt;&amp;#34;http://goo.gl/84556T&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;RuntimeError: redirection forbidden: http://goo.gl/84556T -&amp;gt; https://github.com/pi-chan/open_uri_allow_redirect
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; from /Users/hiromasa/.rbenv/versions/2.1.0/lib/ruby/2.1.0/open-uri.rb:223:in &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;open_loop&lt;span style="color:#e6db74"&gt;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; from /Users/hiromasa/.rbenv/versions/2.1.0/lib/ruby/2.1.0/open-uri.rb:149:in `open_uri&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; from /Users/hiromasa/.rbenv/versions/2.1.0/lib/ruby/2.1.0/open-uri.rb:703:in &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;open&lt;span style="color:#e6db74"&gt;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; from /Users/hiromasa/.rbenv/versions/2.1.0/lib/ruby/2.1.0/open-uri.rb:34:in `open&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; from &lt;span style="color:#f92672"&gt;(&lt;/span&gt;irb&lt;span style="color:#f92672"&gt;)&lt;/span&gt;:2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; from /Users/hiromasa/.rbenv/versions/2.1.0/bin/irb:11:in &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&amp;lt;main&amp;gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;irb&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;:003:0&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このようなケースでは、そのままのOpenURIは使えない。&lt;/p&gt;
&lt;h1 id="open_uri_redirections"&gt;open_uri_redirections&lt;/h1&gt;
&lt;p&gt;Rubyだから既存のクラスを拡張してしまえばよい。探してみるとOpenURIでHTTPSへのリダイレクトを許可するような拡張をしているgemがあった。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/jaimeiniesta/open_uri_redirections"&gt;jaimeiniesta/open_uri_redirections&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このgemにより、openメソッドで&lt;code&gt;allow_redirections&lt;/code&gt;というオプションを扱えるようになる。HTTPからHTTPSのリダイレクトやその逆のリダイレクトを許可するかどうかを呼び出し元が制御できるようになるというわけ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;open-uri&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;open_uri_redirections&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;open(&lt;span style="color:#e6db74"&gt;&amp;#39;http://github.com&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:allow_redirections&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;:safe&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;open(&lt;span style="color:#e6db74"&gt;&amp;#39;http://github.com&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:allow_redirections&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;:all&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;open&lt;/code&gt;の中で使われる&lt;code&gt;redirectable?&lt;/code&gt;というメソッドを置き換えることによってこれを実現している。&lt;/p&gt;
&lt;h2 id="このgemの問題点"&gt;このgemの問題点&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;open&lt;/code&gt;の呼び出しを自分で書くときはいいが、ライブラリなどの自分で手を加えにくいコードが&lt;code&gt;open&lt;/code&gt;を呼んでいる場合にはこのgemでは対応しきれない。&lt;/p&gt;
&lt;h1 id="open_uri_allow_redirect作った"&gt;open_uri_allow_redirect作った&lt;/h1&gt;
&lt;p&gt;その問題を解決するために、少しばかり改変したgemを作った。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/open_uri_allow_redirect"&gt;pi-chan/open_uri_allow_redirect&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このgemでは&lt;code&gt;open&lt;/code&gt;の引数を使わず、&lt;code&gt;OpenURI.allow_redirect&lt;/code&gt;に渡したブロック内の&lt;code&gt;open&lt;/code&gt;呼び出しは全てのリダイレクトを許可するという作りになっている。&lt;/p&gt;
&lt;p&gt;こんな感じで使える。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;open_uri_allow_redirect&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;open(&lt;span style="color:#e6db74"&gt;&amp;#34;http://github.com&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# =&amp;gt; raises RuntimeError, redirected to https://github.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;OpenURI&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;allow_redirect &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; open(&lt;span style="color:#e6db74"&gt;&amp;#34;http://github.com&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# =&amp;gt; no error&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ライブラリのコードが&lt;code&gt;open&lt;/code&gt;を呼んでいるときにも対応できる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# in other library&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;module&lt;/span&gt; MyLibrary
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;use_open_method_internally&lt;/span&gt;(uri)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; open(uri)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;open_uri_allow_redirect&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;OpenURI&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;allow_redirect &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;MyLibrary&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;use_open_method_internally(&lt;span style="color:#e6db74"&gt;&amp;#34;http://github.com/&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# =&amp;gt; no error&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;いえい。&lt;/p&gt;</description></item><item><title>iOSでFacebook連携ログインするアプリを作る手順まとめ</title><link>https://blog.piyo.tech/posts/2014-05-26-200000/</link><pubDate>Mon, 26 May 2014 20:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-26-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c99f0eb1-303b-428d-9aef-8f37c6bd14b5/fcd8e2621e44418091c160ad70d42709/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-26-15-00.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Facebookログインが必要なiPhoneアプリはたくさんあり、大抵のアプリケーションはFacebookのiPhoneアプリと連携してパスワード入力無しでログインを済ませてくれるのでユーザーとしてはとても楽だ。&lt;/p&gt;
&lt;p&gt;だけど、Facebookアプリを使わずに自アプリ内でWebViewを開いて、そこでメールとパスワードを入力しなければいけないフローになっているアプリもそれなりに見かける。&lt;/p&gt;
&lt;p&gt;僕の場合は各種サービスのパスワードは管理ツールで自動生成していて覚えていない。Macの場合は管理ツールが常時立ち上がっているのですぐに参照できるが、iPhoneの場合は、管理アプリを立ちあげる→マスターパスワードを入力→目的のサイトを選択→パスワードをコピー→元のアプリに戻る、という手順を踏まなければならないため、非常に使い勝手が悪い。&lt;/p&gt;
&lt;p&gt;というか、Facebookアプリが認証の仕組みを提供しているのにそれを実装してないアプリはろくなもんじゃない。実装自体そんなに難しいものでもないはずなので、開発者の怠慢でしかないと僕は思う。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;やったことないけど。&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id="facebookアプリを使った認証機能を実装する"&gt;Facebookアプリを使った認証機能を実装する&lt;/h1&gt;
&lt;p&gt;やったことない、じゃダメだと思うのでやってみた。&lt;/p&gt;
&lt;p&gt;きちんとした公式ドキュメントがあるのでこちらを参照すれば十分だが、せっかくなので試したプロセスを記録しておく。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.facebook.com/docs/ios/getting-started"&gt;Getting Started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.facebook.com/docs/facebook-login/ios/v2.0"&gt;Facebook Login for iOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="facebook側での事前準備"&gt;Facebook側での事前準備&lt;/h2&gt;
&lt;h3 id="アプリケーションを登録する"&gt;アプリケーションを登録する &lt;/h3&gt;
&lt;p&gt;Facebookの開発者用ページに飛んでアプリケーションを作る。今から作ろうとしているiPhoneアプリのためのIDみたいなものだ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://developers.facebook.com/"&gt;Facebook Developers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;開発者ページのナビゲーションから&lt;code&gt;Create a New App&lt;/code&gt;のリンクをクリックする。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/226cfb71-946a-48f7-b0cd-f4b9d5f4e9dc/f24535c4e978689cc579a835dfcf62a0/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-26-14-09.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;次のようなフォームが出てくるので適当に入力する。今回はDisplay Nameを&lt;code&gt;LoginTest&lt;/code&gt;、Namespaceを&lt;code&gt;fblogintest&lt;/code&gt;とした。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Is this a test version of another app?&lt;/code&gt;は&lt;code&gt;いいえ&lt;/code&gt;のまま、カテゴリは今から作ろうとしているアプリケーションに合ったものにすればいいが、今回はとりあえずユーティリティを選んでおいた。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/6106d3b2-bbfe-4cc9-a22f-8fe5193cdd51/af94330278bb279ddc8bb680db9759c5/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-26-14-12.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;アプリ作成が終わるとDashboardが表示される。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/96dd8a38-5c68-4f50-ba32-5c24ff415a39/e90e5c6ffefc8bfe6815cafade610bd1/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-26-11-16.png" alt=""&gt;&lt;/p&gt;
&lt;h3 id="アプリケーションの設定"&gt;アプリケーションの設定&lt;/h3&gt;
&lt;p&gt;↑で作ったアプリケーションに対して、少しだけ設定が必要。&lt;/p&gt;
&lt;p&gt;管理画面の左側&lt;code&gt;Settings&lt;/code&gt;メニューを選び、その先で&lt;code&gt;Add Platform&lt;/code&gt;をクリックし、iOSを選ぶ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c7428f61-7867-4d8b-8ef9-54e2f124d160/c12add43bf376b32ee13773c94a65de2/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-26-11-16.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;新しく現れたフォームでは、これから作るiPhoneアプリのバンドルIDのところと、&lt;code&gt;Single Sign On&lt;/code&gt;のところを変更する。他の欄は当面は空白で良さそう。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/4bbb499f-d5e3-4e7a-9d4b-0e7c984013a5/6f46b1b84b7190d4144dad6ce145f66b/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-26-14-17.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="xcodeプロジェクトを作る"&gt;Xcodeプロジェクトを作る&lt;/h2&gt;
&lt;p&gt;プロジェクトを新規作成し、SDKの導入やplistの設定を行う。&lt;/p&gt;
&lt;h3 id="facebook-sdkの導入"&gt;Facebook SDKの導入&lt;/h3&gt;
&lt;p&gt;開発者向けサイトからダウンロードする方法もあるが、今はCocoaPodsが便利。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Podfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;Facebook-iOS-SDK&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% pod install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="plistを編集する"&gt;plistを編集する&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;{プロジェクト名}-Info.plist&lt;/code&gt;にいくつか追記する必要がある。この情報が間違っていると正しく動かなかったり、アプリケーションがクラッシュしたりする。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FacebookAppID&lt;/code&gt; → アプリケーション管理画面のAppID&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FacebookDisplayName&lt;/code&gt; → アプリケーション作成時に入力したDisplayName&lt;/li&gt;
&lt;li&gt;&lt;code&gt;URL types&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;URL Schemes&lt;/code&gt; → &amp;ldquo;fb&amp;rdquo; + AppID&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c3f3b002-fa51-4c02-ba64-7792e1f2ef38/95200e4d3c53a36163e1ee0b24e71ebe/deep/0/FBLogin---FBLogin-Info.plist.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="アプリを実装する"&gt;アプリを実装する&lt;/h2&gt;
&lt;p&gt;開発者向けドキュメントにあるようなログインしてユーザー名を表示する程度のサンプルを実装してみる。&lt;/p&gt;
&lt;h3 id="storyboardでコントロールを配置する"&gt;Storyboardでコントロールを配置する&lt;/h3&gt;
&lt;p&gt;次の図のようにコントロールを配置した。UILabelを2つとUIViewが2つ。ラベルは現在の状態やユーザー名を表示するためのもので、UIViewはSDKのFBLoginViewやFBProfilePictureViewをカスタムクラスとして使う。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/3916e3ce-6907-4ab0-bfe2-c3e190a6658c/faad585c66483fad6fdeb00ddf636364/deep/0/FBLogin---Main.storyboard---Edited.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ちなみにカスタムクラスはstoryboardのインスペクタで指定することができる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/936de02d-2f7d-463b-a105-7bf485959357/4d009fca43fa852c585c3e2ea23a5aea/deep/0/FBLogin---Main.storyboard---Edited.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;コードからも呼びたいのでプロパティとも紐付けておく。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-oできる" data-lang="oできる"&gt;bjc
#import &amp;lt;UIKit/UIKit.h&amp;gt;
#import &amp;lt;FacebookSDK.h&amp;gt;
@interface ViewController : UIViewController&amp;lt;FBLoginViewDelegate&amp;gt;
@property (weak, nonatomic) IBOutlet FBLoginView *loginView;
@property (weak, nonatomic) IBOutlet UILabel *statusLabel;
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (weak, nonatomic) IBOutlet FBProfilePictureView *profilePictureView;
@end
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;追記&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Storyboardで&lt;code&gt;FBLoginView&lt;/code&gt;などのクラスを参照すると、実行時にクラスが見つからないという警告が出てしまう場合がある。そういう場合は起動時に対象のクラスを一度ロードさせてやると良いらしい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;application:&lt;/span&gt;(UIApplication &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)application
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;didFinishLaunchingWithOptions:&lt;/span&gt;(NSDictionary &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)launchOptions
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Override point for customization after application launch.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; [FBLoginView &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; YES;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;追記ここまで&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;今回はStoryboardを使ったが、コードでUIを定義することももちろん可能。&lt;/p&gt;
&lt;h3 id="パーミッションの設定"&gt;パーミッションの設定&lt;/h3&gt;
&lt;p&gt;機能に応じて今から作るアプリがどんな権限を持つかを指定する必要がある。連携確認画面でこのアプリにはコレとアレとソレを許可しますみたいなリストは見たことがあるはず。&lt;/p&gt;
&lt;p&gt;パーミッションは初期化のときに指定するのがいい。今回はViewController.mの&lt;code&gt;viewDidLoad&lt;/code&gt;あたりで書いておく。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; [super viewDidLoad];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; self.loginView.readPermissions &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;@[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;@&amp;#34;public_profile&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;@&amp;#34;email&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;@&amp;#34;user_friends&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;]&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑の例では、公開プロフィール、メールアドレス、友達一覧へのアクセス権を要求している。&lt;/p&gt;
&lt;h3 id="urlスキームの処理を書く"&gt;URLスキームの処理を書く&lt;/h3&gt;
&lt;p&gt;URLスキームを使ってFacebookの公式アプリと連携することになるため、連携のためのコードを書く必要がある。これはドキュメントに書いてるコードをそのまま貼り付ければ良い。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AppDelegate.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;application:&lt;/span&gt;(UIApplication &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)application
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;openURL:&lt;/span&gt;(NSURL &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)url
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;sourceApplication:&lt;/span&gt;(NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)sourceApplication
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;annotation:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)annotation {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Call FBAppCall&amp;#39;s handleOpenURL:sourceApplication to handle Facebook app responses
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt; wasHandled &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// You can add your app-specific url handling code here if needed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; wasHandled;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="連携時のdelegateを実装する"&gt;連携時のDelegateを実装する&lt;/h3&gt;
&lt;p&gt;続いてログイン成功時や、ログアウト時、エラー時などの処理を担当するDelegateメソッドを実装していく。&lt;/p&gt;
&lt;p&gt;実装するメソッドは次の4つ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;loginViewFetchedUserInfo:user:&lt;/code&gt; 公開プロフィールを取ってきたとき&lt;/li&gt;
&lt;li&gt;&lt;code&gt;loginViewShowingLoggedInUser:&lt;/code&gt; ログイン中の表示をするとき&lt;/li&gt;
&lt;li&gt;&lt;code&gt;loginViewShowingLoggedOutUser:&lt;/code&gt; ログアウト中の表示するとき&lt;/li&gt;
&lt;li&gt;&lt;code&gt;loginView:handleError:&lt;/code&gt; エラーが起こったとき&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;まず、ViewController.hでFBLoginViewDelegateプロトコルを継承する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ViewController.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;FacebookSDK.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ViewController&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;UIViewController&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;FBLoginViewDelegate&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次に、ViewController.mにDelegateの実装を書く。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;loginViewFetchedUserInfo:&lt;/span&gt;(FBLoginView &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)loginView &lt;span style="color:#a6e22e"&gt;user:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;FBGraphUser&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;)user
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; self.profilePictureView.profileID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [user objectID];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; self.nameLabel.text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; user.name;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;loginViewShowingLoggedInUser:&lt;/span&gt;(FBLoginView &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)loginView
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; self.statusLabel.text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;You&amp;#39;re logged in as&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;loginViewShowingLoggedOutUser:&lt;/span&gt;(FBLoginView &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)loginView
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; self.statusLabel.text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;You&amp;#39;re not logged in!&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; self.profilePictureView.profileID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; nil;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; self.nameLabel.text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// loginView:handleError: は長いので省略
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="やってみた感想"&gt;やってみた感想&lt;/h1&gt;
&lt;p&gt;とまあこんな具合で実装できた。&lt;/p&gt;
&lt;p&gt;図入りで書くと長くなったが、やってみた感じはだいぶ楽だった。冒頭に書いたとおり、WebViewでログインさせようとするアプリの開発者は怠慢だと言っていいと思う。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/31314e06-68fd-4bf7-8c0c-e34c36e52125/d18b9486f286eb70ac64f371407f4e14/deep/0/%E5%90%8D%E7%A7%B0%E6%9C%AA%E8%A8%AD%E5%AE%9A.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>rails-composerとrails newの-mオプション</title><link>https://blog.piyo.tech/posts/2014-05-25-190000/</link><pubDate>Sun, 25 May 2014 19:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-25-190000/</guid><description>&lt;p&gt;Railsで使いたいgemが大体定まってくると&lt;code&gt;rails new&lt;/code&gt;でアプリケーションを作ってからの作業が毎回同じことの繰り返しで面倒になってくる。その上、手作業だと設定漏れが出ることも往々にしてあるため、自動化するのが望ましい。&lt;/p&gt;
&lt;p&gt;幸い&lt;code&gt;rails new&lt;/code&gt;コマンドには&lt;code&gt;-m&lt;/code&gt;オプションでテンプレートを指定できるようになっている。&lt;/p&gt;
&lt;p&gt;公式ドキュメントはこれ。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://guides.rubyonrails.org/rails_application_templates.html"&gt;Rails Application Templates — Ruby on Rails Guides&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;サンプルコードを見ると何ができるのかわかりやすい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# template.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;generate(&lt;span style="color:#e6db74"&gt;:scaffold&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;person name:string&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;route &lt;span style="color:#e6db74"&gt;&amp;#34;root to: &amp;#39;people#index&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;rake(&lt;span style="color:#e6db74"&gt;&amp;#34;db:migrate&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;git &lt;span style="color:#e6db74"&gt;:init&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;git &lt;span style="color:#e6db74"&gt;add&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;git &lt;span style="color:#e6db74"&gt;commit&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;%Q{ -m &amp;#39;Initial commit&amp;#39; }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="rails-composer"&gt;rails-composer&lt;/h1&gt;
&lt;p&gt;テンプレートは自分で必要なものだけを入れて作るのが普通だとは思うが、誰かが用意したテンプレートを使うという手もある。そういったテンプレートのうち、全部入りな感じのテンプレートを提供しているのが&lt;code&gt;rails-composer&lt;/code&gt;というプロジェクトだ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/RailsApps/rails-composer/"&gt;RailsApps/rails-composer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このような使い方ができる。&lt;code&gt;-m&lt;/code&gt;オプションにGitHub上にあるテンプレートファイルのURLを渡す。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% rails new myapp -m https://raw.github.com/RailsApps/rails-composer/master/composer.rb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実行すると色々な質問に答えながらセットアップが進む。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;question Web server for development?
question Web server for production?
question Database used in development?
question Template engine?
question Test framework?
question Continuous testing?
question Front-end framework?
question Add support for sending email?
question Authentication?
question Authorization?
question Use a form builder gem?
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;Webサーバーには何を使うか(Puma/Unicorn/Thinなど)&lt;/li&gt;
&lt;li&gt;DBには何を使うか&lt;/li&gt;
&lt;li&gt;テンプレートエンジンには何を使うか(ERB/Haml/Slim)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などなど。質問の答えによって追加されるgemや配置される設定ファイルなどが変わる。&lt;/p&gt;
&lt;p&gt;一例として全ての出力をGistに貼ってみた。とてもじゃないけど全文をembedする気にはなれなかった。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/pi-chan/16e053d83cabcb498336"&gt;https://gist.github.com/pi-chan/16e053d83cabcb498336&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;プロダクション運用するアプリケーションの場合はよく考えた上でミニマルなテンプレートを使うのが適切だろうけれど、検証のためにとりあえず作ってみるといった用途の場合はrails-composerのような全部入りのテンプレートでもいいかもしれない。&lt;/p&gt;</description></item><item><title>PostgresSQL+ActiveRecordのwhereで大文字小文字を無視</title><link>https://blog.piyo.tech/posts/2014-05-24-190000/</link><pubDate>Sat, 24 May 2014 19:00:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-24-190000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7f74be95-2281-4a2f-a03a-6445baaab2fd/12d244aaf283b54c525f8f912cf2bd80/deep/0/postgresql.png" alt=""&gt;&lt;/p&gt;
&lt;h1 id="sqlのlower"&gt;SQLのlower&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Model&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(&lt;span style="color:#e6db74"&gt;&amp;#34;lower(name) like ?&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;%john%&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_sql
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# SELECT \&amp;#34;models\&amp;#34;.* FROM \&amp;#34;models\&amp;#34; WHERE (lower(name) like &amp;#39;%john%&amp;#39;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="sqlのilike"&gt;SQLのILIKE&lt;/h1&gt;
&lt;p&gt;PosgreSQLではILIKEが使える。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Model&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(&lt;span style="color:#e6db74"&gt;&amp;#34;name ilike ?&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;%john%&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_sql
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# SELECT \&amp;#34;models\&amp;#34;.* FROM \&amp;#34;models\&amp;#34; WHERE (name ilike &amp;#39;%john%&amp;#39;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="arelを使う"&gt;arelを使う&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;t &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Model&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;arel_table
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Model&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(t&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:name&lt;/span&gt;&lt;span style="color:#f92672"&gt;].&lt;/span&gt;matches(&lt;span style="color:#e6db74"&gt;&amp;#34;%john%&amp;#34;&lt;/span&gt;))&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_sql
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# SELECT \&amp;#34;models\&amp;#34;.* FROM \&amp;#34;models\&amp;#34; WHERE (\&amp;#34;models\&amp;#34;.\&amp;#34;name\&amp;#34; ILIKE &amp;#39;%john%&amp;#39;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;matches&lt;/code&gt;が&lt;code&gt;ILIKE&lt;/code&gt;を使ってくれる。&lt;/p&gt;</description></item><item><title>大きい1枚のPDFをA4サイズ複数枚に分割して印刷する</title><link>https://blog.piyo.tech/posts/2014-05-23-203000/</link><pubDate>Fri, 23 May 2014 20:30:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-23-203000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7f9b7db4-ef9a-4b58-97cd-ef226cd7a987/663424ca08e66e0626446be8b0b58bc8/deep/0/imgres.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;あと3週間でワールドカップが開幕する。僕は重度のサッカーファンで試合日程やグループ分けなどがわかるような情報をリビングに印刷して貼りたいと思っている。&lt;/p&gt;
&lt;p&gt;そういった用途ではA4サイズの紙では物足りない。お祭り気分がまったくない。どうせなら派手にやりたい。&lt;/p&gt;
&lt;p&gt;というわけで、大きめの画像を数枚にわけて印刷することにした。&lt;/p&gt;
&lt;h1 id="素材"&gt;素材&lt;/h1&gt;
&lt;p&gt;まずは素材を探す。画像検索を駆使し使い勝手がよさそうだったこれに狙いを定めた。PDFでダウンロードできる。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://smartcoder247.wordpress.com/tag/fifa-world-cup-2014-excel-chart/#ChartOptionC"&gt;FIFA world cup 2014 Excel chart | SmartCoder247&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;検索キーワードとしては、&lt;code&gt;world cup 2014 wall chart&lt;/code&gt;がよさそう。&lt;/p&gt;
&lt;h1 id="poster-driver"&gt;Poster Driver&lt;/h1&gt;
&lt;p&gt;続いてPoster Driverというツールをインストールする。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;PosterDividerは画像ファイルやPDFを数ページに分割します。これによって家庭のプリンターで大きなポスターを作ることができます。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://sourceforge.jp/projects/posterdivider/"&gt;PosterDivider プロジェクト日本語トップページ - SourceForge.JP&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PosterDividerは画像ファイルかPDFファイルを読み込むことができる。最終的に欲しいサイズや印刷用紙のサイズなどのパラメータを調整し出力ボタンを押せば、PosterDividerが計算してくれたページ数のPDFファイルを書き出してくれる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/8cb5213b-6bb5-4ac0-b434-62f57402ce93/0579d5038915be8a6d5e5db8308a2393/deep/0/screenshot_339.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;画像右下にプレビューが出ているのがわかる。&lt;/p&gt;
&lt;p&gt;縦置きにしか対応していない感じなのとインターフェースがだいぶイケてないところに若干の不満があるが、滅多に使わないのでよしとする。&lt;/p&gt;
&lt;p&gt;書きだされたPDFファイルはこんなふうになる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/fc4bf307-60cf-4abf-ac25-bbf87e453760/a1dfc6bafbbe2b6123afe29594556a09/deep/0/screenshot_340.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;あとは印刷して貼り合わせればOK。ちょっと手間だけど、お祭り気分のためにはそのぐらい頑張る。&lt;/p&gt;</description></item><item><title>自サイトへのはてなブックマークを監視する</title><link>https://blog.piyo.tech/posts/2014-05-22-200000/</link><pubDate>Thu, 22 May 2014 20:00:04 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-22-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/3e976567-9515-4f74-a117-5d9b887c064a/7c3858ca5e559fb08509db5ac564b81d/deep/0/20131011192039.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;誰かがブックマークつけてくれたときに2件目にセルフブックマークして新着にでも入ってくんねーかな活動のときに便利な方法を知った。&lt;/p&gt;
&lt;p&gt;はてなブックマークにはブックマークを新着順に表示してくれる機能がある。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://b.hatena.ne.jp/bookmarklist"&gt;はてなブックマーク - 新着ブックマーク&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そしてこの機能にはURLによる絞り込み機能がついている。自分のブログのURLで絞り込むことで自分のブログについたブックマークのみを新着順に閲覧できる。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://b.hatena.ne.jp/bookmarklist?url=https://blog.piyo.tech"&gt;http://b.hatena.ne.jp/bookmarklist?url=https://blog.piyo.tech&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そして、このページにはRSSフィードが提供されている。&lt;/p&gt;
&lt;p&gt;…あとは…わかるな？&lt;/p&gt;</description></item><item><title>RailsのRakeタスクが定義される順番</title><link>https://blog.piyo.tech/posts/2014-05-21-203000/</link><pubDate>Wed, 21 May 2014 20:30:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-21-203000/</guid><description>&lt;p&gt;Railsで使うRakeタスクは大きくわけて3種類あり、普通はこの順番で定義されることになっている。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;gemのタスク&lt;/li&gt;
&lt;li&gt;アプリケーション固有のタスク&lt;/li&gt;
&lt;li&gt;Railsのタスク&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;まずソースコードを読んでみた。&lt;/p&gt;
&lt;h1 id="rakefile"&gt;Rakefile&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Rakefile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;expand_path(&lt;span style="color:#e6db74"&gt;&amp;#39;../config/application&amp;#39;&lt;/span&gt;, __FILE__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;.&lt;/span&gt;load_tasks
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;config/application.rb&lt;/code&gt;を読んでから&lt;code&gt;Rails.application.load_tasks&lt;/code&gt;を呼ぶ。&lt;/p&gt;
&lt;h1 id="railsapplicationload_tasks"&gt;Rails.application.load_tasks&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;Rails.application.load_tasks&lt;/code&gt;は&lt;code&gt;railtie&lt;/code&gt;の&lt;code&gt;Rails::Engine&lt;/code&gt;に定義されている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# railties-4.1.0/lib/rails/engine.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;load_tasks&lt;/span&gt;(app&lt;span style="color:#f92672"&gt;=&lt;/span&gt;self)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#34;rake&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; run_tasks_blocks(app)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; self
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この中で呼ばれている&lt;code&gt;run_tasks_blocks&lt;/code&gt;は&lt;code&gt;Engine&lt;/code&gt;のサブクラスである、&lt;code&gt;Rails::Application&lt;/code&gt;に定義されていて、実装は次のようになっている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# railties-4.1.0/lib/rails/application.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;run_tasks_blocks&lt;/span&gt;(app) &lt;span style="color:#75715e"&gt;#:nodoc:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; railties&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each { &lt;span style="color:#f92672"&gt;|&lt;/span&gt;r&lt;span style="color:#f92672"&gt;|&lt;/span&gt; r&lt;span style="color:#f92672"&gt;.&lt;/span&gt;run_tasks_blocks(app) }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#34;rails/tasks&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; task &lt;span style="color:#e6db74"&gt;:environment&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ActiveSupport&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;on_load(&lt;span style="color:#e6db74"&gt;:before_initialize&lt;/span&gt;) { config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;eager_load &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; require_environment!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このうちの最初の3行が最初に挙げた3種類のタスクの定義に相当する。&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;gemのタスク&lt;/li&gt;
&lt;li&gt;アプリケーション固有のタスク&lt;/li&gt;
&lt;li&gt;Railsのタスク&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2 id="gemのタスク"&gt;gemのタスク&lt;/h2&gt;
&lt;p&gt;gem用のタスクというものがある。たとえば&lt;code&gt;db:migrate&lt;/code&gt;はActiveRecordのRakeタスクで、このタスクは&lt;code&gt;activerecord-4.1.0/lib/active_record/railties/databases.rake&lt;/code&gt;に定義されている。これをここではgem用のタスクと呼ぶことにする。&lt;/p&gt;
&lt;p&gt;gem用のタスクはRailtieを介して定義されている。&lt;/p&gt;
&lt;p&gt;まず&lt;code&gt;ActiveRecord::Railtie&lt;/code&gt;のクラス定義でスーパークラスである&lt;code&gt;Rails::Railtie&lt;/code&gt;の&lt;code&gt;rake_task&lt;/code&gt;メソッドが呼ばれ、タスクの定義がブロックとして渡されている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# activerecord-4.1.0/lib/active_record/railtie.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;rake_tasks &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ... 略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; load &lt;span style="color:#e6db74"&gt;&amp;#34;active_record/railties/databases.rake&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この&lt;code&gt;rake_tasks&lt;/code&gt;メソッドは単にブロックをArrayとして取っておくだけのものとなっている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rake_tasks&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;blk)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; @rake_tasks &lt;span style="color:#f92672"&gt;||=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; @rake_tasks &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; blk &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; blk
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; @rake_tasks
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここで取っておいたブロックは、RailsのRakeファイルから呼び出される&lt;code&gt;load_tasks&lt;/code&gt;において、このコードの部分&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;railties&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each { &lt;span style="color:#f92672"&gt;|&lt;/span&gt;r&lt;span style="color:#f92672"&gt;|&lt;/span&gt; r&lt;span style="color:#f92672"&gt;.&lt;/span&gt;run_tasks_blocks(app) }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;で実行され、各gemのタスクが定義されることとなる。&lt;/p&gt;
&lt;h2 id="アプリケーション固有のタスク"&gt;アプリケーション固有のタスク&lt;/h2&gt;
&lt;p&gt;アプリケーション固有のタスクというのは、&lt;code&gt;lib/tasks/*.rake&lt;/code&gt;という名前で定義すアプリケーション専用のRakeタスクのことを言っている（勝手に呼んでいる）。&lt;/p&gt;
&lt;p&gt;このファイルがどこで読み込まれているかを知るためには&lt;code&gt;Rails::Application.run_tasks_block&lt;/code&gt;中の&lt;code&gt;super&lt;/code&gt;という呼び出しを見ていく必要がある。&lt;code&gt;super&lt;/code&gt;である&lt;code&gt;Rails::Engine.run_tasks_blocks&lt;/code&gt;のコードは次のとおり。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;run_tasks_blocks&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;) &lt;span style="color:#75715e"&gt;#:nodoc:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; paths&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;lib/tasks&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;].&lt;/span&gt;existent&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sort&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each { &lt;span style="color:#f92672"&gt;|&lt;/span&gt;ext&lt;span style="color:#f92672"&gt;|&lt;/span&gt; load(ext) }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここでの&lt;code&gt;super&lt;/code&gt;は&lt;code&gt;@rake_tasks&lt;/code&gt;が持っているコードブロックを実行するもので、gem用のタスクのときに使われているがRailsアプリケーションとしては使われていないはず。&lt;/p&gt;
&lt;p&gt;アプリケーション固有のタスクはメソッド2行目のこの部分、&lt;code&gt;paths[&amp;quot;lib/tasks&amp;quot;].existent.sort.each { |ext| load(ext) }&lt;/code&gt;でロードされる。コードは見たまんま。&lt;/p&gt;
&lt;h2 id="railsのタスク"&gt;Railsのタスク&lt;/h2&gt;
&lt;p&gt;まだ見ていない最後の行でRailsのタスクが定義される。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;rails/tasks&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;requireされている&lt;code&gt;tasks.rb&lt;/code&gt;にはタスクが定義されているファイルを複数ロードするというコードが書かれている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# railties-4.1.0/lib/rails/tasks.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Load Rails Rakefile extensions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;%w(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; annotations
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; documentation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; framework
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; log
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; middleware
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; misc
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; routes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; statistics
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; tmp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;task&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; load &lt;span style="color:#e6db74"&gt;&amp;#34;rails/tasks/&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;task&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.rake&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# railties-4.1.0/lib/rails/tasks/routes.rake&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;desc &lt;span style="color:#e6db74"&gt;&amp;#39;Print out all defined routes in match order, with names. Target specific controller with CONTROLLER=x.&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;task &lt;span style="color:#e6db74"&gt;routes&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:environment&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; all_routes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;.&lt;/span&gt;routes&lt;span style="color:#f92672"&gt;.&lt;/span&gt;routes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;action_dispatch/routing/inspector&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; inspector &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActionDispatch&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Routing&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;RoutesInspector&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(all_routes)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; puts inspector&lt;span style="color:#f92672"&gt;.&lt;/span&gt;format(&lt;span style="color:#66d9ef"&gt;ActionDispatch&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Routing&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;ConsoleFormatter&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new, &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;CONTROLLER&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;rake routes&lt;/code&gt;や&lt;code&gt;rake stats&lt;/code&gt;などはここで定義されているということがわかる。&lt;/p&gt;
&lt;h1 id="rakeタスクの削除の可否"&gt;Rakeタスクの削除の可否&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-05-13-195503"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-05-13-195503" alt="RailsのRakeタスクを上書き・再定義するには - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-05-13-195503"&gt;RailsのRakeタスクを上書き・再定義するには - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;すでにロードされているRakeタスクを削除する方法がある。この記事ではアプリケーション固有のタスクを書くときに既存のタスク削除して上書きするという方法にトライした。&lt;/p&gt;
&lt;p&gt;この記事でも書いたが、アプリケーション固有のタスクを定義する段階では、Railsのタスクは削除できない。先ほど見たとおりRailsのタスクは最後に読み込まれるからだ。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Rails::Application.run_tasks_blocks&lt;/code&gt;自体をモンキーパッチしてしまうなどの方法は無くはないかもしれないが、似たようなコードをコピーしてくることになるのであまりスマートではない。となると、きれいに書く方法はないのかもしれない。&lt;/p&gt;</description></item><item><title>routes.rbでresourcesを使ったときのパラメータをid以外にする</title><link>https://blog.piyo.tech/posts/2014-05-20-200000/</link><pubDate>Tue, 20 May 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-20-200000/</guid><description>&lt;p&gt;Railsでは&lt;code&gt;has_many&lt;/code&gt;な関連を持つモデルに対してRESTなルートを簡単に定義できる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# routes.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;resources &lt;span style="color:#e6db74"&gt;:blogs&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;only&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:index&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; resources &lt;span style="color:#e6db74"&gt;:posts&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;only&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:index&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このようなルートが定義される。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% rake routes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; Prefix Verb URI Pattern Controller#Action
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; blog_posts GET /blogs/:blog_id/posts&lt;span style="color:#f92672"&gt;(&lt;/span&gt;.:format&lt;span style="color:#f92672"&gt;)&lt;/span&gt; posts#index
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; blogs GET /blogs&lt;span style="color:#f92672"&gt;(&lt;/span&gt;.:format&lt;span style="color:#f92672"&gt;)&lt;/span&gt; blogs#index
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このときのパラメータである&lt;code&gt;:blog_id&lt;/code&gt;にはデフォルトでは&lt;code&gt;Blog&lt;/code&gt;モデルのidが使われる。そしてこれらのルートに相当するURLは&lt;code&gt;/blogs/1/posts&lt;/code&gt;などとなる。&lt;/p&gt;
&lt;h1 id="id以外のカラムをパラメータにする"&gt;id以外のカラムをパラメータにする&lt;/h1&gt;
&lt;p&gt;例えば&lt;code&gt;Blog&lt;/code&gt;モデルにはアプリケーション内でユニークなユーザー名のようなものを持っているとし、それをルートのパラメータにしたいというケースを考える。&lt;/p&gt;
&lt;p&gt;これが実現すると&lt;code&gt;/blogs/xoyip/posts&lt;/code&gt;というURLが使えるようになる。個人的には先ほど書いたものよりかっこいいと思う。よくわからない数字が入るのは好きじゃない。&lt;/p&gt;
&lt;h2 id="やり方"&gt;やり方&lt;/h2&gt;
&lt;p&gt;Blogモデルに&lt;code&gt;to_param&lt;/code&gt;メソッドを定義する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Blog&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;to_param&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; user_name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;to_param&lt;/code&gt;はActiveRecord::IntegrationモジュールのメソッドでStringを返す。モデルのインスタンスからURLを生成するときに使われるメソッドで、ソースを見ると確かにデフォルトではidを文字列にして返しているのがわかる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ActiveRecord::Integration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;to_param&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; id &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; id&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="パラメータ名を変える"&gt;パラメータ名を変える&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;to_param&lt;/code&gt;のオーバーライドによってURLに使うパラメータは変わったけれど、&lt;code&gt;rake routes&lt;/code&gt;が吐き出す一覧における表記はidのままとなっていて気持ち悪い。これを変えておいたほうがあとあとわかりやすいので、こちらも変更する。&lt;/p&gt;
&lt;p&gt;routes.rbで使う&lt;code&gt;resources&lt;/code&gt;メソッドは&lt;code&gt;param&lt;/code&gt;という引数を取ることができる。ここにシンボルを書いておくと、パラメータの名前が書いたものに変わるという仕組みになっている。&lt;/p&gt;
&lt;p&gt;先ほどの例でいくとこのように書くことができ、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# routes.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;resources &lt;span style="color:#e6db74"&gt;:blogs&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;param&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:user_name&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;only&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:index&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; resources &lt;span style="color:#e6db74"&gt;:posts&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;only&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:index&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;rake routesの出力はこのように変わる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% rake routes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; Prefix Verb URI Pattern Controller#Action
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; blog_posts GET /blogs/:blog_user_name/posts&lt;span style="color:#f92672"&gt;(&lt;/span&gt;.:format&lt;span style="color:#f92672"&gt;)&lt;/span&gt; posts#index
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; blogs GET /blogs&lt;span style="color:#f92672"&gt;(&lt;/span&gt;.:format&lt;span style="color:#f92672"&gt;)&lt;/span&gt; blogs#index
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コントローラ側でパラメータを扱うときには注意が必要で、それまで&lt;code&gt;param[:blog_id]&lt;/code&gt;のように書いていたところを&lt;code&gt;param[:blog_user_name]&lt;/code&gt;などと変更する必要がある。&lt;/p&gt;
&lt;p&gt;少し手間かもしれないが、可読性のことを考えてパラメータ名も変更しておいたほうがいい。&lt;/p&gt;</description></item><item><title>Rubyで標準出力を文字列で乗っ取る</title><link>https://blog.piyo.tech/posts/2014-05-19-203000/</link><pubDate>Mon, 19 May 2014 20:30:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-19-203000/</guid><description>&lt;p&gt;この間書いたこの記事のコードがDRYじゃないので少し修正した。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-05-14-201109"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-05-14-201109" alt="GrapeのAPIのエンドポイントをrake routes的に出力する - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-05-14-201109"&gt;GrapeのAPIのエンドポイントをrake routes的に出力する - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;やりたかったのは記事タイトルの通りで、Grapeで定義したAPIの結果を&lt;code&gt;rake routes&lt;/code&gt;の結果と一緒に出力するというもの。&lt;/p&gt;
&lt;p&gt;ソースを深く読んで行くと既存の&lt;code&gt;rake routes&lt;/code&gt;タスクの乗っ取りはそう簡単にはいかなかったため、別のタスクで&lt;code&gt;rake routes&lt;/code&gt;と同じような処理をした上、さらにGrapeの情報も出力するってことをやっていた。&lt;/p&gt;
&lt;p&gt;この、&lt;strong&gt;&lt;code&gt;rake routes&lt;/code&gt;と同じような処理&lt;/strong&gt;の書き方がまずくて、このタスクの該当部分をそのまま持ってくるといういけていない書き方をしてしまっていた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;task &lt;span style="color:#e6db74"&gt;my_routes&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:environment&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# この4行はRailsの中からほぼコピペしている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; all_routes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;.&lt;/span&gt;routes&lt;span style="color:#f92672"&gt;.&lt;/span&gt;routes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;action_dispatch/routing/inspector&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; inspector &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActionDispatch&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Routing&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;RoutesInspector&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(all_routes)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; output &lt;span style="color:#f92672"&gt;=&lt;/span&gt; inspector&lt;span style="color:#f92672"&gt;.&lt;/span&gt;format(&lt;span style="color:#66d9ef"&gt;ActionDispatch&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Routing&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;ConsoleFormatter&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new, &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;CONTROLLER&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# このあとoutput を使って何かする、みたいな。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これはDRYの原則に反するし、気持ち悪い。そこでなんとかする方法を考えた。&lt;/p&gt;
&lt;p&gt;まず、この&lt;code&gt;my_routes&lt;/code&gt;タスクからデフォルトの&lt;code&gt;routes&lt;/code&gt;タスクを呼ぶことを考えた。これはとても簡単で、&lt;code&gt;Rake::Task[&amp;quot;routes&amp;quot;].execute&lt;/code&gt;というコードで呼び出すことができる。&lt;/p&gt;
&lt;p&gt;これでできたと思いたいところだが、実はこの&lt;code&gt;routes&lt;/code&gt;タスク、内部で出力用データを作ってそのまま標準出力にputsしている。&lt;code&gt;my_routes&lt;/code&gt;でやりたかったのは&lt;code&gt;routes&lt;/code&gt;の結果を受け取って、その内容を元に出力テキストの調整をするのでこれでは困る。&lt;/p&gt;
&lt;p&gt;まあきっとRubyだから標準出力乗っ取るぐらい余裕だろうと思ったが、その通りだった。&lt;/p&gt;
&lt;h1 id="capture_io"&gt;capture_io&lt;/h1&gt;
&lt;p&gt;minitestの中に&lt;code&gt;capture_io&lt;/code&gt;というメソッドがあって、これを使うと標準出力と標準エラーを則って文字列として取り出すことができる。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-capture_io"&gt;module Minitest::Assertions - minitest-5.3.4 Documentation&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="使い方"&gt;使い方&lt;/h2&gt;
&lt;p&gt;まず使い方から。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;task &lt;span style="color:#e6db74"&gt;my_routes&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:environment&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; out, err &lt;span style="color:#f92672"&gt;=&lt;/span&gt; capture_io &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Raks&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Task&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;routes&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;].&lt;/span&gt;execute
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# このあとout を使って何かする、みたいな。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="capture_ioのソース"&gt;capture_ioのソース&lt;/h2&gt;
&lt;p&gt;このためだけに&lt;code&gt;minitest&lt;/code&gt;をrequireするのはどうかと思ったので&lt;code&gt;capture_io&lt;/code&gt;のコードは適当に貼り付けた。ああ。またDRYじゃない。&lt;/p&gt;
&lt;p&gt;ソースはこんな感じ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# File lib/minitest/assertions.rb, line 399&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;capture_io&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; _synchronize &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;begin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;stringio&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; captured_stdout, captured_stderr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;StringIO&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new, &lt;span style="color:#66d9ef"&gt;StringIO&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; orig_stdout, orig_stderr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $stdout, $stderr
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; $stdout, $stderr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; captured_stdout, captured_stderr
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;yield&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; captured_stdout&lt;span style="color:#f92672"&gt;.&lt;/span&gt;string, captured_stderr&lt;span style="color:#f92672"&gt;.&lt;/span&gt;string
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ensure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; $stdout &lt;span style="color:#f92672"&gt;=&lt;/span&gt; orig_stdout
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; $stderr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; orig_stderr
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Rails x PostgreSQL dbseed用sqlを作る</title><link>https://blog.piyo.tech/posts/2014-05-18-200000/</link><pubDate>Sun, 18 May 2014 20:00:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-18-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7f74be95-2281-4a2f-a03a-6445baaab2fd/12d244aaf283b54c525f8f912cf2bd80/deep/0/postgresql.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;今日から文体を常体にする。&lt;/p&gt;
&lt;p&gt;データベースに最初からデータを入れておきたい場合、Railsでは&lt;code&gt;rake db:seed&lt;/code&gt;を使う。このタスクによりRailsアプリケーションがロードされた状態で&lt;code&gt;db/seeds.rb&lt;/code&gt;に書いたコードが実行される。&lt;/p&gt;
&lt;p&gt;シード用データを作ること自体が重い場合（例えば外部のAPIを呼ばなければいけないとか、たくさんのjsonファイルを解析しなければいけないとか）、ローカルで流したスクリプトを再度プロダクション環境で流すのは馬鹿らしいので、ローカルのデータベースをダンプしたものを使うのが賢いのだと思う。&lt;/p&gt;
&lt;p&gt;環境は次のものを想定する。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Heroku&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PostgreSQLでは&lt;code&gt;pg_dump dbname &amp;gt; dump.sql&lt;/code&gt;や&lt;code&gt;psql dbname &amp;lt; dump.sql&lt;/code&gt;ようなコマンドを使えるが、Herokuのような環境ではそれらのコマンドを直接叩けないことも多い。&lt;/p&gt;
&lt;p&gt;そのためsqlファイルのインポートはActiveRecord経由で行うこととする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# db/seeds.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;sql &lt;span style="color:#f92672"&gt;=&lt;/span&gt; open(&lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(&lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;root, &lt;span style="color:#e6db74"&gt;&amp;#34;db&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;seeds.sql&amp;#34;&lt;/span&gt;))&lt;span style="color:#f92672"&gt;.&lt;/span&gt;read
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;connection&lt;span style="color:#f92672"&gt;.&lt;/span&gt;execute sql
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;seeds.sqlというダンプファイルをリポジトリに含めてき、&lt;code&gt;rake db:seed&lt;/code&gt;でダンプファイルをインポートをするだけ。&lt;/p&gt;
&lt;p&gt;あとはこのコードが読めるダンプファイルを書き出せばいい。&lt;/p&gt;
&lt;h1 id="pg_dump"&gt;pg_dump&lt;/h1&gt;
&lt;p&gt;pg_dumpの詳しいことは触れないが、基本的にはデータベースを指定して実行するとダンプしてくれる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% pg_dump mydatabase &amp;gt; seeds.sql
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドではスキーマとデータ自体が両方出力されるが、このダンプファイルは使えない。結論から言うとpg_dumpコマンドには次の2つのオプションをつける。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% pg_dump mydatabase --data-only --inserts &amp;gt; seeds.sql
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="data-only"&gt;&amp;ndash;data-only&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;--data-only&lt;/code&gt;オプション（または、&lt;code&gt;-a&lt;/code&gt;オプション）でデータのみをダンプできる。Railsではデータベースのスキーマはrakeタスクで管理するため、ダンプファイルにスキーマは不要。&lt;/p&gt;
&lt;h2 id="inserts"&gt;&amp;ndash;inserts&lt;/h2&gt;
&lt;p&gt;このオプションにより、ダンプファイルのフォーマットをINSERT文を使ったものにできる。指定がない場合はCOPYを使ったものになるが、ActiveRecordから実行できない。&lt;/p&gt;
&lt;h1 id="微調整"&gt;微調整&lt;/h1&gt;
&lt;p&gt;ファイルフォーマット的にはここまでの作業で問題なくなったが、余計なデータが一種類入っている。それはschema_migrationのデータだ。&lt;/p&gt;
&lt;p&gt;ダンプしたファイルを覗くと、&lt;code&gt;INSERT INTO schema_migrations VALUES ('20140513040222');&lt;/code&gt;といった行があるのがわかる。この情報は&lt;code&gt;rake db:migrate&lt;/code&gt;を実行したときにRailsが入れてくれるデータで、同じデータをINSERTするとエラーとなってしまう。そのため、これらの行を削除する必要がある。&lt;/p&gt;
&lt;p&gt;seeds.sqlが完成したので、このファイルをリポジトリにaddしてcommitする。&lt;/p&gt;
&lt;p&gt;あとはHerokuにデプロイして、データベース周りのタスクを実行すればよい。コマンドで言うと次のコマンドとなる。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;git push heroku&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;heroku run rake db:migrate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;heroku run rake db:seed&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>RailsのDBマイグレーションでカラムを変更する</title><link>https://blog.piyo.tech/posts/2014-05-17-200000/</link><pubDate>Sat, 17 May 2014 20:00:05 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-17-200000/</guid><description>&lt;p&gt;あとからデフォルト値を変えたり、Nullableをやめたりってときのやりかたを忘れがちなのでメモ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MigrationName&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Migration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;change&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; change_column &lt;span style="color:#e6db74"&gt;:models&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:column_name&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:integer&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;null&lt;/span&gt;:&lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;default&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こんな感じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;change_column :&lt;span style="color:#960050;background-color:#1e0010"&gt;モデル複数形&lt;/span&gt;, :&lt;span style="color:#960050;background-color:#1e0010"&gt;属性&lt;/span&gt;, :&lt;span style="color:#960050;background-color:#1e0010"&gt;型&lt;/span&gt;, {&lt;span style="color:#960050;background-color:#1e0010"&gt;オプション&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Pry便利だけどスタックトレース見られない、を解決</title><link>https://blog.piyo.tech/posts/2014-05-16-200000/</link><pubDate>Fri, 16 May 2014 20:00:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-16-200000/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b1517cbc-ca4e-4e78-9299-2b22177be595/6c99722eb274398e93986dc786423a68/deep/0/pry_logo.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Pryまじ便利。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://morizyun.github.io/blog/pry-command-rails-ruby/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://morizyun.github.io/blog/pry-command-rails-ruby/" alt="Pryが真の力を発揮してくれる19個のコマンドとコマンドの自作方法[Rails] - 酒と泪とRubyとRailsと" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://morizyun.github.io/blog/pry-command-rails-ruby/"&gt;Pryが真の力を発揮してくれる19個のコマンドとコマンドの自作方法[Rails] - 酒と泪とRubyとRailsと&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://morizyun.github.io/blog/pry-command-rails-ruby/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://morizyun.github.io/blog/pry-command-rails-ruby/" alt="はてなブックマーク - Pryが真の力を発揮してくれる19個のコマンドとコマンドの自作方法[Rails] - 酒と泪とRubyとRailsと" title="はてなブックマーク - Pryが真の力を発揮してくれる19個のコマンドとコマンドの自作方法[Rails] - 酒と泪とRubyとRailsと" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;ちなみにPryにはこういう意味があったらしい。知りませんでした。ロゴを見る限りてこをイメージしているらしい。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://eow.alc.co.jp/search?q=pry"&gt;英辞郎 on the WEB&lt;/a&gt;より&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pry
【1名】
のぞき見、詮索
詮索好きな人
【1自動】
のぞき込む、詮索する、首を突っ込む、ほじくる
【2名】
てこ、てこ作用（で動かす道具）、てこを応用した道具【2他動】
～をてこで動かす、てこで上げる、苦労して引き出す
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;デバッグも&lt;code&gt;debugger&lt;/code&gt;よりも&lt;code&gt;pry-debugger&lt;/code&gt;使っています。&lt;code&gt;pry-debugger&lt;/code&gt;は&lt;code&gt;pry&lt;/code&gt;にステップ実行などの機能を追加するgemです。ブレークしたいところに&lt;code&gt;binding.pry&lt;/code&gt;と書いておくと、そのときのスコープでPryが起動します。&lt;/p&gt;
&lt;h1 id="bindingpryとは"&gt;binding.pryとは&lt;/h1&gt;
&lt;p&gt;ちょっと脱線。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;binding&lt;/code&gt;というのはKernelモジュールのbindingメソッドで、Bindingクラスのオブジェクトを返します。Bindingオブジェクトは&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ローカル変数のテーブルとself、モジュールのネストなどの情報を保持するオブジェクトのクラスです。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;というものです。&lt;/p&gt;
&lt;p&gt;また、&lt;code&gt;binding.pry&lt;/code&gt;の&lt;code&gt;pry&lt;/code&gt;の部分は、&lt;code&gt;pry&lt;/code&gt;という名前のメソッドで、&lt;code&gt;Object&lt;/code&gt;クラスに定義されています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# pry-0.9.12.6/lib/pry/core_extensions.rb より&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Object&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pry&lt;/span&gt;(object&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;, hash&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; object&lt;span style="color:#f92672"&gt;.&lt;/span&gt;nil? &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Hash&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; object
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Pry&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;start(self, object &lt;span style="color:#f92672"&gt;||&lt;/span&gt; {})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Pry&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;start(object, hash)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;binding.pry&lt;/code&gt;の場合、引数のないpryメソッド呼び出しなので、&lt;code&gt;Pry.start&lt;/code&gt;にself（つまりbinding）を渡してPryを起動するということになるわけですね〜。&lt;/p&gt;
&lt;h1 id="pry-stack_explorer"&gt;pry-stack_explorer&lt;/h1&gt;
&lt;p&gt;本題に戻ります。&lt;/p&gt;
&lt;p&gt;Pryは超便利だけど、単体ではデバッガとしての機能やスタックを追う機能はあります。デバッガの機能は&lt;code&gt;pry-debugger&lt;/code&gt;で使えるようになりました。&lt;/p&gt;
&lt;p&gt;スタックトレースを見たい場合は&lt;code&gt;pry-stack_explorer&lt;/code&gt;というgemを導入する必要があります。それにしてもアンダースコアとダッシュを混ぜた名前を付けるなんて、、、！&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pry/pry-stack_explorer"&gt;pry/pry-stack_explorer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pry-stack-explorer&lt;/code&gt;をrequireした状態で&lt;code&gt;binding.pry&lt;/code&gt;によりPryを起動したとき、次のコマンドが使えるようになります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;down&lt;/code&gt; Go down to the callee&amp;rsquo;s context.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;frame&lt;/code&gt; Switch to a particular frame.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;show-stack&lt;/code&gt; Show all frames&lt;/li&gt;
&lt;li&gt;&lt;code&gt;up&lt;/code&gt; Go up to the caller&amp;rsquo;s context.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;show-stackでスタックトレースがわかるし、up/downでコンテキストの移動ができたりします。Pryという強力な環境でスタックトレースまでできるので、ライブラリの挙動を調べたりデバッグするのによさそう。&lt;/p&gt;</description></item><item><title>Grapeを使ったAPI実装でのネストやパラメータ</title><link>https://blog.piyo.tech/posts/2014-05-15-201100/</link><pubDate>Thu, 15 May 2014 20:11:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-15-201100/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/97c337d2-68bd-40e6-ab7c-a0a8fe470b8d/4dd82c750c456853ae1e5c5e6362218e/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-14-9-04.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Grapeをもう少し使ってみました。関連記事は↓&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-05-12-204748"&gt;RailsのGrapeとJbuilderでAPI開発 - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="基本形"&gt;基本形&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# app/api/api.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;resource &lt;span style="color:#e6db74"&gt;:items&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; get &lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;jbuilder&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#39;items&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; @items &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Item&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;all
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="パラメータを受け取る"&gt;パラメータを受け取る&lt;/h1&gt;
&lt;p&gt;全てのItemではなく、idに該当するItemだけが欲しいとき。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;resource &lt;span style="color:#e6db74"&gt;:items&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; get &lt;span style="color:#e6db74"&gt;&amp;#39;/:id&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;jbuilder&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#39;item&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; @item &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Item&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find_by_id(params&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:id&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;/api/items/1&lt;/code&gt;というエンドポイントで&lt;code&gt;id=1&lt;/code&gt;のItemが得られます。&lt;/p&gt;
&lt;h1 id="ネストする"&gt;ネストする&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Item&lt;/li&gt;
&lt;li&gt;Entry&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;というモデルがあって、Item has many Entriesな関連を持っている場合はリソースをネストさせることが多いと思います。Railsのルーティングとかでもよくやるアレです。Grapeでも似たような書き方ができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;resource &lt;span style="color:#e6db74"&gt;:items&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; route_param &lt;span style="color:#e6db74"&gt;:item_id&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; resource &lt;span style="color:#e6db74"&gt;:entries&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; get &lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;jbuilder&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#39;entries&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; @item &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Item&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find_by_id(params&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:item_id&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; @entries &lt;span style="color:#f92672"&gt;=&lt;/span&gt; @item&lt;span style="color:#f92672"&gt;.&lt;/span&gt;entries &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; @item
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; get &lt;span style="color:#e6db74"&gt;&amp;#39;/:id&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;jbuilder&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#39;entry&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; @item &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Item&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find_by_id(params&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:item_id&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; @entry &lt;span style="color:#f92672"&gt;=&lt;/span&gt; @item&lt;span style="color:#f92672"&gt;.&lt;/span&gt;entries&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find_by_id(params&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:id&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; @item
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上のコードにより2つのAPIが定義されます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/api/items/1/entries&lt;/code&gt;でItem(id=1)のEntryを全て返す&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/api/items/1/entries/1&lt;/code&gt;でItem(id=1)のEntryのうち(id=1)のものを返す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ネストの階層はこのようになっています。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;resource :items&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;route_param :item_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;resource :entries&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;2番めに出てくる&lt;code&gt;route_param&lt;/code&gt;というのがありますが、実はこれ&lt;code&gt;resource&lt;/code&gt;のエイリアスでGrapeの中では同じように扱われます。&lt;/p&gt;
&lt;p&gt;公式ドキュメントによると元々は&lt;code&gt;namespace&lt;/code&gt;というメソッドがあって、それに対するaliasとして以下のものが定義されているようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;namespace&lt;/li&gt;
&lt;li&gt;group&lt;/li&gt;
&lt;li&gt;resource&lt;/li&gt;
&lt;li&gt;resources&lt;/li&gt;
&lt;li&gt;segment&lt;/li&gt;
&lt;li&gt;route_param&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;読みやすくなるようコンテキストに応じて使えばよいということで、上のような場合はやはり&lt;code&gt;resource(s)&lt;/code&gt;や&lt;code&gt;route_param&lt;/code&gt;が適切っぽいでしょう。&lt;/p&gt;
&lt;h1 id="api定義全体"&gt;API定義全体&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;API&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Grape&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;API&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; format &lt;span style="color:#e6db74"&gt;:json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; formatter &lt;span style="color:#e6db74"&gt;:json&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;Grape&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Formatter&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Jbuilder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; default_format &lt;span style="color:#e6db74"&gt;:json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; resource &lt;span style="color:#e6db74"&gt;:items&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; get &lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;jbuilder&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#39;items&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; @items &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Item&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;all
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; params &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; requires &lt;span style="color:#e6db74"&gt;:id&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;type&lt;/span&gt;: Integer, &lt;span style="color:#e6db74"&gt;desc&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Item ID&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; get &lt;span style="color:#e6db74"&gt;&amp;#39;/:id&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;jbuilder&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#39;item&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; @item &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Item&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find_by_id(params&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:id&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; params &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; requires &lt;span style="color:#e6db74"&gt;:item_id&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;type&lt;/span&gt;: Integer, &lt;span style="color:#e6db74"&gt;desc&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Item ID&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; route_param &lt;span style="color:#e6db74"&gt;:item_id&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; resource &lt;span style="color:#e6db74"&gt;:entries&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; get &lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;jbuilder&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#39;entries&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; @item &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Item&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find_by_id(params&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:item_id&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; @entries &lt;span style="color:#f92672"&gt;=&lt;/span&gt; @item&lt;span style="color:#f92672"&gt;.&lt;/span&gt;entries &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; @item
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; params &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; requires &lt;span style="color:#e6db74"&gt;:id&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;type&lt;/span&gt;: Integer, &lt;span style="color:#e6db74"&gt;desc&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Entry ID&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; get &lt;span style="color:#e6db74"&gt;&amp;#39;/:id&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;jbuilder&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#39;entry&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; @item &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Item&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find_by_id(params&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:item_id&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; @entry &lt;span style="color:#f92672"&gt;=&lt;/span&gt; @item&lt;span style="color:#f92672"&gt;.&lt;/span&gt;entries&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find_by_id(params&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:id&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; @item
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>GrapeのAPIのエンドポイントをrake routes的に出力する</title><link>https://blog.piyo.tech/posts/2014-05-14-201109/</link><pubDate>Wed, 14 May 2014 20:10:39 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-14-201109/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/783fa62d-cc2e-4724-b469-27c40dab804d/25cf9247130e423ac715ec3bbb125ad2/deep/0/US_Route_54_in_New_Mexico.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;RailsアプリケーションにGrapeを使って定義したエンドポイントは&lt;code&gt;rake routes&lt;/code&gt;には表示されません。表示されるのは&lt;code&gt;routes.rb&lt;/code&gt;でマウントしたAPIのルートのみ。&lt;/p&gt;
&lt;p&gt;そこで自前の&lt;code&gt;rake routes&lt;/code&gt;を定義してGrapeのAPIもroutesに表示してあげることにしました。&lt;/p&gt;
&lt;h1 id="参考"&gt;参考&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;blockquote class="twitter-tweet" lang="ja"&gt;&lt;p&gt;&lt;a href="https://twitter.com/kamipo"&gt;@kamipo&lt;/a&gt; こんなんどうでしょ &lt;a href="https://t.co/kkSyqiGott"&gt;https://t.co/kkSyqiGott&lt;/a&gt; 同僚が見つけてきた Grape の routes 出す task + Rails の routes タスク実行したら一緒に Grape のほうも出力するように調整&lt;/p&gt;&amp;mdash; Kensuke Nagae (@kyanny) &lt;a href="https://twitter.com/kyanny/statuses/392557139366932480"&gt;2013, 10月 22&lt;/a&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/kyanny/7096634"&gt;Put this file to &lt;code&gt;lib/tasks/routes.rake&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="libtasksroutesrake"&gt;lib/tasks/routes.rake&lt;/h1&gt;
&lt;p&gt;上のリンクから持ってきたものを少し変更し、task名を&lt;code&gt;routes&lt;/code&gt;としています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;desc &lt;span style="color:#e6db74"&gt;&amp;#34;API Routes&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;task &lt;span style="color:#e6db74"&gt;routes&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:environment&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;API&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;routes&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;api&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; method &lt;span style="color:#f92672"&gt;=&lt;/span&gt; api&lt;span style="color:#f92672"&gt;.&lt;/span&gt;route_method&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ljust(&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; api&lt;span style="color:#f92672"&gt;.&lt;/span&gt;route_path
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#34; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;method&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;path&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この状態で&lt;code&gt;$ rake routes&lt;/code&gt;とすると先にGrapeのエンドポイントが出力され、続いてRailsのroutesが出力されます。&lt;/p&gt;
&lt;p&gt;こんな感じ。揃っていなくて気持ち悪いですね。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; GET /blogs(.:format)
GET /blogs/:id(.:format)
GET /blogs/:blog_id/posts(.:format)
GET /blogs/:blog_id/posts/:id(.:format)
Prefix Verb URI Pattern Controller#Action
blog_posts GET /blogs/:blog_id/posts(.:format) posts#index
POST /blogs/:blog_id/posts(.:format) posts#create
new_blog_post GET /blogs/:blog_id/posts/new(.:format) posts#new
edit_blog_post GET /blogs/:blog_id/posts/:id/edit(.:format) posts#edit
blog_post GET /blogs/:blog_id/posts/:id(.:format) posts#show
PATCH /blogs/:blog_id/posts/:id(.:format) posts#update
PUT /blogs/:blog_id/posts/:id(.:format) posts#update
DELETE /blogs/:blog_id/posts/:id(.:format) posts#destroy
blogs GET /blogs(.:format) blogs#index
POST /blogs(.:format) blogs#create
new_blog GET /blogs/new(.:format) blogs#new
edit_blog GET /blogs/:id/edit(.:format) blogs#edit
blog GET /blogs/:id(.:format) blogs#show
PATCH /blogs/:id(.:format) blogs#update
PUT /blogs/:id(.:format) blogs#update
DELETE /blogs/:id(.:format) blogs#destroy
api /api API
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="デフォルトのroutesタスクを再定義しよう"&gt;デフォルトのroutesタスクを再定義しよう&lt;/h1&gt;
&lt;p&gt;Railsのデフォルトタスクは&lt;code&gt;lib/tasks&lt;/code&gt;以下のファイルの読み込み後に行われるため、&lt;code&gt;lib/tasks/routes.rake&lt;/code&gt;ファイルではデフォルトタスクの再定義はできません。&lt;/p&gt;
&lt;p&gt;Rubyだからメタに書けばできないことはないんだろうけど、いろいろ試してまだ答えに行き着いていません。今後の課題。&lt;/p&gt;
&lt;h1 id="別タスクで無理矢理解決"&gt;別タスクで無理矢理解決&lt;/h1&gt;
&lt;p&gt;実際のroutesタスクは&lt;code&gt;ruby/2.1.0/gems/railties-4.1.0/lib/rails/tasks/routes.rake&lt;/code&gt;にあります（バージョンは読み替えてもらうとして）。&lt;/p&gt;
&lt;p&gt;内容はこうなっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;desc &lt;span style="color:#e6db74"&gt;&amp;#39;Print out all defined routes in match order, with names. Target specific controller with CONTROLLER=x.&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;task &lt;span style="color:#e6db74"&gt;routes&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:environment&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; all_routes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;.&lt;/span&gt;routes&lt;span style="color:#f92672"&gt;.&lt;/span&gt;routes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;action_dispatch/routing/inspector&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; inspector &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActionDispatch&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Routing&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;RoutesInspector&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(all_routes)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; puts inspector&lt;span style="color:#f92672"&gt;.&lt;/span&gt;format(&lt;span style="color:#66d9ef"&gt;ActionDispatch&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Routing&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;ConsoleFormatter&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new, &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;CONTROLLER&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このソースを流用して、Grape APIの結果も含めて出力すりゃいいじゃんということで、ソースはこうなりました。DRY？なにそれ状態。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;desc &lt;span style="color:#e6db74"&gt;&amp;#34;Routes with API routes&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;task &lt;span style="color:#e6db74"&gt;all_routes&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:environment&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;.&lt;/span&gt;require_environment!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;action_dispatch/routing/inspector&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; all_routes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;.&lt;/span&gt;routes&lt;span style="color:#f92672"&gt;.&lt;/span&gt;routes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; inspector &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActionDispatch&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Routing&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;RoutesInspector&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(all_routes)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; output &lt;span style="color:#f92672"&gt;=&lt;/span&gt; inspector&lt;span style="color:#f92672"&gt;.&lt;/span&gt;format(&lt;span style="color:#66d9ef"&gt;ActionDispatch&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Routing&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;ConsoleFormatter&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new, &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;CONTROLLER&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; puts output
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; first_line &lt;span style="color:#f92672"&gt;=&lt;/span&gt; output&lt;span style="color:#f92672"&gt;.&lt;/span&gt;lines&lt;span style="color:#f92672"&gt;.&lt;/span&gt;first
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; verb_index &lt;span style="color:#f92672"&gt;=&lt;/span&gt; first_line&lt;span style="color:#f92672"&gt;.&lt;/span&gt;index(&lt;span style="color:#e6db74"&gt;&amp;#34;Verb&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; pattern_index &lt;span style="color:#f92672"&gt;=&lt;/span&gt; first_line&lt;span style="color:#f92672"&gt;.&lt;/span&gt;index(&lt;span style="color:#e6db74"&gt;&amp;#34;URI Pattern&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;API&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;routes&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;api&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; method &lt;span style="color:#f92672"&gt;=&lt;/span&gt; api&lt;span style="color:#f92672"&gt;.&lt;/span&gt;route_method
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;ljust(pattern_index&lt;span style="color:#f92672"&gt;-&lt;/span&gt;verb_index&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# &amp;#34;GET&amp;#34; =&amp;gt; &amp;#34;GET &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;rjust(pattern_index&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# &amp;#34;GET &amp;#34; =&amp;gt; &amp;#34; GET &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; api&lt;span style="color:#f92672"&gt;.&lt;/span&gt;route_path
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;method&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;path&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ほんで、&lt;code&gt;$ rake all_routes&lt;/code&gt;ってやるとこういう出力が得られるようになります。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; Prefix Verb URI Pattern Controller#Action
blog_posts GET /blogs/:blog_id/posts(.:format) posts#index
POST /blogs/:blog_id/posts(.:format) posts#create
new_blog_post GET /blogs/:blog_id/posts/new(.:format) posts#new
edit_blog_post GET /blogs/:blog_id/posts/:id/edit(.:format) posts#edit
blog_post GET /blogs/:blog_id/posts/:id(.:format) posts#show
PATCH /blogs/:blog_id/posts/:id(.:format) posts#update
PUT /blogs/:blog_id/posts/:id(.:format) posts#update
DELETE /blogs/:blog_id/posts/:id(.:format) posts#destroy
blogs GET /blogs(.:format) blogs#index
POST /blogs(.:format) blogs#create
new_blog GET /blogs/new(.:format) blogs#new
edit_blog GET /blogs/:id/edit(.:format) blogs#edit
blog GET /blogs/:id(.:format) blogs#show
PATCH /blogs/:id(.:format) blogs#update
PUT /blogs/:id(.:format) blogs#update
DELETE /blogs/:id(.:format) blogs#destroy
api /api API
GET /blogs(.:format)
GET /blogs/:id(.:format)
GET /blogs/:blog_id/posts(.:format)
GET /blogs/:blog_id/posts/:id(.:format)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;さっきより全然いい。コードは気持ち悪いけど結果はOKです。とりあえずこれでいこうと思います。&lt;/p&gt;</description></item><item><title>RailsのRakeタスクを上書き・再定義するには</title><link>https://blog.piyo.tech/posts/2014-05-13-195503/</link><pubDate>Tue, 13 May 2014 19:54:34 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-13-195503/</guid><description>&lt;p&gt;既存のRakeタスクと同名のRakeタスクを定義した場合、上書きではなく連続実行になります。確か。&lt;/p&gt;
&lt;p&gt;Railsでフレームワーク側で定義されているRakeタスクが30ほどありますが、それに含まれるタスクを少しカスタムして実行したいような場合に、&lt;code&gt;lib/tasks&lt;/code&gt;以下にrakeタスクを追加するだけでは既存のタスクも動いてしまいます。&lt;/p&gt;
&lt;p&gt;例えば&lt;code&gt;lib/tasks/db_migrate.rake&lt;/code&gt;とかいうファイルを用意して、次のようなコードを書いたとします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;namespace &lt;span style="color:#e6db74"&gt;:db&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; desc &lt;span style="color:#e6db74"&gt;&amp;#34;puts hoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; task &lt;span style="color:#e6db74"&gt;:migrate&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; p &lt;span style="color:#e6db74"&gt;&amp;#34;hoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;rake -T&lt;/code&gt;でタスクを一覧してみると、次のように表示されます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;rake db:migrate # Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog) / puts hoge
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;やはり既存のタスクも一緒に動いてしまうようです。既存のタスクは動かしたくない場合はどうすればいいか。そのためには最初に既存のタスクを削除する必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Rake&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;.&lt;/span&gt;instance_variable_get(&lt;span style="color:#e6db74"&gt;&amp;#39;@tasks&amp;#39;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;delete(&lt;span style="color:#e6db74"&gt;&amp;#39;db:migrate&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;namespace &lt;span style="color:#e6db74"&gt;:db&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; desc &lt;span style="color:#e6db74"&gt;&amp;#34;puts hoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; task &lt;span style="color:#e6db74"&gt;:migrate&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; p &lt;span style="color:#e6db74"&gt;&amp;#34;hoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;するとこのようになりました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;rake db:migrate # puts hoge
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これで大体OKです。&lt;/p&gt;
&lt;p&gt;ところで&lt;code&gt;rake routes&lt;/code&gt;や&lt;code&gt;rake stats&lt;/code&gt;などの一部のタスクは&lt;code&gt;lib/task/*.rake&lt;/code&gt;が読み込まれたあとで定義されるためこの方法では削除できません。&lt;code&gt;rake routes&lt;/code&gt;などを再定義する方法は今調べているところです。&lt;/p&gt;</description></item><item><title>RailsのGrapeとJbuilderでAPI開発</title><link>https://blog.piyo.tech/posts/2014-05-12-204748/</link><pubDate>Mon, 12 May 2014 20:47:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-12-204748/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/19b268be-e319-407d-a65b-a032bb42409a/84b4502d3a929166749d1d42ab567931/deep/0/img_0.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;RailsでAPIを作るならGrapeを使うってのが定番っぽいので使ってみました。&lt;/p&gt;
&lt;p&gt;参考にしたのはこのへん&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/intridea/grape"&gt;intridea/grape&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://qiita.com/anoworl/items/756f01cc3d188ebad139"&gt;Ruby - RailsとGrapeで行う最高のWeb API開発 - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="grapeの導入hello-world"&gt;Grapeの導入〜Hello World&lt;/h1&gt;
&lt;p&gt;インストールは&lt;code&gt;gem install&lt;/code&gt;すればOKです。次にAPIの実装コードを書くファイルを用意します。僕は&lt;code&gt;#{Rails.root}/app/api/api.rb&lt;/code&gt;としました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# app/api/api.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;API&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Grape&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;API&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; format &lt;span style="color:#e6db74"&gt;:json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; resource &lt;span style="color:#e6db74"&gt;:items&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; get &lt;span style="color:#e6db74"&gt;&amp;#39;/hello&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;hello&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;world&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そして&lt;code&gt;routes.rb&lt;/code&gt;にてGrapeをマウントします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# routes.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;mount &lt;span style="color:#66d9ef"&gt;API&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/api&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;APIは↑で定義したクラス名です。&lt;/p&gt;
&lt;p&gt;以上のコードで&lt;code&gt;http://domain.com/api/items/hello&lt;/code&gt;というURLに対するGETで&lt;code&gt;{hello:&amp;quot;world&amp;quot;}&lt;/code&gt;というレスポンスが得られます。これが概要。&lt;/p&gt;
&lt;h2 id="mountとプレフィックス"&gt;mountとプレフィックス&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;mount API =&amp;gt; &amp;quot;/api&amp;quot;&lt;/code&gt;としましたがこれは自由に変更できます。&lt;code&gt;mount API =&amp;gt; &amp;quot;/&amp;quot;&lt;/code&gt;と、ルートを指定できます。&lt;/p&gt;
&lt;p&gt;この他にAPIクラスにprefixを付けることができるようになっていて、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;API&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Grape&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;API&lt;/span&gt;  format &lt;span style="color:#e6db74"&gt;:json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; prefix &lt;span style="color:#e6db74"&gt;&amp;#34;api&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;#この行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑のように書くとAPIクラスに定義されているAPIのURLに&lt;code&gt;api&lt;/code&gt;と付けられるようになります。&lt;/p&gt;
&lt;p&gt;ところで、マウントパスとprefixの両方定義できます。Grapeの使い始めで色々いじっていたときに両方に&lt;code&gt;&amp;quot;api&amp;quot;&lt;/code&gt;という値を入れてしまい、&lt;code&gt;/api/api/items/hello&lt;/code&gt;というURLでアクセスしなければならないことに気が付かず、&lt;code&gt;/api/items/hello&lt;/code&gt;が404になってしまうことにしばらくハマりました。&lt;/p&gt;
&lt;h1 id="jbuilderでviewを書く"&gt;JbuilderでViewを書く&lt;/h1&gt;
&lt;p&gt;さきほどのサンプルではレスポンスのjsonを直書きしましたが、プロダクションレベルではさすがにそんなことはしません。htmlのViewを作るときのように別ファイルを使って書きます。&lt;/p&gt;
&lt;p&gt;Rails4にはjsonを作るためのjbuilderというgemがデフォルトで含まれるのでそれを使うと良いでしょう。他にはRablというものがあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/rails/jbuilder"&gt;rails/jbuilder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nesquena/rabl"&gt;nesquena/rabl&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;GrapeでJbuilderを使うには&lt;code&gt;grape-jbuilder&lt;/code&gt;というgemを導入します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/milkcocoa/grape-jbuilder"&gt;milkcocoa/grape-jbuilder&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;導入は&lt;code&gt;Gemfile&lt;/code&gt;に&lt;code&gt;gem 'grape-jbuilder&lt;/code&gt;でおk。&lt;/p&gt;
&lt;p&gt;すると、Grape::Formatter::Jbuilderが使えるようになります。FormatterはAPIクラスで次のように指定できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;API&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Grape&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;API&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; format &lt;span style="color:#e6db74"&gt;:json&lt;/span&gt;  formatter &lt;span style="color:#e6db74"&gt;:json&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;Grape&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Formatter&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Jbuilder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとはjbuilderを使うAPIにどのViewを対応させるかを書いてあげれば使えるようになります。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;app/views/api/items.jbuilder&lt;/code&gt;ファイルを使う場合、apiのほうには&lt;code&gt;jbuilder:'items'&lt;/code&gt;と書きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# app/api/api.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;resource &lt;span style="color:#e6db74"&gt;:items&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; get &lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;jbuilder&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#39;items&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; @items &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Item&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;all
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Viewのほうには、&lt;code&gt;@items&lt;/code&gt;を使うようなコードを書くと動的にViewを生成できるようになるわけです。シンタックスは違えど、ERBと同じような感じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# app/views/api/items.jbuilder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;json&lt;span style="color:#f92672"&gt;.&lt;/span&gt;items &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; json&lt;span style="color:#f92672"&gt;.&lt;/span&gt;array!(@items) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;item&lt;span style="color:#f92672"&gt;|&lt;/span&gt;  json&lt;span style="color:#f92672"&gt;.&lt;/span&gt;(item, &lt;span style="color:#e6db74"&gt;:id&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:title&lt;/span&gt;, &lt;span style="color:#f92672"&gt;..&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;などなど&lt;/span&gt;&lt;span style="color:#f92672"&gt;..&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例えばこのようなjsonが得られるわけですね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;items&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hogehoge&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;foobar&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Rubyのダミーデータ生成gem</title><link>https://blog.piyo.tech/posts/2014-05-11-201307/</link><pubDate>Sun, 11 May 2014 20:12:39 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-11-201307/</guid><description>&lt;p&gt;Railsアプリケーションの作り始めってローカルのデータベースにデータが全然なくて何かと作りづらいってことありませんか？データがないとページネーション書けないし、なんか雰囲気出ないし、、、みたいな。&lt;/p&gt;
&lt;p&gt;Railsの場合はseed.rbにデータ生成プログラムを書いておいて、&lt;code&gt;rake db:seed&lt;/code&gt;でデータベースを作れます。そのときにダミーデータ生成gemを使うと幸せになれます。&lt;/p&gt;
&lt;p&gt;調べたらけっこうたくさんありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/emmanueloga/ffaker"&gt;EmmanuelOga/ffaker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sevenwire/forgery"&gt;sevenwire/forgery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/stympy/faker"&gt;stympy/faker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/benburkert/randexp"&gt;benburkert/randexp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tomharris/random_data"&gt;tomharris/random_data&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;このうち、実質的に使えるのは上の2つかなと思います。3番めのfakerはリファクタリングされて高速化したffakerがあれば要らないし、下の2つは古いし用途が微妙に違う…？という感じだったので。&lt;/p&gt;
&lt;p&gt;使い方はどちらもシンプルです。Railsに依存しないので単なるRubyスクリプトでも使えます。&lt;/p&gt;
&lt;h1 id="ffaker"&gt;ffaker&lt;/h1&gt;
&lt;p&gt;ドキュメントはfakerのほうが優れているのでそちらを参考にするといいでしょう。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Faker::Name.name&lt;/li&gt;
&lt;li&gt;Faker::Address.city&lt;/li&gt;
&lt;li&gt;Faker::Internet.email&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などなど、カテゴリごとにいろいろ用意されています。あとは、繰り返し呼び出すだけで異なる結果が返ってくるので何も考えなくていいのがいいですね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# seeds.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;times &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Post&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create(&lt;span style="color:#e6db74"&gt;title&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;Faker&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Lorem&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sentence(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;), &lt;span style="color:#e6db74"&gt;author&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;Faker&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Name&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;name)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="forgery"&gt;forgery&lt;/h1&gt;
&lt;p&gt;こちらも似たようなインターフェースが提供されています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# seeds.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;times &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Post&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create(&lt;span style="color:#e6db74"&gt;title&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;Forgery&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;LoremIpsum&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sentence, &lt;span style="color:#e6db74"&gt;author&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;Forgery&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Name&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;full_name)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="どっちでもよさそう"&gt;どっちでもよさそう&lt;/h1&gt;
&lt;p&gt;こういう類のgemは本番で使うことはあまりないと思うので適当に選べばよさそう。&lt;/p&gt;
&lt;p&gt;日本語データを生成したい場合はこういうのもあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/tily/ruby-faker-japanese"&gt;tily/ruby-faker-japanese&lt;/a&gt;&lt;/p&gt;</description></item><item><title>ruby-end.elいけてる</title><link>https://blog.piyo.tech/posts/2014-05-10-204905/</link><pubDate>Sat, 10 May 2014 20:48:40 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-10-204905/</guid><description>&lt;p&gt;導入はここを見るといいです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/rejeep/ruby-end.el"&gt;rejeep/ruby-end.el&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これだけでSublimeよりイケてる環境になった気がします。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/EzTaouppileTwUayQyM5Sgasvh-q5w9Xtu2wP4AyGI7cPDkuNrd_E3XhNQ0tsJh17PjR-4B5ZXedgGBz_mnGJxR2YJq9zZ2WWyOCr17_omogUJ0DqWvhPZ8PyoECVi35lvY3hYs2rzJkL7MN7iBocNYuSs2fCZLfxKPu3k5JONrHikdZgWVwnSXCExtHJYuCG7HJFF08BL-r9KFJADSksGTBYf5Icei8C_4OTrxQnW7XlB6hjvScCJ1MdVRfcfyHsWEduNX4V1Er0zWiMPscwV6PgXH_giNHOLs8aDlo8bOK27CtBb3VOt6gRnMTKZyOmA5jaK47U-J6rxiwF7AcdXcXa9_SJ4ljB3XFMmNdxX9odFhY8diX9kydP3qla73ztlixWEt03Koe1FWecOMx-pPn2T0nPOzfpxHN2Ps78Mhd_pRBgLgSazQkczcjg07_0EY15gdGvPiULZCElMsuuOtuIWYiiSQcPBKAMqiBMlJ64jGXKF39xfdz2lXv2ZvuoAYpR1PGR9hmuKJivj2vlQnDJNUwd8xTGR4X3kevlPUIHVEMnJRhKufEYnaGwMcrEohkWTpFM3TzYZh_1VGZA4cw4qw2PFdwc15FLvatO7TwZ2J-Pg5Em03iKpRgni6_P-YjJK_t8elVffjMdAbsWZ83Teo4c345cw=w454-h300-no" alt=""&gt;&lt;/p&gt;</description></item><item><title>ブラウザのjavascriptのみを使ってipa展開からplist解析まで</title><link>https://blog.piyo.tech/posts/2014-05-09-190407/</link><pubDate>Fri, 09 May 2014 19:03:43 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-09-190407/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7e399fd6-ba3a-4bd2-baae-16437c635994/5712220a6ef5e02f1182961b95e15e35/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-07-21-26.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ここ数日取り組んでだことについてまとめます。iPhoneアプリのバイナリであるipaをごにょごにょしてplistファイルを取り出し中身を見てやろうっていうことをブラウザ単体でできるかという取り組みです。&lt;/p&gt;
&lt;p&gt;関連記事というか、下準備の記事がこちらです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2014-05-07-214725"&gt;バイナリ形式のplistファイル - ぴよログ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2014-05-08-203906"&gt;binary plist parser for Javascript (non-Node) - ぴよログ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="ipaファイルを指定する"&gt;ipaファイルを指定する&lt;/h1&gt;
&lt;p&gt;ipaファイルはHTMLのinput要素で指定させます。↓の例では&lt;code&gt;webkitdirectory directory&lt;/code&gt;をつけているのでフォルダ指定になっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;form&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;action&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;#&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;input&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;file&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;file-input&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;webkitdirectory&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;directory&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;input&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;button&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;button-start&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;plist解析&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;form&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このHTMLによりこういうフォームができます。ipaファイルが入っているフォルダを指定して、&lt;code&gt;plist解析&lt;/code&gt;ボタンにより処理をスタートさせる作りにしておきました。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b48e64cf-abba-4585-b8cf-aa1b96089b1f/910ff3b42e13a6b66365de0051b5a7fa/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-09-15-46.png" alt=""&gt;&lt;/p&gt;
&lt;h1 id="ipaファイルを展開する"&gt;ipaファイルを展開する&lt;/h1&gt;
&lt;p&gt;ipaファイルはzip形式で圧縮されています。&lt;a href="http://gildas-lormeau.github.io/zip.js/"&gt;zip.js&lt;/a&gt;というJavascriptがライブラリがあり、これを使えばブラウザ上でファイルを展開して色々ごにょごにょできるようになっています。&lt;/p&gt;
&lt;p&gt;デモ（&lt;a href="http://gildas-lormeau.github.io/zip.js/demos/demo2.html"&gt;Read a zip file demo&lt;/a&gt;）を参考に展開部分を書いてみました。&lt;/p&gt;
&lt;h2 id="inputからファイルの情報を得る"&gt;inputからファイルの情報を得る&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fileInput&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; document.&lt;span style="color:#a6e22e"&gt;getElementById&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;file-input&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;fileInput&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;files&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// fileはipaファイルの情報を持っている
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="展開する"&gt;展開する&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;model&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getEntries&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;entries&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;entries&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;forEach&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;entry&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// entry が展開後の中身
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;modelっていうオブジェクトが急にでてきました。zip.jsのサンプルから持ってきたもので、zip.jsを使う関数を持っているオブジェクトです。単に使うだけならわざわざこんな別のオブジェクトを用意する必要はなく、普通に関数にでもしておけばいいかと思います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;model&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;URL&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;webkitURL&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;mozURL&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;URL&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;getEntries&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;onend&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;zip&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;createReader&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;zip&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;BlobReader&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;), &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;zipReader&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;zipReader&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getEntries&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;onend&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; }, &lt;span style="color:#a6e22e"&gt;onerror&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;})();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;getEntries&lt;/code&gt;関数では、zip.jsの&lt;code&gt;zip.createReader&lt;/code&gt;によって渡したファイルを展開してコールバックに要素を渡してくれるという風になっています。&lt;/p&gt;
&lt;h1 id="plistを解析する"&gt;plistを解析する&lt;/h1&gt;
&lt;h2 id="plistを特定する"&gt;plistを特定する&lt;/h2&gt;
&lt;p&gt;ipaファイルを&lt;code&gt;getEntries&lt;/code&gt;によって展開すると中身のコレクションが得られるので、その中からplistを特定します。ここは単純に文字列比較を用いました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;model&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getEntries&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;entries&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;entries&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;forEach&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;entry&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;entry&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;filename&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;match&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;app/Info.plist&amp;#34;&lt;/span&gt;)){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// entry は Info.plistファイル
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="plistの中身を得る"&gt;plistの中身を得る&lt;/h2&gt;
&lt;p&gt;これでplist以外のものを除外できました。次にやることはplistを内容を取得することです。ここでもzip.jsのインターフェースを使います。&lt;/p&gt;
&lt;p&gt;サンプルコードにおけるzip.js呼び出し用のオブジェクト&lt;code&gt;model&lt;/code&gt;に&lt;code&gt;getEntryFile&lt;/code&gt;という関数がありました。それを少し改変し、与えたファイルの内容をバイナリで得られるようにしました。&lt;/p&gt;
&lt;p&gt;得られたバイナリデータはonendコールバックに渡して処理します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;getEntryFile&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;entry&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;onend&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;onprogress&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;writer&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;zip&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;BlobWriter&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;entry&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getData&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;writer&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;onend&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; }, &lt;span style="color:#a6e22e"&gt;onprogress&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;model&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getEntryFile&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;entry&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// data にplistの中身が入っている
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}, &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="plistのバイナリデータを解析する"&gt;plistのバイナリデータを解析する&lt;/h2&gt;
&lt;p&gt;あとはbplistParserを使ってplistを解析しJSONにするだけです。これは昨日の記事で紹介したライブラリを使うことで実現できます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-05-08-203906"&gt;binary plist parser for Javascript (non-Node) - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;parseFile&lt;/code&gt;のコールバックにjsonが渡ってくるのであとはそれを好きなように使えばOK。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;model&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getEntryFile&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;entry&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fileReader&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;FileReader&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fileReader&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;onload&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;bplist&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;parseFile&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;throw&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;onComplete&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fileReader&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;readAsArrayBuffer&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}, &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ブラウザ単体でipaを展開してplistを解析するという話でした。&lt;/p&gt;
&lt;p&gt;動くサンプルはこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/extract-ipa-parse-plist-example"&gt;pi-chan/extract-ipa-parse-plist-example&lt;/a&gt;&lt;/p&gt;</description></item><item><title>binary plist parser for Javascript (non-Node)</title><link>https://blog.piyo.tech/posts/2014-05-08-203906/</link><pubDate>Thu, 08 May 2014 20:38:42 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-08-203906/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/619c1cf0-1f84-4018-a93e-cde2cf72c288/192d7c3fbaab5750bab067bd7d594584/deep/0/browserify.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Node.jsベースであればJavascriptでバイナリplistをパースする処理を書けるということがわかったというのがこちら↓&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-05-07-214725"&gt;バイナリ形式のplistファイル - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;でも本当にやりたかったのはブラウザでipaファイルを指定して展開し、中にあるInfo.plistを解析するというものでした。上の記事で紹介している&lt;code&gt;node-bplist-parser&lt;/code&gt;のコードはそのままではブラウザで動きませんでした。&lt;/p&gt;
&lt;h1 id="bplist-parserを流用する"&gt;bplist-parserを流用する&lt;/h1&gt;
&lt;h2 id="browserifyする"&gt;browserifyする&lt;/h2&gt;
&lt;p&gt;Node.jsではCommonJS的にモジュールを書けるようになっていますが、ブラウザのJavascriptでは通常はそのようなことはできません。それを実現するために&lt;code&gt;browserify&lt;/code&gt;というnpmモジュールがあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://browserify.org/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://browserify.org/" alt="Browserify" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://browserify.org/"&gt;Browserify&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://browserify.org/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://browserify.org/" alt="はてなブックマーク - Browserify" title="はてなブックマーク - Browserify" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;browserifyを使って吐き出したjsファイルをHTMLファイル中の&lt;code&gt;script&lt;/code&gt;タグで指定しておくと、require(&amp;quot;&amp;quot;)でロードできるようになるということでした。実装はよくわからんけど、とりあえず使ってみました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% browserify -r ./bplistParser.js -o xoyip-bplist-parser.js
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このようにコマンドラインでファイルを変換できます。変換後のファイルを使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;./xoyip-bplist-parser.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bplist&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;bplistParser.js&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;bplist&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;parseFile&lt;/span&gt;( ... );
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="bufferもbrowserifyする"&gt;Bufferもbrowserifyする&lt;/h2&gt;
&lt;p&gt;上のサンプルコードにも書いた&lt;code&gt;parseFile&lt;/code&gt;が今回使いたい関数です。Node.js版で想定されているこの関数の本来の引数はファイルパスかBufferオブジェクトというもので、パース部分ではBufferオブジェクトから少しずつ読み出しを行っています。このBufferもブラウザには存在しないため同じくbrowserifyしたものを&lt;code&gt;require&lt;/code&gt;して使いました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% npm install buffer
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;% browserify -r path/to/buffer.js -o buffer.js
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そして、解析したい内容をBufferオブジェクトにして&lt;code&gt;parseFile&lt;/code&gt;に渡せば…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;できませんでした&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;Node.jsで動かしたときは正常にパースできていたので、デバッグしながらブラウザ版と比較して動かしてみたとことろ、Bufferオブジェクトのサイズが全然違う！ということがわかりました。&lt;/p&gt;
&lt;p&gt;bplist-parserをそのまま流用するのは諦めました。&lt;/p&gt;
&lt;h1 id="パース部分を書き換える"&gt;パース部分を書き換える&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;bplist-parser&lt;/code&gt;内部ではBufferが来ることを想定していますが、Bufferを渡しても動かないというのがここまででわかったことです。&lt;/p&gt;
&lt;p&gt;仕方がないので、基本ロジックはそのままに別のバイナリデータライブラリを導入し、Bufferと置き換えることにしました。そのときに用いたのが&lt;code&gt;jDataView.js&lt;/code&gt;です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/jDataView/jDataView"&gt;jDataView/jDataView&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;こちらもNode.jsのモジュールなのでbrowserifyをかけて使っています。&lt;/p&gt;
&lt;h2 id="bplist-parserを書き換える"&gt;bplist-parserを書き換える&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;parseFile&lt;/code&gt;にBufferのオブジェクトを渡すのではなく、jDataViewのオブジェクトを渡せばいい、という風に変更します。&lt;/p&gt;
&lt;p&gt;bplist-parserの内部ではBufferオブジェクトの&lt;code&gt;buffer&lt;/code&gt;に対して色々なアクセスをします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 元のbplist-parser
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// bufferはBufferのオブジェクト
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;buffer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;buffer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;readUInt&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;buffer&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑を↓のように書き換えました。幸いというか、目的が同じなので当たり前かもしれませんが、似たようなメソッドが提供されているので整合性がとれるように置き換えれば問題ありませんでした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 書き換え後のbplist-parser
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// bufferはjDataViewのオブジェクト
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;buffer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;byteLength&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;buffer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;buffer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getUint8&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="完成したものがこちら"&gt;完成したものがこちら&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/bplist-parser"&gt;pi-chan/bplist-parser&lt;/a&gt;&lt;/p&gt;</description></item><item><title>バイナリ形式のplistファイル</title><link>https://blog.piyo.tech/posts/2014-05-07-214725/</link><pubDate>Wed, 07 May 2014 21:47:25 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-07-214725/</guid><description>&lt;p&gt;iOSアプリはiTunesを使えばMacでもダウンロードできます。そしてダウンロードしたipaファイルはzipファイルとして展開でき、中身を覗き見ることができるようになっています。&lt;/p&gt;
&lt;p&gt;ところでiOSアプリケーションのURLスキーム定義はどこに書かれているのかというと、ipaファイルの中にあるplistファイルに記載されています。URLスキームのリストは公開されていませんが、手元のアプリに限って言えばplistファイルを覗くことによって特定することが可能です。&lt;/p&gt;
&lt;h1 id="手作業で確認する"&gt;手作業で確認する&lt;/h1&gt;
&lt;h2 id="ipaファイルをリネームする"&gt;ipaファイルをリネームする&lt;/h2&gt;
&lt;p&gt;こいつを。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7e399fd6-ba3a-4bd2-baae-16437c635994/5712220a6ef5e02f1182961b95e15e35/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-07-21-26.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;こう。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9dda87be-9cca-46ef-8b7f-1adf2cfbb133/f4328d2ef2342ee31b69780862918076/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-07-21-26.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="plistを探す"&gt;plistを探す&lt;/h2&gt;
&lt;p&gt;展開した先にはこれらのファイルやディレクトリが並びます。目的のplistはここにある&lt;code&gt;iTunesMetadata.plist&lt;/code&gt;ではなくて、Payloadの下にある&lt;code&gt;Facebook.app&lt;/code&gt;のの内部にあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;META-INF&lt;/li&gt;
&lt;li&gt;Payload&lt;/li&gt;
&lt;li&gt;iTunesArtwork&lt;/li&gt;
&lt;li&gt;iTunesMetadata.plist&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Payload/Facebook.app&lt;/code&gt;を右クリックし&lt;code&gt;パッケージの内容を表示&lt;/code&gt;で中身を表示し、&lt;code&gt;Info.plist&lt;/code&gt;を探します。Finderからであればクイックルックでplistファイルの内容をプレビューすることもできますね。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CFBundleURLTypes&lt;/code&gt;の項目を見るとURLスキームがわかります。Facebookでは数多くのURLスキームが定義されていました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;CFBundleURLTypes&amp;#34;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;CFBundleTypeRole&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Editor&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;CFBundleURLName&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;com.facebook&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;CFBundleURLSchemes&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fbauth2&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fbauth&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fb&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fblogin&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fbapi&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fbapi20130214&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fbapi20130410&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fbapi20130702&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fbapi20131010&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fbapi20131219&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fbapi20140116&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fbapi20140410&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;]&lt;span style="color:#960050;background-color:#1e0010"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="コードで自動処理"&gt;コードで自動処理&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;ipaをzipにリネーム&lt;/li&gt;
&lt;li&gt;展開&lt;/li&gt;
&lt;li&gt;plistを探して解析&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;この流れならコードで自動化できそうです。plistはXMLだし。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;と思ったら違った！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;plistはbplistというバイナリのplistファイルになっていました。XMLパーサーがあれば余裕と思っていたらそういうわけにはいかなそうです。&lt;/p&gt;
&lt;h2 id="外部ライブラリを探す"&gt;外部ライブラリを探す&lt;/h2&gt;
&lt;p&gt;珍しくjavascriptでなんとかできないかと調べていたところ、あ.jsのライブラリに&lt;code&gt;bplist-parser&lt;/code&gt;なるものがあることがわかりました。これで簡単に解析できました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/joeferner/node-bplist-parser"&gt;joeferner/node-bplist-parser&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;インストールは&lt;code&gt;npm install bplist-parser&lt;/code&gt;でOKです。&lt;/p&gt;
&lt;h2 id="メインプログラム"&gt;メインプログラム&lt;/h2&gt;
&lt;p&gt;サンプルそのままですが、このようなファイルを作りました。また対象とするplistファイルはプログラムと同じディレクトリに置いておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bplist&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;bplist-parser&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;bplist&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;parseFile&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Info.plist&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;throw&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;JSON&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;stringify&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これだけでバイナリ形式のplistをJSON形式で得られることがわかりました。&lt;/p&gt;
&lt;p&gt;なお、バイナリplistのフォーマットは公開されているそうです。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://opensource.apple.com/source/CF/CF-550/CFBinaryPList.c"&gt;CFBinaryPList.c&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="やりたいこと"&gt;やりたいこと&lt;/h1&gt;
&lt;p&gt;Node.jsで動かすことはできましたが、ブラウザ上のJavascriptではバイナリデータの処理周りがうまくいかず、バイナリplistの解析ができていません。&lt;code&gt;bplist-parser&lt;/code&gt;をbrowserifyしたり、他のバイナリライブラリを使って&lt;code&gt;bplist-parser&lt;/code&gt;をブラウザ用に書き直したりしましたが今のところうまくいっていません。&lt;/p&gt;</description></item><item><title>はてなブログの「注目記事」モジュール導入してみました</title><link>https://blog.piyo.tech/posts/2014-05-04-200005/</link><pubDate>Sun, 04 May 2014 19:59:44 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-04-200005/</guid><description>&lt;p&gt;はてなブログに新機能ができたので使ってみます。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://staff.hatenablog.com/entry/2014/05/01/163941"&gt;サイドバーに「注目記事」モジュールを追加しました。よく読まれている記事を一覧表示できます - はてなブログ開発ブログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;デザイン設定→カスタマイズ→サイドバー→モジュールを追加から追加できます。設定できる内容は↓の通り。僕はこのように設定しました。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/917deef4-7efa-4ae0-ae03-6f37d706aab0/d470e45117cc1d9526c53a296e31c473/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-03-22-48.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;サイドバーにはこのように表示されるようになりました。サムネ有りにするとバランス悪くなるのがどうもイケてないなぁという印象。CSS自分で書いたほうがいいかもしれません。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/075327fa-ca1b-4916-8443-bdae9146c553/1ac9d35b834a086456b7c6858e5738dd/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-03-22-50.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;今日までの1週間のGoogle Analyticsの結果と見比べてみると、まあまあ正しそうな感じがします。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/324c0837-a615-4bfd-af4e-eb4e79246854/c1af2d0b3c49078d9654b2a9c82c103b/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-03-22-54.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>CloudFlare使ってHerokuでルートドメイン使おう</title><link>https://blog.piyo.tech/posts/2014-05-03-192920/</link><pubDate>Sat, 03 May 2014 19:29:20 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-03-192920/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/71d014ae-a36e-4c50-a97a-20b738cc99e8/cec11c4413159ddfa9682fbbfac3eac3/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-03-13-44.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Herokuが古いルーティングの仕組みを使っているアプリケーションの管理者に対して &lt;strong&gt;&amp;ldquo;Action Required: Legacy Routing Ending&amp;rdquo;&lt;/strong&gt; というタイトルでメールを出してきました。&lt;/p&gt;
&lt;p&gt;廃止予定のRoutingを用いてかどうかをリストしてくれるサポートページがあり、&lt;code&gt;Legacy!&lt;/code&gt;という赤いマークが付いているアプリケーションは対応が必要ということがわかります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://legacy-routing.herokuapp.com/"&gt;Heroku Support (Legacy Routing)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/4c1e0832-75d2-4ec3-9b22-9f8176840137/2ffe707b474118ecd825ee0ad52408a6/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-03-13-23.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;使っていない、使う予定のないものであればまあほっといていいんでしょうけど。&lt;/p&gt;
&lt;h1 id="aレコードが使えなくなる"&gt;Aレコードが使えなくなる&lt;/h1&gt;
&lt;p&gt;2013年の4月頃にHerokuのサービスに独自ドメインを設定したときにはAレコードを使うことができていました。しかし2014年5月現在、Aレコードから飛ばす先のIPが廃止されているため新しいアプリケーションからは使うことができなくなっています。その上今回の対応で完全に既存のアプリケーションでも使えなくなるようなので、Aレコードを使ったドメインの設定は変えなければいけなくなりました。&lt;/p&gt;
&lt;h1 id="代わりにcnameを使う"&gt;代わりにCNAMEを使う&lt;/h1&gt;
&lt;p&gt;自分で使っているドメイン管理サービスでAレコードを削除し、代わりにCNAMEを追加します。CNAMEの値には、Herokuに割り当てられている&lt;code&gt;XXXXX.herokuapp.com&lt;/code&gt;というドメインを入れます。&lt;/p&gt;
&lt;p&gt;こんな感じ。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;www.mydoamin.com&lt;/code&gt; =&amp;gt; &lt;code&gt;myapp.herokuapp.com&lt;/code&gt;&lt;/p&gt;
&lt;h1 id="ルートドメイン使えない"&gt;ルートドメイン使えない&lt;/h1&gt;
&lt;p&gt;サービスのURL,ルートドメイン（wwwとかが付いていない、&lt;code&gt;mydomain.com&lt;/code&gt;などのこと）にしたいことありますよね。確か、多くのドメイン管理サービスではルートドメイン対してCNAMEを使うことができなくなっています、確か。僕が使ったお名前.comもそうでした。サブドメイン入れろって怒られます。&lt;/p&gt;
&lt;p&gt;元々Aレコードで運用していたときはルートドメインでサービスにアクセスできるようにしていたのでこれは困ります。&lt;/p&gt;
&lt;p&gt;そこで登場する回避策が&lt;a href="http://www.cloudflare.com/"&gt;CloudFlare&lt;/a&gt;です。&lt;/p&gt;
&lt;h1 id="cloudflareを使うとどうなる"&gt;CloudFlareを使うとどうなる？&lt;/h1&gt;
&lt;p&gt;詳しい仕組みはさておき、Herokuでルートドメインを使うという点においてどんなことができるかを簡単に紹介。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ドメインを入力する&lt;/li&gt;
&lt;li&gt;既存のDNSレコードを読んでコピーしてくれる&lt;/li&gt;
&lt;li&gt;CloudFlare上でレコードの追加ができる（ルートドメインのCNAMEも可能）&lt;/li&gt;
&lt;li&gt;ネームサーバーが提供される&lt;/li&gt;
&lt;li&gt;↑のネームサーバーを元ドメインの管理サービスでドメインのネームサーバーに設定するとCloudFlareの設定を使える&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;サボって箇条書きで書いてしまった。。。で、設定を終えると次のようになります。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/f50bf0ef-23d5-4273-9f70-708a37fc51c8/bf6064db9c038e1432755ab0bc4db493/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-05-03-13-40.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ほんとにルートにCNAMEの設定できるんですよねー。んで、あとはお名前.comで目的のドメインのネームサーバーをCloudFlareのネームサーバーに変更したら、、ちゃんと反映されました。&lt;/p&gt;
&lt;p&gt;数日経った今でもAレコードは削除したのにルートドメインでサービスにアクセスできているのでもう大丈夫そうです。&lt;/p&gt;
&lt;p&gt;これをやるだけなら無料なので試す価値あり！です。&lt;/p&gt;</description></item><item><title>Dashのスニペットに入れておくと便利なやつ教えて</title><link>https://blog.piyo.tech/posts/2014-05-02-195202/</link><pubDate>Fri, 02 May 2014 19:51:49 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-02-195202/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b5de29ab-83f8-43de-b909-1327e488b1cf/08d1a8e20a323aa87ee4a399226c73bf/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-30-21-56.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ドキュメントビューアのDashってなんでスニペット管理機能まで入ってるんでしょうね？どちらも便利なので酷使していますけどね。&lt;/p&gt;
&lt;p&gt;今回はDashに登録してあるスニペットをいくつか紹介します。もし拡散されて他にも便利なスニペットを教えてもらえるようになったりするといいなぁと思っています。&lt;/p&gt;
&lt;p&gt;なおオレオレプレフィックスとして&lt;code&gt;;&lt;/code&gt;を使っています。&lt;/p&gt;
&lt;h1 id="ブログ用"&gt;ブログ用&lt;/h1&gt;
&lt;h2 id="コードブロック"&gt;コードブロック&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;;co&lt;/code&gt;とタイプするとMarkdownのコードブロックを挿入します。プレースホルダーを使う設定にしてあるので、次のようなプロンプトウィンドウが出ます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c280721f-e560-4b54-aafc-442c9eeaafa1/86457f1720bdf6642f9c6194a1ddcbb2/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-30-21-39.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ここに言語名を入れてリターンすると↓こういうのが挿入されるわけです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/ea58ff6f-65f1-4faa-a7da-79ddce48d11f/fa581749c280d06fb28bed845ba383ce/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-30-21-41.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="インラインコード"&gt;インラインコード&lt;/h2&gt;
&lt;p&gt;これもMarkdown用。`hogehoge`とタイプすると、&lt;code&gt;hogehoge&lt;/code&gt;となるこれです。&lt;code&gt;;qo&lt;/code&gt;とタイプすると、バッククオート2文字を入力した後クオートの間にカーソルが移動します。&lt;/p&gt;
&lt;h2 id="画像リンク"&gt;画像リンク&lt;/h2&gt;
&lt;p&gt;貼り付けたい画像のURLをコピーしている状態で&lt;code&gt;;mdi&lt;/code&gt;とタイプするとMarkdownの画像リンクを貼り付けます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;![](https://www.evernote.com/shard/s15/sh/ea58ff6f-65f1-4faa-a7da-79ddce48d11f/fa581749c280d06fb28bed845ba383ce/deep/0/スクリーンショット-2014-04-30-21-41.png)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;僕の場合Skitchでスクリーンショットを撮影したあと共有URLを発行します。するとURLが自動的にクリップボードに入るので、あとはこのスニペットで貼り付けるだけというわけです。&lt;/p&gt;
&lt;h1 id="便利系"&gt;便利系&lt;/h1&gt;
&lt;h2 id="メールアドレス"&gt;メールアドレス&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;;ml&lt;/code&gt;とタイプすると自分のメインのメールアドレスが展開されます。&lt;/p&gt;
&lt;p&gt;他にもいくつかメールアドレスがあるので、それぞれにスニペットを用意しています。&lt;/p&gt;
&lt;h2 id="草"&gt;草&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;;;w&lt;/code&gt;とタイプすると&lt;code&gt;ｗ&lt;/code&gt;を入力します。やっぱり草は全角でないとね。&lt;/p&gt;
&lt;p&gt;ｗｗｗｗｗｗｗ&lt;/p&gt;
&lt;p&gt;ちなみにセミコロンが2つ続くのは、他に&lt;code&gt;;w&lt;/code&gt;で始まるスニペットがあるためです。&lt;/p&gt;
&lt;h2 id="gitのremote-add"&gt;gitのremote add&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;git remote add origin&lt;/code&gt;が面倒なのでスニペットにしています。SSHの関係でホスト名を変える必要があるんですが、いちいち覚えてらんないので。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;;gh&lt;/code&gt;とタイプすると次の文字列に展開されます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;git remote add origin git@gh:xoyip/
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="日付"&gt;日付&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;;da&lt;/code&gt;とタイプするとその日の日付に展開されます。例えば&lt;code&gt;2014/04/28（月）&lt;/code&gt;といった具合。&lt;/p&gt;
&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;p&gt;細かいのは他にも色々あるけど他の人でも役に立ちそうなのはこのぐらいだと思われます。&lt;/p&gt;</description></item><item><title>Objective-Cで非同期処理のテスト（依存ライブラリなし版）</title><link>https://blog.piyo.tech/posts/2014-05-01-191106/</link><pubDate>Thu, 01 May 2014 19:10:49 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-05-01-191106/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/6e92f434-a1de-4ea9-8275-6de118df4de3/ac119abf9550ffc0849419fd27cfce05/deep/0/xcode.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Xcode標準のテストライブラリがうまいことやってくれないせいで、非同期処理のテストを書く場合に待ちの処理を自分で書いてあげないといけません。&lt;/p&gt;
&lt;p&gt;最近のすごくいい感じの拡張が紹介されたのでこれを使うとなかなかいい感じです。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.tokoro.me/2014/04/21/objc-async-test/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://www.tokoro.me/2014/04/21/objc-async-test/" alt="Objective-Cで非同期処理のテストをシンプルに書く方法 - TOKOROM BLOG" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://www.tokoro.me/2014/04/21/objc-async-test/"&gt;Objective-Cで非同期処理のテストをシンプルに書く方法 - TOKOROM BLOG&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://www.tokoro.me/2014/04/21/objc-async-test/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://www.tokoro.me/2014/04/21/objc-async-test/" alt="はてなブックマーク - Objective-Cで非同期処理のテストをシンプルに書く方法 - TOKOROM BLOG" title="はてなブックマーク - Objective-Cで非同期処理のテストをシンプルに書く方法 - TOKOROM BLOG" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;ですが、実際はそこまでやらなくてもSDK標準の機能だけでも簡単に実装できます。サンプルコードは以下の通り。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;testExample&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; CFRunLoopRef rl &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CFRunLoopGetCurrent();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; NSURLRequest &lt;span style="color:#f92672"&gt;*&lt;/span&gt;req &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSURLRequest requestWithURL:[NSURL URLWithString:&lt;span style="color:#e6db74"&gt;@&amp;#34;https://blog.piyo.tech/&amp;#34;&lt;/span&gt;]];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; NSOperationQueue &lt;span style="color:#f92672"&gt;*&lt;/span&gt;queue &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSOperationQueue new];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; [NSURLConnection sendAsynchronousRequest:req queue:queue completionHandler:&lt;span style="color:#f92672"&gt;^&lt;/span&gt;(NSURLResponse &lt;span style="color:#f92672"&gt;*&lt;/span&gt;response, NSData &lt;span style="color:#f92672"&gt;*&lt;/span&gt;data, NSError &lt;span style="color:#f92672"&gt;*&lt;/span&gt;connectionError) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;complete&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; XCTAssert(NO);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; CFRunLoopStop(rl);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; }];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;test ended&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; XCTAssert(YES);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; CFRunLoopRun();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;重要なのは次の3行です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CFRunLoopRef rl = CFRunLoopGetCurrent();&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CFRunLoopStop(rl);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CFRunLoopRun();&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;テスト関数を抜ける直前で&lt;code&gt;CFRunLoopRun()&lt;/code&gt;でランループを起動させ待機し、非同期処理が完了したあとで&lt;code&gt;CFRunLoopStop&lt;/code&gt;によりランループを停止させてテスト関数を抜けさせます。このときの引数に&lt;code&gt;CFRunLoopGetCurrent&lt;/code&gt;で取っておいた&lt;code&gt;CFRunLoopRef&lt;/code&gt;を渡したいので最初の一行があります。&lt;/p&gt;</description></item><item><title>iOSでアニメーションGIF</title><link>https://blog.piyo.tech/posts/2014-04-30-193014/</link><pubDate>Wed, 30 Apr 2014 19:29:58 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-30-193014/</guid><description>&lt;p&gt;iOSのUIImageViewではアニメーションGIFの再生ができないようです。Googleで&lt;code&gt;UIImageView&lt;/code&gt;+&lt;code&gt;gif&lt;/code&gt;などと検索すると先人たちが色々頑張っていることがわかります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://d.hatena.ne.jp/eth0jp/20101126/1290707742"&gt;MacとiPhoneでアニメーションGIFを表示する方法まとめ - yoshida_eth0の日記&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://cocoadays-info.blogspot.jp/2012/01/gifuiimage.html"&gt;アニメーションGIFをアニメーション付きのUIImage に変換するライブラリ | Cocoaの日々情報局&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/4386675/add-animated-gif-image-in-iphone-uiimageview"&gt;Add animated Gif image in Iphone UIImageView - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などなど。&lt;/p&gt;
&lt;h1 id="ylgifimage"&gt;YLGIFImage&lt;/h1&gt;
&lt;p&gt;YLGIFImageというライブラリを使うと、YLImageViewやYLGIFImageといったUIImageViewやUIImageのサブクラスが提供されます。このクラスでは上で紹介されているようなGIFアニメーション画像を表示するための処理をラップしてくれているため、とても簡単に使うことができます。&lt;/p&gt;
&lt;p&gt;アニメーションGIFといえばLGTMな感じもあるので、試しにこれを表示してみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.lgtm.in/i/QiOgViRfq"&gt;LGTM.in/g&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.lgtm.in/i/QiOgViRfq"&gt;&lt;img src="http://www.lgtm.in/p/QiOgViRfq" alt="LGTM"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="サンプル"&gt;サンプル&lt;/h1&gt;
&lt;p&gt;ソースコードはこちら→&lt;a href="https://github.com/pi-chan/ios-sandbox/tree/master/AnimGif"&gt;ios-sandbox/AnimGif at master · xoyip/ios-sandbox&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="storyboard"&gt;Storyboard&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/edb4470d-f09d-45f6-9e16-0dddb9b90eda/992e7adace3bd9895027213d129e2445/deep/0/AnimGif---Main.storyboard.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="viewcontrollerm"&gt;ViewController.m&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; [super viewDidLoad];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Do any additional setup after loading the view, typically from a nib.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; self.imageView.image &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [UIImage imageNamed:&lt;span style="color:#e6db74"&gt;@&amp;#34;sample.gif&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; self.gifImageView.image &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [YLGIFImage imageNamed:&lt;span style="color:#e6db74"&gt;@&amp;#34;sample.gif&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="結果"&gt;結果&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/Kqx4D3D08v9CCF7s-EQWoiIPXjVCuaIUxaaFz_rw_dckDH2pBm1UAmthBhVbsO0ozAEJqN6geRjtuxtwq5_qEnv11U33yzvWU2hCUL9H9MyYUN4u_uz2ruCmHaaJFBp5eZq9cYYRDxt2RjLp2VFKIrncVqnG45_vjfHb2NdiK9SD5T3TjRoqTvV2cUVZUgy56P0LN3D5ojo-r5J8ZBj1czD-ffNaAa6FvGBLP5w5lfsqIhqeDSf7ihL48dE6aiApOs9gYCUgalyX6uOoVvD9EydURxLwmwu7yXcGHY78M_AQKGxMnuZhL8KD6XM9V6vjqfhM8awwiVA7kCl4yNlx_GKuWUfGdU-eZFYg6zI2gRyrhdeWyFtI-67gSZtYAqOPT5UNrD7Jmzmn4wjFIxkKtqGDCCDlq5izjwrEMIaSrM8b19We9kuHIXBZXU-Z8k9N3edQgyiGY_7mRREALUkcCtLMggsNppd3wJWUW8swKPR08P-vkC0ROU4SeAyG4EiNPSBxE_XXz9qXTOZ7EC0_ss_CoCkcS1VN71aA34RTddHIZy_Rf5jxXbRglgS82dAHk3JBGnQYWR8_CfJkUBN_YxP1gmgKf7llZ1MrtB8YeMPEui2E1ikxju3tYEhg0dCdZt4GMn_DbuSEgLpW9VeGdppAoFrvVR00ow=w189-h352-no" alt=""&gt;&lt;/p&gt;</description></item><item><title>Macで特定のアプリでのみ独自ショートカットを有効にする</title><link>https://blog.piyo.tech/posts/2014-04-29-200012/</link><pubDate>Tue, 29 Apr 2014 19:59:56 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-29-200012/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/78804920-718b-4dbe-8b45-441f7bcc819b/f97520c2e7a05571e079d40c24e8cb88/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-28-13-15.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;頻繁に行う操作がキーボードで出来なくてストレスがやばいこと、別にありませんよね。僕はしょっちゅうありますが、そういうのに出くわすとついついそのストレスを回避する方向で頑張ってしまって何をやっていたのか忘れたりするっていうことが多々。&lt;/p&gt;
&lt;h1 id="メニュー項目にショートカットを割り当てる"&gt;メニュー項目にショートカットを割り当てる&lt;/h1&gt;
&lt;p&gt;メニューには存在するけどショートカットがアサインされていないような場合は特別なツールを導入することなく設定できるようです。詳細はこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://nanapi.jp/68641/"&gt;Macで任意のキーボードショートカットを設定する方法 | nanapi [ナナピ]&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="メニュー項目にない場合"&gt;メニュー項目にない場合&lt;/h1&gt;
&lt;p&gt;たまにあるんですよそういうのが。ショートカットはあるんだけどメニューにも特に書かれてい上に、カスタマイズもできないようなのが。ファンクションキーなんかが使われていると最悪なのでできれば別のキーにしたいということになるわけです。&lt;/p&gt;
&lt;p&gt;幸い常用しているキーリマップツールでそれができるので、オリジナルの設定を追加してみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://pqrs.org/macosx/keyremap4macbook/index.html.ja"&gt;KeyRemap4MacBook - OS X用のソフトウェア&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="設定ファイルを開く"&gt;設定ファイルを開く&lt;/h2&gt;
&lt;p&gt;KeyRemap4Macbookから設定ファイルがある場所を開いてくれます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/bf9b6693-a479-4c23-928f-58a89f94159b/bd46d377e5176d83e1b5a81c3f222352/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-28-12-58.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c37392d2-fa22-461a-9f61-39bc735b8be4/fb50fe53d4a25b80eafe8e39ab66cee1/deep/0/screenshot_333.jpg" alt=""&gt;&lt;/p&gt;
&lt;h2 id="privatexmlを書く"&gt;private.xmlを書く&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://pqrs.org/macosx/keyremap4macbook/xml.html.ja"&gt;公式リファレンス&lt;/a&gt;から持ってきたものです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;root&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;appdef&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;appname&amp;gt;&lt;/span&gt;APPSTORE&lt;span style="color:#f92672"&gt;&amp;lt;/appname&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;equal&amp;gt;&lt;/span&gt;com.apple.appstore&lt;span style="color:#f92672"&gt;&amp;lt;/equal&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/appdef&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;item&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;Space to Tab on App Store.app&lt;span style="color:#f92672"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;identifier&amp;gt;&lt;/span&gt;private.appdef&lt;span style="color:#f92672"&gt;&amp;lt;/identifier&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;only&amp;gt;&lt;/span&gt;APPSTORE&lt;span style="color:#f92672"&gt;&amp;lt;/only&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;autogen&amp;gt;&lt;/span&gt;__KeyToKey__ KeyCode::SPACE, KeyCode::TAB&lt;span style="color:#f92672"&gt;&amp;lt;/autogen&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/root&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;only&lt;/code&gt;タグ =&amp;gt; 特定のアプリケーションでのみ有効にしたい場合に使う&lt;/li&gt;
&lt;li&gt;&lt;code&gt;identifier&lt;/code&gt;タグ =&amp;gt; 各アイテムの識別子で、一意の文字列ならなんでもよさそう&lt;/li&gt;
&lt;li&gt;&lt;code&gt;appdef&lt;/code&gt;タグ =&amp;gt; &lt;code&gt;only&lt;/code&gt;で使うアプリ名をBundle IDを使って定義する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;このサンプルはMacAppStoreでのみショートカットを有効にするという例ですが、&lt;code&gt;appdef&lt;/code&gt;の&lt;code&gt;equal&lt;/code&gt;を書き換えることによって対象のアプリケーションを変えることももちろん可能です。&lt;/p&gt;
&lt;h3 id="bundle-idを調べる"&gt;Bundle IDを調べる&lt;/h3&gt;
&lt;p&gt;で、そのBundle IDを調べるにはどうしたらいいのかというと、XXXXXXX.appの中を覗けばわkるようになっています。&lt;/p&gt;
&lt;p&gt;Finderでアプリケーションフォルダを開いて対象のXXXXXX.appを右クリックするとパッケージの内容を表示となるので、その中にある&lt;code&gt;Contents&lt;/code&gt;フォルダの中にある&lt;code&gt;Info.plist&lt;/code&gt;を開きます。&lt;/p&gt;
&lt;p&gt;そして&lt;code&gt;CFBundleIdentifier&lt;/code&gt;を検索すると次のようなものが見つかると思います（↓はChromeの例）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleIdentifier&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.google.Chrome&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;下の行、&lt;code&gt;com.google.Chrome&lt;/code&gt;がBundleIDのです。先ほどの設定ファイルの&lt;code&gt;appdef&lt;/code&gt;のところに&lt;code&gt;com.google.Chrome&lt;/code&gt;と書けばChromeでのみ有効となるショートカットを定義できるようになるわけです。&lt;/p&gt;
&lt;h2 id="ショートカットを有効にする"&gt;ショートカットを有効にする&lt;/h2&gt;
&lt;p&gt;ReloadXMLボタンを押すとprivate.xmlに書いた項目が一番上に表れます。あとはチェックを入れて有効にすればOK。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/e9d3609a-ce9f-47a8-a9a7-184521fcdec2/ca71ce624e9e081487f0ac735a7dd488/deep/0/screenshot_334.jpg" alt=""&gt;&lt;/p&gt;</description></item><item><title>XcodeのstoryboardからUI部品にプロパティを与える方法</title><link>https://blog.piyo.tech/posts/2014-04-28-201708/</link><pubDate>Mon, 28 Apr 2014 20:16:53 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-28-201708/</guid><description>&lt;p&gt;Storyboard上に配置しているUI部品のプロパティを、Storyboard上から設定できるということを最近知りました。これってみんな知ってるんですかね？&lt;/p&gt;
&lt;h1 id="独自のボタンクラス"&gt;独自のボタンクラス&lt;/h1&gt;
&lt;p&gt;サンプルとして角丸半径や輪郭線の幅を外部から設定できる&lt;code&gt;UIButton&lt;/code&gt;のサブクラスを用意しました。公開プロパティ&lt;code&gt;cornerRadius&lt;/code&gt;、&lt;code&gt;borderWidth&lt;/code&gt;の値をStoryboardから設定する感じで使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// CustomeButton.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;UIKit/UIKit.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CustomButton&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;UIButton&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;assign&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; cornerRadius;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;assign&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; borderWidth;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;awakeFromNib&lt;/code&gt;メソッドを定義することでNibの読み込み時の処理を書けるようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// CustomeButton.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;#34;CustomButton.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@implementation&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CustomButton&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;awakeFromNib&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; self.layer.cornerRadius &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self.cornerRadius;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; self.layer.borderWidth &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self.borderWidth ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="storyboardでの設定"&gt;Storyboardでの設定&lt;/h1&gt;
&lt;p&gt;StoryboardでUIButtonを置いたらこの画像のようにクラスや値をセットします。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7fe900e4-7587-4002-9e05-fb76cf456fef/330b7a141f4337a92222c6296ac21c4b/deep/0/CustomButton---Main_iPhone.storyboard.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;なお余談ですが、&lt;code&gt;Key Path&lt;/code&gt;には先ほど定義した&lt;code&gt;CustomButton&lt;/code&gt;のプロパティだけでなく、&lt;code&gt;UIButton&lt;/code&gt;のプロパティも使うことができます。&lt;/p&gt;
&lt;h1 id="結果"&gt;結果&lt;/h1&gt;
&lt;p&gt;左Storyboard、右シミュレータです。この程度のサンプルではあまりメリットがないかもしれませんが、オリジナルのUIコンポーネントを作ってちょいちょいやりたいときには便利かも。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/ce9b5a6b-e7d9-4d1d-9b48-54a3fa821ede/0e359f4eabf070ff174995454efc66f1/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-28-12-26.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="ネタ元"&gt;ネタ元&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.albertopasca.it/whiletrue/2014/04/objc-uibutton-rounded-corners/"&gt;[ObjC] – UIButton with rounded corners&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Underscore.js風Objective-Cライブラリ「_.m」</title><link>https://blog.piyo.tech/posts/2014-04-27-204024/</link><pubDate>Sun, 27 Apr 2014 20:40:24 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-27-204024/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/6eb72a2e-d257-4f2c-8f07-4742f6e2a6ff/4cf70d13836bab6e6e3dee4741e11916/deep/0/underscore.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;マニアックなライブラリを見つけたのでメモっておきます！&lt;/p&gt;
&lt;p&gt;&lt;a href="http://kmalakoff.github.io/_.m/"&gt;_.m Home&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Underscore.js風のインターフェースを提供するObjective-Cのライブラリです。前書いたこれに少しだけ近い。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-03-11-185204"&gt;ActiveRecordのようなselectやwhereをObjective-Cで使う - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今回紹介する&lt;code&gt;_.m&lt;/code&gt;には&lt;code&gt;map&lt;/code&gt;とか&lt;code&gt;reduce&lt;/code&gt;みたいなものもあるので、より関数型っぽい？んじゃないかと思います。Underscore.jsなどを知っている人には無用だけど、提供されているインターフェースについてざっくりと紹介。&lt;/p&gt;
&lt;h1 id="each"&gt;each&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;_.each(AI(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;), &lt;span style="color:#f92672"&gt;^&lt;/span&gt;(N&lt;span style="color:#f92672"&gt;*&lt;/span&gt; num, ...){ SS.alert(num); });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// =&amp;gt; alerts each number in turn...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;_.each(OKV({&lt;span style="color:#e6db74"&gt;@&amp;#34;one&amp;#34;&lt;/span&gt;, N.I(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)}, {&lt;span style="color:#e6db74"&gt;@&amp;#34;two&amp;#34;&lt;/span&gt;, N.I(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)}, {&lt;span style="color:#e6db74"&gt;@&amp;#34;three&amp;#34;&lt;/span&gt;, N.I(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)}), &lt;span style="color:#f92672"&gt;^&lt;/span&gt;(N&lt;span style="color:#f92672"&gt;*&lt;/span&gt; num, ...){ SS.alert(num); });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// =&amp;gt; alerts each number in turn...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;each&lt;/code&gt;は各要素に特定の処理をさせるメソッドで、ループの代わりに使ったりします。まあ普通のeachってことです。&lt;/p&gt;
&lt;p&gt;よく見ると&lt;code&gt;AI&lt;/code&gt;とか&lt;code&gt;OKV&lt;/code&gt;とか&lt;code&gt;N&lt;/code&gt;といった謎のキーワードがでてきます。これは同じ人が書いたライブラリ&lt;code&gt;SubjectiveScript&lt;/code&gt;で定義されているマクロで、こんな感じになっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define AI(...) A.newI((I[]){__VA_ARGS__}, sizeof((I[]){__VA_ARGS__})/sizeof(I))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define OKV(...) O.newWithKV((KV[]){__VA_ARGS__, &lt;/span&gt;&lt;span style="color:#75715e"&gt;/* NIL_TERMINATION */&lt;/span&gt;&lt;span style="color:#75715e"&gt; nil})
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここでも&lt;code&gt;A&lt;/code&gt;とか&lt;code&gt;O&lt;/code&gt;とか色々略しまくっていてわかりにくいんですが、慣れた人に楽にかけるようにしたいって思想なんでしょうか。このライブラリについては最後に参考リンクと一部の定義を載せておきます。&lt;/p&gt;
&lt;h1 id="map"&gt;map&lt;/h1&gt;
&lt;p&gt;各要素の対する処理結果を配列で得る場合に使うmap関数。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;_.map(AI(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;), &lt;span style="color:#f92672"&gt;^&lt;/span&gt;(N&lt;span style="color:#f92672"&gt;*&lt;/span&gt; num, ...){ &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; N.I(num.I &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;); });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// =&amp;gt; [3, 6, 9]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;_.map(OKV({&lt;span style="color:#e6db74"&gt;@&amp;#34;one&amp;#34;&lt;/span&gt;, N.I(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)}, {&lt;span style="color:#e6db74"&gt;@&amp;#34;two&amp;#34;&lt;/span&gt;, N.I(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)}, {&lt;span style="color:#e6db74"&gt;@&amp;#34;three&amp;#34;&lt;/span&gt;, N.I(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)}), &lt;span style="color:#f92672"&gt;^&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;(N&lt;span style="color:#f92672"&gt;*&lt;/span&gt; num, ...){ &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; N.I(num.I &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;); });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// =&amp;gt; [3, 6, 9]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここは&lt;code&gt;AI&lt;/code&gt;やら&lt;code&gt;OKV&lt;/code&gt;などの略語がわかりさえすれば読めそうです。&lt;/p&gt;
&lt;h1 id="reduce"&gt;reduce&lt;/h1&gt;
&lt;p&gt;コレクションの中身を集約するときに使うreduceです。初期値を与えてそれに対して各要素を使った値を足したりしていく感じ。Rubyでは&lt;code&gt;inject&lt;/code&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;N&lt;span style="color:#f92672"&gt;*&lt;/span&gt; sum &lt;span style="color:#f92672"&gt;=&lt;/span&gt; _.reduce(AI(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;), &lt;span style="color:#f92672"&gt;^&lt;/span&gt;(N&lt;span style="color:#f92672"&gt;*&lt;/span&gt; memo, N&lt;span style="color:#f92672"&gt;*&lt;/span&gt; num, ...){ &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; N.I(memo.I &lt;span style="color:#f92672"&gt;+&lt;/span&gt; num.I); }, N.I(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// =&amp;gt; 6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="delay"&gt;delay&lt;/h1&gt;
&lt;p&gt;配列やディクショナリのようなコレクション要素に対する操作以外のこともできるようです。例えば&lt;code&gt;delay&lt;/code&gt;ではNミリ秒後に実行させたい処理を簡単に書くことができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;_.delay(&lt;span style="color:#f92672"&gt;^&lt;/span&gt;{ NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;%d&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;); }, NSEC_PER_SEC&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// =&amp;gt; &amp;#39;logged later&amp;#39; // Appears after one second.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="書き切れない"&gt;書き切れない&lt;/h1&gt;
&lt;p&gt;Underscore.jsにあるようなインターフェースのうちの8割〜9割ほどが提供されている感じです。公式のリファレンスが参考になりますが、Underscore.jsのリファレンスを読むのも助けになりそうです。&lt;/p&gt;
&lt;p&gt;日本語の場合はこういうまとめが参考になりそう。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://d.hatena.ne.jp/ninoseki/20110414/1302786001"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://d.hatena.ne.jp/ninoseki/20110414/1302786001" alt="便利機能満載のライブラリUnderscore.js - にのせき日記" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://d.hatena.ne.jp/ninoseki/20110414/1302786001"&gt;便利機能満載のライブラリUnderscore.js - にのせき日記&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/ninoseki/20110414/1302786001" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/ninoseki/20110414/1302786001" alt="はてなブックマーク - 便利機能満載のライブラリUnderscore.js - にのせき日記" title="はてなブックマーク - 便利機能満載のライブラリUnderscore.js - にのせき日記" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h1 id="subjectivescript"&gt;SubjectiveScript&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/kmalakoff/SubjectiveScript.m"&gt;kmalakoff/SubjectiveScript.m&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt; B;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; NSInteger I;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; NSUInteger UI;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt; F;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;double&lt;/span&gt; D;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;id&lt;/span&gt; KV[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;]; &lt;span style="color:#75715e"&gt;// key-value pair
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define NSO NSObject
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define A NSMutableArray
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define NSA NSArray
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define O NSMutableDictionary
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define NSD NSDictionary
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define S NSMutableString
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define NSS NSString
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define Date NSDate
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define N NSNumber
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define E NSException
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Android端末に登録済みのGoogleアカウントでOAuth</title><link>https://blog.piyo.tech/posts/2014-04-26-190713/</link><pubDate>Sat, 26 Apr 2014 19:07:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-26-190713/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b50969f5-24d6-44a9-b649-a8c1c763d804/addff1d65afef877468bd000f6270d09/deep/0/google_logo.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Android触り始めています。Androidでは端末にGoogleのアカウントを登録でき、アプリでは端末に登録済みのアカウントを使ってGoogleの各種サービスと連携できるため、ユーザーに改めてログインを求める必要がありません。&lt;/p&gt;
&lt;p&gt;ということで色々調べてサンプル的に実装し始めたのですが、全然まとまった情報がなくて超困りました。iOSでGoogleAPIのことを調べていたときもそうだったんですが、GoogleのAPI周りの情報はすごくわかりづらいですね。MicrsoftのMSDNを読んでいるような感じがしました、っていうと言い過ぎか。&lt;/p&gt;
&lt;p&gt;なお、Android Studioでの話です。&lt;/p&gt;
&lt;h1 id="サンプルを探す"&gt;サンプルを探す&lt;/h1&gt;
&lt;p&gt;まずはサンプルを探しました。で、Javaのクライアントのドキュメントに簡単そうに見えるサンプルがあったのでこれ（↓）を試そうと思ったんですが、すでにインターフェース変わっていて使えませんでした！ちくしょー&lt;/p&gt;
&lt;p&gt;&lt;a href="https://code.google.com/p/google-api-java-client/wiki/OAuth2#Android"&gt;OAuth2 - google-api-java-client - OAuth 2.0 - Google APIs Client Library for Java - Google Project Hosting&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;気を取り直して最新と思われるものを探したら、これが見つかりました。&lt;/p&gt;
&lt;p&gt;[https://code.google.com/p/google-api-java-client/source/browse?repo=samples#hg/ / - google-api-java-client - Google APIs Client Library for Java - Google Project Hosting]&lt;/p&gt;
&lt;p&gt;Mercurialで管理されているソースコードです。一式cloneしておくとよさそうなので、次のコマンドでローカルに持ってきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% hg clone https://code.google.com/p/google-api-java-client.samples/ google-api-java-client-samples
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="プロジェクトを作る"&gt;プロジェクトを作る&lt;/h1&gt;
&lt;p&gt;Androidに慣れていないこともあって、ダウンロードしてきたサンプルコードがそのまま動かなくてハマることが多々ありました。新規プロジェクトを作り、サンプルコードを参考に必要な部分を書いていくことにします。&lt;/p&gt;
&lt;p&gt;参考にしたのは、&lt;code&gt;tasks-android-sample&lt;/code&gt;です。&lt;/p&gt;
&lt;h2 id="google-play-services"&gt;Google Play services&lt;/h2&gt;
&lt;p&gt;Google Play servicesという追加のSDKを入れる必要があります。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/07b90403-073a-410f-a086-1154e599580a/6b73a29fab56cc6c4cdfbc642391476f/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-25-21-44.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="google-api-java-client"&gt;google-api-java-client&lt;/h2&gt;
&lt;p&gt;依存していそうなライブラリを全部入れておきましょう。本番では不要なものは外せばいいけど、検証なのでそういう細かいことは無視です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://code.google.com/p/google-api-java-client/wiki/Setup#Download_Library_with_Dependencies"&gt;Setup - google-api-java-client - Download and Setup instructions - Google APIs Client Library for Java - Google Project Hosting&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;持ってきたライブラリの&lt;code&gt;jar&lt;/code&gt;ファイルをプロジェクトの&lt;code&gt;libs&lt;/code&gt;ディレクトリに移動します。&lt;/p&gt;
&lt;h2 id="buildgradle"&gt;build.gradle&lt;/h2&gt;
&lt;p&gt;このあたりで&lt;code&gt;gradle&lt;/code&gt;ファイルの中身を確認しとくといいですね。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;dependencies {
compile &amp;#39;com.android.support:appcompat-v7:+&amp;#39;
compile &amp;#39;com.google.android.gms:play-services:+&amp;#39; # この行は追記
compile fileTree(dir: &amp;#39;libs&amp;#39;, include: [&amp;#39;*.jar&amp;#39;]) # この行があることを確認
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;play-servicesの行を書かなくてビルドで怒られてしまいしばらくはまりました。&lt;/p&gt;
&lt;h1 id="実装編"&gt;実装編&lt;/h1&gt;
&lt;h2 id="全文はこちら"&gt;全文はこちら&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/pi-chan/11288689"&gt;https://gist.github.com/pi-chan/11288689&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="oncreate"&gt;onCreate&lt;/h2&gt;
&lt;p&gt;onCreateでは主にAPIの設定を行っています。ついでにボタンのイベントハンドラもここに直で書いています。&lt;/p&gt;
&lt;p&gt;この部分がAPIの設定。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt; mCredential &lt;span style="color:#f92672"&gt;=&lt;/span&gt; GoogleAccountCredential.&lt;span style="color:#a6e22e"&gt;usingOAuth2&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;, Collections.&lt;span style="color:#a6e22e"&gt;singleton&lt;/span&gt;(TasksScopes.&lt;span style="color:#a6e22e"&gt;TASKS&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; SharedPreferences settings &lt;span style="color:#f92672"&gt;=&lt;/span&gt; getPreferences(Context.&lt;span style="color:#a6e22e"&gt;MODE_PRIVATE&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; mCredential.&lt;span style="color:#a6e22e"&gt;setSelectedAccountName&lt;/span&gt;(settings.&lt;span style="color:#a6e22e"&gt;getString&lt;/span&gt;(PREF_ACCOUNT_NAME, &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; service &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Tasks.&lt;span style="color:#a6e22e"&gt;Builder&lt;/span&gt;(mHttpTransport, mJsonFactory, mCredential)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;setApplicationName&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Google-TasksAndroidSample/1.0&amp;#34;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;build&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ボタンクリックでは&lt;code&gt;chooseAccount&lt;/code&gt;メソッドを呼ぶだけにしています。&lt;/p&gt;
&lt;h2 id="onactivityresult"&gt;onActivityResult&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;requestCode&lt;/code&gt;などの条件が満たされていたら情報を取り出してきてアカウント名をログに出すってことをしています。これで一応認証が済みました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(requestCode &lt;span style="color:#f92672"&gt;==&lt;/span&gt; REQUEST_ACCOUNT_PICKER &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; resultCode &lt;span style="color:#f92672"&gt;==&lt;/span&gt; RESULT_OK &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; data &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; data.&lt;span style="color:#a6e22e"&gt;getExtras&lt;/span&gt;() &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt; ){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; String accountName &lt;span style="color:#f92672"&gt;=&lt;/span&gt; data.&lt;span style="color:#a6e22e"&gt;getExtras&lt;/span&gt;().&lt;span style="color:#a6e22e"&gt;getString&lt;/span&gt;(AccountManager.&lt;span style="color:#a6e22e"&gt;KEY_ACCOUNT_NAME&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(accountName &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; mCredential.&lt;span style="color:#a6e22e"&gt;setSelectedAccountName&lt;/span&gt;(accountName);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; SharedPreferences settings &lt;span style="color:#f92672"&gt;=&lt;/span&gt; getPreferences(Context.&lt;span style="color:#a6e22e"&gt;MODE_PRIVATE&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; SharedPreferences.&lt;span style="color:#a6e22e"&gt;Editor&lt;/span&gt; editor &lt;span style="color:#f92672"&gt;=&lt;/span&gt; settings.&lt;span style="color:#a6e22e"&gt;edit&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; editor.&lt;span style="color:#a6e22e"&gt;putString&lt;/span&gt;(PREF_ACCOUNT_NAME, accountName);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; Log.&lt;span style="color:#a6e22e"&gt;d&lt;/span&gt;(TAG, accountName);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="次にやるべきこと"&gt;次にやるべきこと&lt;/h1&gt;
&lt;p&gt;実際にサービスから情報を取ってくるところに辿りつくためにはまだわかっていないことがたくさんあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一度認証したらその情報を残せるのか？&lt;/li&gt;
&lt;li&gt;アクセストークンは？&lt;/li&gt;
&lt;li&gt;API_KEY使ってないぞ？&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Android端末の写真をコードから削除する</title><link>https://blog.piyo.tech/posts/2014-04-25-204708/</link><pubDate>Fri, 25 Apr 2014 20:46:56 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-25-204708/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/713c9513-e67c-4e11-9f1a-cb73b5f9f446/5ac8868ed058e316f54c31b604053a89/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-23-15-32.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Android触り始めました。さすがに初めてすぎて全然わかんない。&lt;/p&gt;
&lt;p&gt;iOSと違ってAndroidでは公式ではないアプリが写真を削除できるらしいということでサンプルを書いてためしてみました。&lt;/p&gt;
&lt;p&gt;下のコードでは&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ギャラリーを開いて&lt;/li&gt;
&lt;li&gt;写真を選択して&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ContentResolver::delete&lt;/code&gt;にURI渡しで削除&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MainActivity&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; ActionBarActivity {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onCreate&lt;/span&gt;(Bundle savedInstanceState) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;onCreate&lt;/span&gt;(savedInstanceState);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; setContentView(R.&lt;span style="color:#a6e22e"&gt;layout&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;activity_main&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ボタンクリックで写真選択へ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; Button b &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (Button)findViewById(R.&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;button_open&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; b.&lt;span style="color:#a6e22e"&gt;setOnClickListener&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; View.&lt;span style="color:#a6e22e"&gt;OnClickListener&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onClick&lt;/span&gt;(View v) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; Intent intent &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Intent();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; intent.&lt;span style="color:#a6e22e"&gt;setType&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;image/*&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; intent.&lt;span style="color:#a6e22e"&gt;setAction&lt;/span&gt;(Intent.&lt;span style="color:#a6e22e"&gt;ACTION_PICK&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; startActivityForResult(intent, 0);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onActivityResult&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; requestCode, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; resultCode, Intent data) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (requestCode &lt;span style="color:#f92672"&gt;==&lt;/span&gt; 0 &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; resultCode &lt;span style="color:#f92672"&gt;==&lt;/span&gt; RESULT_OK) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; getContentResolver().&lt;span style="color:#a6e22e"&gt;delete&lt;/span&gt;(data.&lt;span style="color:#a6e22e"&gt;getData&lt;/span&gt;(), &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt; (Exception e){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; Log.&lt;span style="color:#a6e22e"&gt;d&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;MainActivity&amp;#34;&lt;/span&gt;, e.&lt;span style="color:#a6e22e"&gt;getMessage&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;でもこれだけでは削除は完了しません。&lt;/p&gt;
&lt;p&gt;例外キャッチ時のメッセージを適当な&lt;code&gt;&amp;quot;Fail&amp;quot;&lt;/code&gt;みたいなメッセージにしていたせいで全然気が付かなかったんですが、ちゃんと例外メッセージを出したらこんなん↓が出てました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;writing com.android.providers.media.MediaProvider uri content://media/external/images/media/1368
from pid=27267, uid=10071 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;パーミッションが足りないらしい。&lt;/p&gt;
&lt;p&gt;ということで&lt;code&gt;AndroidManifest.xml&lt;/code&gt;にパーミッションに関して追記することで削除ができるようになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;utf-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;manifest&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;xmlns:android=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://schemas.android.com/apk/res/android&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;package=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;com.....&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;application&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/application&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;android:name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;android.permission.WRITE_EXTERNAL_STORAGE&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/manifest&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;多分パーミッションの設定自体Android開発では当たり前のことなんでしょうね。誰も言及してないし。&lt;/p&gt;</description></item><item><title>bundle openで使うBUNDLER_EDITORをカスタマイズする</title><link>https://blog.piyo.tech/posts/2014-04-24-200613/</link><pubDate>Thu, 24 Apr 2014 20:06:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-24-200613/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/2afcce6d-ead2-405d-af63-7e9703abc187/4e6cee5177faa72b513db9aef8552df4/deep/0/gembundler.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Rebuild.fmで開発環境の話が出たので便乗。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://rebuild.fm/41/"&gt;Rebuild: 41: Kids These Days Don&amp;rsquo;t Know Shell (Naoya Ito)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bundle open&lt;/code&gt;するとEDITORに指定されているエディタでgemのディレクトリが開く仕組みになっています。@miyagawaさんはEDITORに自分で書いたシェルスクリプトを指定していて、シェルでgemのディレクトリに移動してlsとかいろいろやって編集してシェルをExitすると元のディレクトリに戻るって話をしていました。なにそれ便利そう、っていうね。&lt;/p&gt;
&lt;h1 id="bundler_editor"&gt;BUNDLER_EDITOR&lt;/h1&gt;
&lt;p&gt;シェルが開くエディタは一般的には&lt;code&gt;EDITOR&lt;/code&gt;環境変数に設定しますが、Bundler用の環境変数&lt;code&gt;BUNDLER_EDITOR&lt;/code&gt;というものがあります。これを使うことで既存のEDITORを変える必要がありません。&lt;/p&gt;
&lt;p&gt;この環境変数にシェルスクリプトのパスを入れておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# .zshrc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;export BUNDLER_EDITOR&lt;span style="color:#f92672"&gt;=&lt;/span&gt;~/bin/bundler.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="シェルスクリプト"&gt;シェルスクリプト&lt;/h1&gt;
&lt;p&gt;肝心のシェルスクリプトの中身ですが、これだけｗｗ&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;zsh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでカレントディレクトリがgemのディレクトリになった状態でシェルが起動してくれました。本当は&lt;code&gt;zsh&lt;/code&gt;のあとで&lt;code&gt;clear&lt;/code&gt;して&lt;code&gt;ls&lt;/code&gt;したかったんだけど、ちょっと調べてわからなかったのでパスしました。&lt;/p&gt;</description></item><item><title>Octopressによるブログ構築+Tips</title><link>https://blog.piyo.tech/posts/2014-04-23-201004/</link><pubDate>Wed, 23 Apr 2014 20:09:54 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-23-201004/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/37812171-cdc4-45b0-963c-9f9be79152bd/435dafabd775e0c47223c7632d349f66/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-23-0-08.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ブログはこっちがメインなんだけど、調べたこととか学んだことをさくっと書いておく場所が欲しくて少し前から静的サイトジェネレータについて調べていたんですが、それがだいたい落ち着いたんでまとめておきます。&lt;/p&gt;
&lt;p&gt;まず結論ですが、こうなりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Octopress(Ruby)&lt;/li&gt;
&lt;li&gt;さくらVPS&lt;/li&gt;
&lt;li&gt;Bitbucket+GitHubで管理&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="導入編"&gt;導入編&lt;/h1&gt;
&lt;p&gt;英語ではありますが公式が一番わかりやすいです。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://octopress.org/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://octopress.org/" alt="Octopress" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://octopress.org/"&gt;Octopress&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://octopress.org/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://octopress.org/" alt="はてなブックマーク - Octopress" title="はてなブックマーク - Octopress" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;ソース一式持ってきて&lt;code&gt;bundle&lt;/code&gt;するだけなんでRubyが入っていれば余裕です。日本のユーザーも多いのでググれば見つかるはずです。導入については特に触れません。&lt;/p&gt;
&lt;h2 id="使い方"&gt;使い方&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rake new_post&lt;/code&gt;で新規ブログ記事&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rake new_page&lt;/code&gt;で新規ページ&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rake generate&lt;/code&gt;でサイト生成&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rake rsync&lt;/code&gt;でVPSにアップロード&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rake preview&lt;/code&gt;でファイルを監視しつつローカルサーバーでサーブ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;僕が使うのはこのあたりです。&lt;/p&gt;
&lt;h1 id="tips編"&gt;Tips編&lt;/h1&gt;
&lt;h2 id="rakefile"&gt;Rakefile&lt;/h2&gt;
&lt;h3 id="rsyncの設定"&gt;Rsyncの設定&lt;/h3&gt;
&lt;p&gt;Rsyncのコマンドに指定した秘密鍵があるような場合はデフォルトのままでは動かないのでコマンド自体を書き換える必要がありました。&lt;/p&gt;
&lt;p&gt;元々こうなっているところを&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rsync -avze &amp;#39;ssh -p &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;ssh_port&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;exclude&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;rsync_args&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;--delete&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; rsync_delete &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;public_dir&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;ssh_user&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;document_root&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こう変更。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rsync -avze &amp;#39;ssh -p &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;ssh_port&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; -i &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;identity_file&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;exclude&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;rsync_args&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;--delete&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; rsync_delete &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;public_dir&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;ssh_user&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;document_root&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="rakeタスクのエイリアス"&gt;Rakeタスクのエイリアス&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;rake rsync&lt;/code&gt;などとタイプするのが面倒なので↓のリンクを参考にエイリアス的に使えるようにしました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.toshimaru.net/rake-alias/"&gt;Rakeタスクにエイリアスを付ける - Hack Your Design!&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;alias_task&lt;/span&gt;(tasks)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; tasks&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;new_name, old_name&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; task new_name, &lt;span style="color:#f92672"&gt;[*&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Rake&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;[&lt;/span&gt;old_name&lt;span style="color:#f92672"&gt;].&lt;/span&gt;arg_names&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;old_name&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;alias_task &lt;span style="color:#f92672"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:n&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:new_post&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:g&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:generate&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:s&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:rsync&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:p&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:preview&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="データ管理"&gt;データ管理&lt;/h2&gt;
&lt;p&gt;Octopressが生成するWebサイトのファイルはデフォルトではルートディレクトリの&lt;code&gt;public/&lt;/code&gt;以下に配置されます。生成後のファイルとそれ以外（Octopress自体のソースコードやMarkdown形式の投稿ファイル）は別でソース管理したいなと思いました。&lt;/p&gt;
&lt;p&gt;生成後のファイルはそもそもWebで公開するつもりなのでGitHubで、それ以外のファイルは設定ファイルなどが含まれることもあってBitbucketのプライベートRepoで行くことに。&lt;code&gt;public/&lt;/code&gt;以下を別のリポジトリとして管理し、Octopress側のリポジトリのsubmoduleとして追加するという方法をとりました。&lt;/p&gt;
&lt;p&gt;これでいいじゃんと思っていたら1つ困ったことがあって、&lt;code&gt;rake generate&lt;/code&gt;の際に&lt;code&gt;public/&lt;/code&gt;が一旦削除されてもう一度生成されるという仕組みになっているため、ローカルリポジトリ（&lt;code&gt;.git&lt;/code&gt;）まで削除されてしまうんですよね。&lt;/p&gt;
&lt;p&gt;それじゃ意味ないから&lt;code&gt;public/&lt;/code&gt;以下の&lt;code&gt;.git&lt;/code&gt;などは残すって作戦はどうかと考えたんだけど、Octopressはサイト生成部分はJekyllに丸投げしているだけなので手をいれるのはちょっと重そうだということがわかりました。&lt;/p&gt;
&lt;p&gt;最終的には、&lt;code&gt;public/&lt;/code&gt;は単なる吐き出し先とし、GitHubで管理するサイトのデータは別のディレクトリを使うことにしました。&lt;code&gt;rake generate&lt;/code&gt;でサイト生成後、&lt;code&gt;public/&lt;/code&gt;の中身を&lt;code&gt;website/&lt;/code&gt;というディレクトリに丸コピーする作戦です。もちろんドットファイル以外は削除してからコピーするので不要なファイルが残ることもありません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;desc &lt;span style="color:#e6db74"&gt;&amp;#34;Generate jekyll site&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;task &lt;span style="color:#e6db74"&gt;:generate&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;raise&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;### You haven&amp;#39;t set anything up yet. First run `rake install` to set up an Octopress theme.&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;directory?(source_dir)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#34;## Generating Site with Jekyll&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; system &lt;span style="color:#e6db74"&gt;&amp;#34;compass compile --css-dir &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;source_dir&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/stylesheets&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; system &lt;span style="color:#e6db74"&gt;&amp;#34;jekyll&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 次の2行を追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; system &lt;span style="color:#e6db74"&gt;&amp;#34;rm -rf website/*&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; system &lt;span style="color:#e6db74"&gt;&amp;#34;cp -r public/ website&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="公開先"&gt;公開先&lt;/h1&gt;
&lt;p&gt;コードのコピペとかソース読んだときのメモをバシバシおいているだけなので情報価値は少ないかもしれませんが、ある程度まとまったところでこちらのブログに載せるかもしれません。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://site.piyox.info/"&gt;pi-chanメモ置き場&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Launchd用plistジェネレータ</title><link>https://blog.piyo.tech/posts/2014-04-21-203636/</link><pubDate>Mon, 21 Apr 2014 20:36:29 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-21-203636/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/df3fb317-7efa-4614-9751-f2955f6e137b/96dcdb3b053039d28322e412caaa24de/deep/0/imgres-2.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ローカルのMacで定期的にスクリプトを実行するために最近のMacではCronではなくLaunchDeamon（Launchd）を使うらしいんですが、そのための設定ファイルがplistでまあわかりにくいわけですよ。&lt;/p&gt;
&lt;p&gt;使おうとするとこんな感じでやることになります。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qiita.com/archinwater/items/4c2e9174e4898a197de6"&gt;launchd(8)の使い方 - Qiita&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;また、MacAppのLaunchdクライアントもあります（有料）。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.peterborgapps.com/lingon/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://www.peterborgapps.com/lingon/" alt="Lingon - Peter Borg Apps" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://www.peterborgapps.com/lingon/"&gt;Lingon - Peter Borg Apps&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;僕個人としてはそんなに使わないんだからケチりたいなーと思っていたところ。よく探したらplistファイルを生成するサービスがあったので紹介します。&lt;/p&gt;
&lt;h1 id="launched"&gt;launched&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://launched.zerowidth.com/"&gt;Launched A launchd.plist generator&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="設定する"&gt;設定する&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/2cfb5155-e0d8-4212-b4e8-1036e85e51ed/d81bdb9681a75a7e9a6538316958b26f/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-21-11-35.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="インストール"&gt;インストール&lt;/h2&gt;
&lt;p&gt;設定が終わったら画面右下のCreateボタンを押し、次の画面へ。するとこのような画面が得られます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9e04163a-859e-454c-93c2-bda1759a6386/4fc9731da288bf3f0951140f211fa6b7/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-21-11-35.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Installのところにあるコマンドをコピペしてシェルに貼り付けて実行すると、ユーザー用の設定ファイル置き場にplistがコピーされた上で&lt;code&gt;launchctl&lt;/code&gt;での実行登録まで済ませてくれます。&lt;/p&gt;
&lt;p&gt;シェルスクリプトの中身はこんなふうになっていて、該当ディレクトリにファイルをコピーして&lt;code&gt;launchctl&lt;/code&gt;を呼び出すだけのものです。危険なことはなんもないですね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;echo downloading com.zerowidth.launched.hogewriter.plist...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;mkdir -p ~/Library/LaunchAgents
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;curl -o ~/Library/LaunchAgents/com.zerowidth.launched.hogewriter.plist http://launched.zerowidth.com/plists/7ec12ca0-ab2b-0131-266c-76b008842fe3.xml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;echo installing com.zerowidth.launched.hogewriter.plist...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;launchctl load -w ~/Library/LaunchAgents/com.zerowidth.launched.hogewriter.plist
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="無効にする"&gt;無効にする&lt;/h2&gt;
&lt;p&gt;とりあえず試してみるにしても、バックグラウンドで勝手に動き続けてしまうものなので、解除方法を知らないと大変です。解除は自分でやりましょう。&lt;/p&gt;
&lt;p&gt;ここが参考になります。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.maruko2.com/mw/LaunchDaemons_(launchctl,_launchd.plist)_%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9"&gt;LaunchDaemons (launchctl, launchd.plist) の使い方 - maruko2 Note.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;例えばさっきの例、&lt;code&gt;~/Library/LaunchAgents/com.zerowidth.launched.hogewriter.plist&lt;/code&gt;で言うと、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;% launchctl unload -w ~/Library/LaunchAgents/com.zerowidth.launched.hogewriter.plist
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;unload -w&lt;/code&gt;で無効化してあげれば大丈夫です。&lt;/p&gt;</description></item><item><title>iOS、Androidの空き容量をコードで調べる</title><link>https://blog.piyo.tech/posts/2014-04-19-234427/</link><pubDate>Sat, 19 Apr 2014 23:44:27 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-19-234427/</guid><description>&lt;h1 id="ios"&gt;iOS&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;NSArray &lt;span style="color:#f92672"&gt;*&lt;/span&gt;paths &lt;span style="color:#f92672"&gt;=&lt;/span&gt; NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;NSDictionary &lt;span style="color:#f92672"&gt;*&lt;/span&gt;dictionary &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error:nil];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (dictionary) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; GiB &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt; free &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[dictionary objectForKey: NSFileSystemFreeSize] floatValue]&lt;span style="color:#f92672"&gt;/&lt;/span&gt;GiB;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt; total &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[dictionary objectForKey: NSFileSystemSize] floatValue]&lt;span style="color:#f92672"&gt;/&lt;/span&gt;GiB;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;Space: %.3f&amp;#34;&lt;/span&gt;, free);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;Total: %.3f&amp;#34;&lt;/span&gt;, total);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="android"&gt;Android&lt;/h1&gt;
&lt;p&gt;ディレクトリのパスはいくつかとれますが、デバイスによって使われ方がどうも違うっぽい感じがしました。&lt;/p&gt;
&lt;p&gt;写真のデータ置き場は&lt;code&gt;getDataDirectory&lt;/code&gt;で取れるパスが正解のような感じ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Environment.getDataDirectory()&lt;/li&gt;
&lt;li&gt;Environment.getExternalStorageDirectory()&lt;/li&gt;
&lt;li&gt;Environment.getRootDirectory()&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;参考&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.adakoda.com/android/000134.html"&gt;データ／キャッシュ／外部ストレージ／システムのパスを取得するには - 逆引きAndroid入門&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;long&lt;/span&gt; MEGA_BYTE &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 1048576;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;String path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Environment.&lt;span style="color:#a6e22e"&gt;getDataDirectory&lt;/span&gt;().&lt;span style="color:#a6e22e"&gt;getAbsolutePath&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;StatFs statFs &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; StatFs(path);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;long&lt;/span&gt; availableBlocks &lt;span style="color:#f92672"&gt;=&lt;/span&gt; statFs.&lt;span style="color:#a6e22e"&gt;getAvailableBlocks&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;long&lt;/span&gt; blockSize &lt;span style="color:#f92672"&gt;=&lt;/span&gt; statFs.&lt;span style="color:#a6e22e"&gt;getBlockSize&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;long&lt;/span&gt; freeBytes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; availableBlocks &lt;span style="color:#f92672"&gt;*&lt;/span&gt; blockSize;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;Log.&lt;span style="color:#a6e22e"&gt;d&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;MyApp&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Free:&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; (freeBytes &lt;span style="color:#f92672"&gt;/&lt;/span&gt; MEGA_BYTE));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>テキスト欄に書いたRubyのコードをAutomatorで評価する</title><link>https://blog.piyo.tech/posts/2014-04-18-212759/</link><pubDate>Fri, 18 Apr 2014 21:27:59 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-18-212759/</guid><description>&lt;p&gt;昨日つぶやいたこれについてです。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p&gt;選択したテキストをRubyのコードとして評価して結果を置き換えるというやつ。これ結構前に知って使ってなかったけどいざやってみるとめちゃくちゃ便利。ちょっとした計算とか。 / “Mac を…” &lt;a href="http://t.co/qztBDb4wUY"&gt;http://t.co/qztBDb4wUY&lt;/a&gt; &lt;a href="https://twitter.com/search?q=%23ruby&amp;amp;src=hash"&gt;#ruby&lt;/a&gt; &lt;a href="https://twitter.com/search?q=%23automator&amp;amp;src=hash"&gt;#automator&lt;/a&gt; &lt;a href="https://twitter.com/search?q=%23Mac&amp;amp;src=hash"&gt;#Mac&lt;/a&gt;&lt;/p&gt;&amp;mdash; 大野浩誠 (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/statuses/456655644410392576"&gt;April 17, 2014&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;元記事はタイトルだとなんのことかわかりにくいのですが、それでもブックマークが900以上ついているのがすごい。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://d.hatena.ne.jp/r_kurain/20130219/1361270262"&gt;&amp;lt;img src=&amp;ldquo;&lt;a href="https://capture.heartrails.com/150x130/shadow?http://d.hatena.ne.jp/r_kurain/20130219/1361270262%22"&gt;https://capture.heartrails.com/150x130/shadow?http://d.hatena.ne.jp/r_kurain/20130219/1361270262&amp;quot;&lt;/a&gt; alt=&amp;ldquo;Mac を使っているなら必ず使うべき2つの機能 &amp;ldquo;Automator&amp;rdquo; と &amp;ldquo;サービス&amp;rdquo; - kurainの壺&amp;rdquo; style=&amp;ldquo;border:none;float:left;margin:0 .5em .5em 0;&amp;rdquo; /&amp;gt;&lt;/a&gt;&lt;a href="http://d.hatena.ne.jp/r_kurain/20130219/1361270262"&gt;Mac を使っているなら必ず使うべき2つの機能 &amp;ldquo;Automator&amp;rdquo; と &amp;ldquo;サービス&amp;rdquo; - kurainの壺&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/r_kurain/20130219/1361270262" target="_blank" rel="nofollow"&gt;&amp;lt;img src=&amp;ldquo;&lt;a href="https://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/r_kurain/20130219/1361270262%22"&gt;https://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/r_kurain/20130219/1361270262&amp;quot;&lt;/a&gt; alt=&amp;ldquo;はてなブックマーク - Mac を使っているなら必ず使うべき2つの機能 &amp;ldquo;Automator&amp;rdquo; と &amp;ldquo;サービス&amp;rdquo; - kurainの壺&amp;rdquo; title=&amp;ldquo;はてなブックマーク - Mac を使っているなら必ず使うべき2つの機能 &amp;ldquo;Automator&amp;rdquo; と &amp;ldquo;サービス&amp;rdquo; - kurainの壺&amp;rdquo; style=&amp;ldquo;border:none&amp;rdquo; /&amp;gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h1 id="何やってるかっていうと"&gt;何やってるかっていうと&lt;/h1&gt;
&lt;p&gt;1.Rubyのコードを書いて選択
1.Automatorで作ったサービスを起動する
1.サービスではrubyにテキストを渡す
1.さっき選択していたテキストがRubyのコードとして実行される
1.結果で置き換える&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/zJD2Rm-d47KjoVIxFy5udCNVYYfd514ypugi5-pVOzzke7hJ_MUo70Ih2QpiwD8s6SXfCCXEHmeVV_RJ_cTKcqmhhKq_N1Y8Zkdt-YU-hltL2z9-T5mJDHOIacSeNgsQAF9WpCiSf6OsLPqxPDSUE2NQGDt4R-Bxsp5mP0QFTfRSsmHltSzjMdX1eODOASZo6nMpdPeKjx_axwH5P3U4zkAcQghQSVQvgYSW7-QhgkDLF8xOW_5pWeMbIGLptZkLK9AounkUjq28mE_6LiabavuBtKn12ONWpRjfDDEiQBwMTjUYhmHo_QJgk-IFqKsCD-O1Kili_T-A-h57mYZJuxLtiwoxV9Rq2yFnZ4zXrMHBwYfhScWbrkHRLh3EtH2-8lLSz7L77b5eWs_D5bW_7L7-4vvmdTWqzcXUuRznjRtMw8zePRi5PkkijzRfL7b0NEHW6QePN5a4gOaKSBDdtDyyLoSGjnGxN58HCtn6GxH94__6pZkOcrnSzpimgXeijM5B8mcJwKs7-rXDW_iWnYxALctcCEq5vksX4WY78s2jphE1_aIMhIPShq42lG1kIHZcl2ohhkzodq76rGDvx7H0MArqB7G7XXSJJfW7O_d7AL8gYaf02z9FkdMc3Y-RQRzU-o4g6K-ZSYWqYLgZnxiW4HrX39S9Sw=w540-h252-no" alt=""&gt;&lt;/p&gt;
&lt;h1 id="便利っぽい使いどころ"&gt;便利っぽい使いどころ&lt;/h1&gt;
&lt;h2 id="連番を振る"&gt;連番を振る&lt;/h2&gt;
&lt;p&gt;さっきのキャプチャでもあるようにちょっとした連番を振るのに便利でした。こんなやつ。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; 1.
2.
3.
...
10.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これでいけます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;..&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each {&lt;span style="color:#f92672"&gt;|&lt;/span&gt;i&lt;span style="color:#f92672"&gt;|&lt;/span&gt; printf &lt;span style="color:#e6db74"&gt;&amp;#34;%2d.&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, i}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="計算する"&gt;計算する&lt;/h2&gt;
&lt;p&gt;普通の四則演算とかも便利かも。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;p &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# -46&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こんな感じで改行ありの数値列の合計を求めたいときとか。（ちなみにこのランダム数値列は&lt;code&gt;5.times { printf &amp;quot;%d\n&amp;quot;, rand(1000) }&lt;/code&gt;で出したものです）&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;50
186
860
600
787
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;データを少しいじって配列化したあと合計をとればいけます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;p &lt;span style="color:#f92672"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;186&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;860&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;600&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;787&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;].&lt;/span&gt;inject(&lt;span style="color:#e6db74"&gt;:+&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 2483&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="置換する"&gt;置換する&lt;/h2&gt;
&lt;p&gt;これはエディターでやればいいんだった…&lt;/p&gt;
&lt;p&gt;他にも便利なケースがあったら知りたい。&lt;/p&gt;</description></item><item><title>KFCocoaPodsPluginの検索機能にGitHubのスター数を出す</title><link>https://blog.piyo.tech/posts/2014-04-17-205232/</link><pubDate>Thu, 17 Apr 2014 20:52:32 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-17-205232/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7ee70e03-ec1c-41f2-885e-6607fb53af92/b83c508d8303d9d4b598713c49449bc9/deep/0/Octocat.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;以前、XcodeからPodの追加や検索ができる&lt;strong&gt;KFCocoaPodsPlugin&lt;/strong&gt;がかなり便利という記事と検索したPodを選ぶ際にGitHubのスター数を参考にするという記事を書きました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2014-04-07-193002"&gt;CocoaPods用Xcodeプラグインがかなり便利 - ぴよログ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2014-04-08-215547"&gt;CocoaPodsの比較にGitHubのスター数を用いる - ぴよログ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上で目的は果たせるものの、どうせならスター数を参考にする機能がプラグインに入っていればいいのにと思い立ってこのプラグイン途中まで改造しました。&lt;/p&gt;
&lt;p&gt;そして、こんな感じでリストにスター数を表示させることに成功！&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/5e4b2cc4-da56-47a7-bbf8-1f3e851eac74/3232d125d77decbd80455d2e1d734c90/deep/0/KFCocoaPodsPlugin---KFPodSearchWindow.xib.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;この変更のDiffは↓です。後述するように試作段階でだめだこりゃーとなったので適当なコードです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/KFCocoaPodsPlugin/commit/1a32fd0cc52ec4a7c4a718ddf801815a6bd0ec62#diff-7e4a60cfe31b1ac442a3e2496ae220e3R156"&gt;stargazer · 1a32fd0 · xoyip/KFCocoaPodsPlugin&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="api呼びすぎ"&gt;API呼びすぎ&lt;/h1&gt;
&lt;p&gt; 結構いい感じに使えそう！と思ったけどGitHubのAPIを呼びまくることになるのでこの実装は辞めたほうが良さそうだなと気づきました。&lt;/p&gt;
&lt;p&gt;数えていないのですが、この検索ダイアログに載る検索候補が100とか200以上あるはずです。その全てのレポジトリに対してGitHubのAPIを呼び出してスター数を数えるというのは現実的ではありません。そもそもTokenなしではすぐにアクセスの上限に到達してしまいましたし、Tokenを使ったところでお作法の良いクライアントであるとは言えません。&lt;/p&gt;
&lt;h1 id="改善案"&gt;改善案&lt;/h1&gt;
&lt;p&gt;プラグインからスター数を検索するというのは悪くないアイデアだと思いますが、いきなりスター数を取りに行くというのがダメでした。検索で絞り込んだものに対してスター数を問い合わせるのであれば対象も減っているしオンデマンドでいいなぁという気がします。&lt;/p&gt;</description></item><item><title>masuidriveさんの「wri.peを事例に学ぶ」開発編・リリース編</title><link>https://blog.piyo.tech/posts/2014-04-16-201847/</link><pubDate>Wed, 16 Apr 2014 20:18:47 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-16-201847/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/e50a8e9f-fd50-4126-ab2b-2e617be8ff30/e09fa728b6660a0edf7758342069990d/deep/0/heroku.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;第1回を生視聴した増井さんのこれの第2回、第3回に関するメモです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-04-04-191507"&gt;@masuidriveさんのスクーの授業が面白かったのでメモるよ - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;先週配信された第2回は生視聴できませんでした。これも増井さん絡みでちょっときもい感じなんですが、IKEA家具でオフィスを作るって記事にインスパイアされてはるばる横浜のIKEAに買い物に行ったせいでへとへとで寝ていました。&lt;/p&gt;
&lt;p&gt;そんで昨日が第3回目の放送でした。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://schoo.jp/class/598/room"&gt;スクーの授業 ”増井雄一郎の「wri.pe」を事例に学ぶ、自作サービスの作り方〜開発編”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://schoo.jp/class/599/room"&gt;スクーの授業 ”増井雄一郎の「wri.pe」を事例に学ぶ、自作サービスの広め方〜リリース編”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.masuidrive.jp/2011/08/01/workspace-in-the-living-room/"&gt;リビングにIKEAで作る2畳の快適仕事環境 | @masuidrive blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2014-04-10-194908"&gt;初心者が初めてIKEAに行ってきたけど難易度高かった - ぴよログ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.piyo.tech/posts/2014-04-12-190905"&gt;IKEA家具で作る格安コーナーデスク - ぴよログ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="第2回-開発編"&gt;第2回 開発編&lt;/h1&gt;
&lt;p&gt;第2回は主にコーディングの話で、サーバーサイドとクライアントサイド両方の話でした。&lt;/p&gt;
&lt;h2 id="サーバーサイド"&gt;サーバーサイド &lt;/h2&gt;
&lt;p&gt;&lt;code&gt;rake stats&lt;/code&gt;知らなかった！&lt;/p&gt;
&lt;h3 id="railsではapiのみを提供"&gt;RailsではAPIのみを提供&lt;/h3&gt;
&lt;p&gt;サーバーサイドではAPIのみを提供するというやり方にはちょうど興味を持っているところでした。これができると、クライアントとサーバーを完全にわけることができるし、ネイティブのモバイルアプリで同じAPIを使えばよくなるので色々便利そうだなと思っています。&lt;/p&gt;
&lt;h3 id="認証にはdeviseを使わない"&gt;認証にはDeviseを使わない&lt;/h3&gt;
&lt;p&gt;これは結構意外でしたね。大抵の連携は&lt;code&gt;Omniauth&lt;/code&gt;+&lt;code&gt;Devise&lt;/code&gt;でいけたりするので。。。&lt;/p&gt;
&lt;p&gt;とはいえ対応が必要になったときに素早いのは自前ですね。簡単だということなのでちゃんと見ておこう。。。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-12-20-212109"&gt;Railsでログインとは別に複数のサービスとの連携を行う方法 - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="クライアントサイド"&gt;クライアントサイド&lt;/h2&gt;
&lt;h3 id="backbonejs"&gt;Backbone.js&lt;/h3&gt;
&lt;p&gt;Backbone.jsの一部を使ってCoffeeScriptでViewを書いたそう。Backboneも前から気になっていた技術でストライクな内容です。前に作っていたRSSリーダーではCoffeeScriptでグローバルに書いていたのでかなりスパゲッティでした＼(^o^)／&lt;/p&gt;
&lt;p&gt;APIとViewがうまく切り分けられれば自然と綺麗になりそうなので、JSの構造化フレームワークは使ってみたいです。&lt;/p&gt;
&lt;h3 id="html5"&gt;HTML5&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Local Storage&lt;/li&gt;
&lt;li&gt;Session Storage&lt;/li&gt;
&lt;li&gt;Application Cache&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;このあたり知らなかった…！&lt;/p&gt;
&lt;h2 id="開発編まとめ"&gt;開発編まとめ&lt;/h2&gt;
&lt;p&gt;open-wripe読もう。&lt;/p&gt;
&lt;h1 id="第3回-リリース編"&gt;第3回 リリース編&lt;/h1&gt;
&lt;p&gt;デプロイ編といったほうがいいのかもしれません。主にPaaSの話、自動テストの話でした。&lt;/p&gt;
&lt;h2 id="heroku"&gt;Heroku&lt;/h2&gt;
&lt;p&gt;個人的にはHerokuにかかっている費用の内訳が興味深いです。スクーのスライドと増井さんのブログに載っています。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.masuidrive.jp/2014/04/01/answers-in-schoo/"&gt;4/1のスクー 「wri.peの作り方」で拾いきれなかった質問 | @masuidrive blog&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Heroku Dyno x 2 = $34.50&lt;/li&gt;
&lt;li&gt;Heroku Worker x 1 = $36.00&lt;/li&gt;
&lt;li&gt;Heroku Postgres Olive = $50.00&lt;/li&gt;
&lt;li&gt;Adept Scale Skiff = $18.00&lt;/li&gt;
&lt;li&gt;Heroku SSL = $20.00&lt;/li&gt;
&lt;li&gt;Websolr Cobalt = $20.00&lt;/li&gt;
&lt;li&gt;Total = $178.50&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Herokuは無料分しか使ったことがありませんでしたが、きちんとしたサービスを作るならそれなりにかかるなあという印象。Workerが結構高いですね。そもそも無料分じゃレスポンス的にも実用性は低いのですが。&lt;/p&gt;
&lt;p&gt;全文検索のsolrも使えるみたいだしオートスケールも魅力。Herokuの運用しても余裕なプロダクトをやってみたいもんです。&lt;/p&gt;
&lt;p&gt;Herokuのメリットの1つがMatzがいることらしいｗｗ&lt;/p&gt;
&lt;h2 id="new-relic"&gt;New Relic&lt;/h2&gt;
&lt;p&gt;これは僕も使ったことがあります。どの料金プランでどの機能が使えるのか忘れてしまいましたが、こんなことができるのでRailsアプリケーションならほぼ必須といってもいいのかもしれません。&lt;/p&gt;
&lt;p&gt;（※1年前はAWSでホストするサービスはちょっといいプランが無料になった気がします）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ページロードの内訳&lt;/li&gt;
&lt;li&gt;レスポンスタイムの内訳&lt;/li&gt;
&lt;li&gt;DBのレスポンス&lt;/li&gt;
&lt;li&gt;コントローラのレスポンスの内訳&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などなど。&lt;/p&gt;
&lt;p&gt;内訳っていうのがすごくて、メソッドごとの所要時間がわかったり、ブラウザのリクエストからレスポンスが戻ってきてDOM構築からレンダリングまでの内訳がわかったりします。遅いクエリを特定してくれたりもするのでパフォーマンスのボトルネックがすぐわかるようになっていますし、iPhoneアプリに通知を出してくれたりもします。&lt;/p&gt;
&lt;p&gt;そして結構儲かっているらしい。&lt;/p&gt;
&lt;h2 id="自動テスト"&gt;自動テスト&lt;/h2&gt;
&lt;p&gt;RSpec+Capybara+Selenium driverの自動テストをしているそう。&lt;/p&gt;
&lt;p&gt;個人で作ったもののほうがテストが重要というのはなんとなく同意。仕事の場合はテストを書くことよりもお金になることのほうが優先度が高くなるはずだし、個人のサービスの場合は不具合のリスクや修正のコストをかけないためにテストが重要になるのかなと思いました。&lt;/p&gt;
&lt;h2 id="質疑応答"&gt;質疑応答&lt;/h2&gt;
&lt;p&gt;せっかくなのでたくさん（3つ）質問したら時間内に全部答えてもらえました。&lt;/p&gt;
&lt;h3 id="qアクセス負荷の話が少しありましたがレスポンスタイムの計測などはしましたか"&gt;Q.アクセス負荷の話が少しありましたが、レスポンスタイムの計測などはしましたか？&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;A.New Relicでおk&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;今の10倍程度のアクセスならさばけるだろうという予測をしておられたのでその辺をどうやって見積もったのかを聞いてみたかったのですが、質問の仕方が難しかったです。&lt;/p&gt;
&lt;p&gt;僕がやってたときはJMeterを使ってがっつり負荷をかけたときのスループットなんかを見ていましたが、そういったベンチマーク的なことはどうだったんでしょう？色々なプラクティス、ケースに興味があります。&lt;/p&gt;
&lt;p&gt;あ、そうそう、Railsのデバッグ環境でプロファイルするならmini-profilerが結構いいです。NewRelicがやってくれるようなことを手元の環境で計測できます。&lt;/p&gt;
&lt;h3 id="qテストではosやブラウザ毎のテストも全て走るようにしているんでしょうか"&gt;Q.テストではOSやブラウザ毎のテストも全て走るようにしているんでしょうか？&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;A.基本Mac、たまにWindows。モダンIE便利。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;まあテストのたびにたくさんのOSや環境でテストするのはきついですよね〜。&lt;/p&gt;
&lt;h3 id="qpoltergeistなどサイレントなwebドライバーもありますがそのあたりのものは実用性はどうでしょうか"&gt;Q.poltergeistなどサイレントなWebドライバーもありますが、そのあたりのものは実用性はどうでしょうか？&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;A.ちょっとテストするときはサイレント、デプロイ前は必ずSeleniumでブラウザを起動して動かす&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PhantomJSと言ったほうが良かったのかも。&lt;/p&gt;
&lt;p&gt;で、これは確かになぁと思いました。ブラウザ毎のちょっとした挙動も検証するならSeleinumを使ったほうが良さそうです。そもそもテストがきちんと動くかどうかを確認するようなときもあるので、そういうちょっとした場合はPhantomJSとかを使うんでしょう。&lt;/p&gt;
&lt;p&gt;さっきの質問にも関連してるけど、デプロイ前にはがっちりテスト、普段はカジュアルにテストということなんですね。&lt;/p&gt;
&lt;h2 id="リリース編まとめ"&gt;リリース編まとめ&lt;/h2&gt;
&lt;p&gt;テストも含めてソース読もう。&lt;/p&gt;
&lt;h1 id="第2回第3回まとめ"&gt;第2回・第3回まとめ&lt;/h1&gt;
&lt;p&gt;ソース（ry&lt;/p&gt;</description></item><item><title>Objective-CでBuilderパターン</title><link>https://blog.piyo.tech/posts/2014-04-15-221845/</link><pubDate>Tue, 15 Apr 2014 22:18:45 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-15-221845/</guid><description>&lt;p&gt;Builderパターンてのは、生成が面倒なオブジェクトの生成をいい感じにするデザインパターンです。Objective-Cではブロックを使っていい感じにできるみたいですね。&lt;/p&gt;
&lt;p&gt;例えば特定日時のNSDateを生成するには次のようなコードを書くことになります。そこそこ煩雑です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;NSDateComponents &lt;span style="color:#f92672"&gt;*&lt;/span&gt;components &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSDateComponents new];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;components.year &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2014&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;components.month &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;components.day &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;components.hour &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;components.timeZone &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSTimeZone timeZoneWithAbbreviation:&lt;span style="color:#e6db74"&gt;@&amp;#34;UTC&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;NSCalendar &lt;span style="color:#f92672"&gt;*&lt;/span&gt;cal &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;NSDate &lt;span style="color:#f92672"&gt;*&lt;/span&gt;date1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [cal dateFromComponents:components];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;%@&amp;#34;&lt;/span&gt;, [date1 debugDescription]);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こちらにあるようなカテゴリを定義しておいてBuilderブロックを使った初期化をできるようにしておくと簡単にかけます。確かに見通しがよくなるかも。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/kluivers/jbw-builders"&gt;kluivers/jbw-builders&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;NSDate &lt;span style="color:#f92672"&gt;*&lt;/span&gt;date2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSDate gregorianDateWithBuilderBlock:&lt;span style="color:#f92672"&gt;^&lt;/span&gt;(NSDateComponents &lt;span style="color:#f92672"&gt;*&lt;/span&gt;builder) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; builder.year &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2014&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; builder.month &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; builder.day &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; builder.hour &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; builder.timeZone &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSTimeZone timeZoneWithAbbreviation:&lt;span style="color:#e6db74"&gt;@&amp;#34;UTC&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;}];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;%@&amp;#34;&lt;/span&gt;, [date2 debugDescription]);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rubyでもブロック内で初期化することありますよね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Hoge&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;hoge&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; hoge&lt;span style="color:#f92672"&gt;.&lt;/span&gt;value1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fuga&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; hoge&lt;span style="color:#f92672"&gt;.&lt;/span&gt;value2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;みたいな。あー、具体例思いつかん。&lt;/p&gt;</description></item><item><title>Xcodeでコードのあいまい補完（キャメルケース補完）</title><link>https://blog.piyo.tech/posts/2014-04-14-191517/</link><pubDate>Mon, 14 Apr 2014 19:15:17 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-14-191517/</guid><description>&lt;p&gt;iOSのSDKはAPIの名前が長いのでXcodeによるコード補完がほぼ必須ですが、微妙にタイポったときに補完が効かなかったりして使い勝手がそんなによくありませんでした。&lt;/p&gt;
&lt;p&gt;ところで、Xcodeにはいっている&lt;code&gt;Open Quickly&lt;/code&gt;の機能（&lt;code&gt;Command&lt;/code&gt;+&lt;code&gt;Shift&lt;/code&gt;+&lt;code&gt;o&lt;/code&gt;）はキャメルケースによる絞り込みに対応しています。キャメルケースによる補完というのは、単語の区切りごとに大文字になっているキャメルケースの文字列の絞り込みを、単語の頭の文字を打つだけで行えるというもので、SublimeTextのコマンドパレットなんかも対応しています。&lt;/p&gt;
&lt;p&gt;例えば&lt;code&gt;HogeFugaFooBar&lt;/code&gt;という単語にヒットさせたいときは&lt;code&gt;hffb&lt;/code&gt;と打てばいいという感じです。&lt;/p&gt;
&lt;p&gt;Xcodeのコード補完でこれを行うためのプラグインがありました。ちょっと便利系プラグインに比べるとこいつは断然入れる価値あるよ！&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/chendo/FuzzyAutocompletePlugin"&gt;chendo/FuzzyAutocompletePlugin&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;公式のスクリーンショットを見てもらえるとよくわかると思いますが、&lt;code&gt;disonce&lt;/code&gt;で&lt;code&gt;dispatch_once&lt;/code&gt;を補完したり、&lt;code&gt;NSAccessibilityWindowRole&lt;/code&gt;のような長いクラス名を&lt;code&gt;nsaccwindowr&lt;/code&gt;で入力したりということができているのがわかると思います。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/H-JkULtXLfLttBMef8vhFGvKGMUcU3518yqZTGSmWAIkxvr94GfGl5JNkYeZTRUM5Kt1XlwHu9l_E8fhtslHeUiq6ZaTon1WrZuzWn7FadVyf9OtRH09VQPcNSrtZkPuiffvWnMf_P0qvUJa9TXoQRNT6iWWlkrvK71YyLnL47zfwvMv4LK2kHin3wp7I295TYuqnZx3UACzcsjGzlDbvs-E0PVRHE2f1M8VoARpSpddhg1NAJWKIS_Qbw7-f1R4m1EjrQ5gIlnd2d2K4NXM-t_VJ2kgyx4wMPP-dLrsFbT12XLiY9LC8ChE8m4lZzHpVYdh0LvzgK-tTtVnQIozjmbpzxy3DUOtkajWaq91ei8xkgW_HZapyEvxp9iqh7rwhQd6hDsmD71p2XtVa5YFHA7DWPkLkwUb19QYc8clbPCzIbE1XyqfYW7IWZOP4D8ich9XQXwEpI4tN3vJUrwYplcCFv200Mmka9Rz-1EypPXe8ml9ywsccAVWBVkRNfsTUC7-YdmuHBxSLHuvWRDk6KprHlMOqeoDVez_SW71TNrguPqawHKmGFItq2pYNzPPyppm4R54C49mKe1e61PfVvP87NlPR-XsbqymgKFoE3OC7Y7FrA0iQfHhyzAXvV8qglO-3FGRySfxC9KfIwiKKFpo6vEuTsQD9Q=w490-h397-no" alt=""&gt;&lt;/p&gt;
&lt;p&gt;インストールはパッケージ管理ツールの&lt;strong&gt;Alcatraz&lt;/strong&gt;で！&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-04-13-212338"&gt;Xcode用プラグインマネージャー「Alcatraz」 - ぴよログ&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Xcode用プラグインマネージャー「Alcatraz」</title><link>https://blog.piyo.tech/posts/2014-04-13-212338/</link><pubDate>Sun, 13 Apr 2014 21:23:38 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-13-212338/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9416538b-6d6e-44df-9eb4-3a199c88e625/0ba22fd206fedcfbffbf07de8eebadb5/deep/0/687474703a2f2f616c63617472617a2e696f2f696d616765732f6865616465724032782e706e67.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;「Alcatraz」というXcode用のプラグインマネージャーを発見しました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/supermarin/Alcatraz"&gt;supermarin/Alcatraz&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;READMEにあるように以下のコマンドでインストール可能です。インストール後はXcodeを再起動。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;curl -fsSL https://raw.github.com/supermarin/Alcatraz/master/Scripts/install.sh | sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;インストールが終わるとWindowメニューに「Package Manager」があらわれます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7aeb7056-5b30-4f79-8d44-20a3bf6d032f/8f01c4dbc5db9f33534b038e1c65d56e/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-12-21-49.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;そいつを起動するとこんな感じ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c4f8b004-a5a1-4008-9b88-53df2aa9b3a1/77b481028c3d66f4acb781a84b769ebd/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-12-21-46.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;なにやらずらずらーっと表示されました。上部にあるボタンで表示対象をフィルター可能です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All&lt;/li&gt;
&lt;li&gt;Xcodeのプラグイン&lt;/li&gt;
&lt;li&gt;カラースキーム&lt;/li&gt;
&lt;li&gt;ファイルテンプレート&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;インストールは項目の左側のアイコンで。また、マウスオーバーすると項目の右側に矢印ボタンとクイックルックボタンが表示されます。矢印ボタンでGitHubなどのページへ。プレビューするにはクイックルックボタン。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/5fca5b9a-0c12-4b4c-9dad-4c0887a5afec/8f94938d56ec33d72dd0af6136796b83/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-12-21-47.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;カラースキームに対してクイックルックを押すとこんな感じでプレビューされます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b3c08fc4-2db7-49ed-92f7-525530f6786f/8a5fafe39699650f331c32ecb5a3dfcc/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-12-21-47.png" alt=""&gt;&lt;/p&gt;
&lt;h1 id="感想"&gt;感想&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Xcodeプラグインにはプレビューがないものが多いし、プレビューできてもどんなものかよくわからいものが多い。名前を知っているプラグインを検索してインストールするのに良さそう。&lt;/li&gt;
&lt;li&gt;カラースキームはプレビューしながら選べてすごく便利。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>bundle installするパスを一箇所にまとめる</title><link>https://blog.piyo.tech/posts/2014-04-11-191504/</link><pubDate>Fri, 11 Apr 2014 19:14:45 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-11-191504/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c8beeb36-3895-4492-b910-e9a4417654b7/3b5bbe1ab3190583c6d16adc5be9c635/deep/0/rails1.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;リスク回避のためにソースコードはDropboxの管理下に置いています（一人プロジェクトだと&lt;code&gt;% git push&lt;/code&gt;を忘れる可能性も少なくありません）。&lt;/p&gt;
&lt;p&gt;プロジェクトに関わるソースファイルだけであれば大した容量にはならないのですが、依存するライブラリのソースコードなどが入ってくる同期するデータサイズが増えます。&lt;/p&gt;
&lt;p&gt;こうなるとDropboxの容量を食うのはもちろんなのですが、同期プロセスがガンガンに走ってしまいCPUがきつくなってしまい、MacbookAirのファンが大騒ぎになります。&lt;/p&gt;
&lt;p&gt;主に問題になるのがRubyのbundlerでインストールしたgem。&lt;/p&gt;
&lt;p&gt;パスを指定せずに&lt;code&gt;% bundle install&lt;/code&gt;するとRuby全体が参照できるところにgemをインストールします。これをやるといろいろなバージョンが混在したりしてわけがわからなくなるので&lt;code&gt;--path&lt;/code&gt;オプションをつけてプロジェクトディレクトリ以下に置きましょうというのが一般的な話なんですが、さっきも言ったようにこれだとDropboxの同期が忙しくなります。&lt;/p&gt;
&lt;p&gt;そこでなんとかしてプロジェクトディレクトリではないけどRuby全体に影響を与えないところに入れられないかなーと考えたのが適当に作ったこのスクリプト。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/usr/bin/env ruby&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;bundle_dir &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/Users/xoyip/.bundle_install_dir/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Dir&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;getwd&lt;span style="color:#f92672"&gt;.&lt;/span&gt;gsub(&lt;span style="color:#e6db74"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;_&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;system &lt;span style="color:#e6db74"&gt;&amp;#34;bundle install --path &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;bundle_dir&lt;span style="color:#e6db74"&gt;}#{&lt;/span&gt;name&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; --binstubs=.bin&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ホームディレクトリにbundler用の場所を作り現在のディレクトリのフルパスを名前に変換したディレクトリ内に各gemをインストールするというもの。ベストなソリューションではないですが僕個人は一応満足しています。&lt;/p&gt;
&lt;p&gt;ついでに&lt;code&gt;--binstubs&lt;/code&gt;を指定して、↓の問題にも同時に対処できるようにしてあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-12-14-203805"&gt;railsのサブコマンドが使えなくなる問題の原因はbinstubs - ぴよログ&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Rails4.1のsecrets.ymlはfigaroと違うの？</title><link>https://blog.piyo.tech/posts/2014-04-09-214405/</link><pubDate>Wed, 09 Apr 2014 21:43:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-09-214405/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c8beeb36-3895-4492-b910-e9a4417654b7/3b5bbe1ab3190583c6d16adc5be9c635/deep/0/rails1.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Rails4.1が正式にリリースされたらしいので少し見てみたけど、secrets.ymlとかいうのがサポートされるようになったんですね。&lt;/p&gt;
&lt;p&gt;公開したくないAPIキーなどの情報を&lt;code&gt;config/secrets.yml&lt;/code&gt;に書いておくとRails内でアクセスできるのだとか。&lt;/p&gt;
&lt;p&gt;こうやって書いておくと&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# config/secrets.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;development&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;secret_key_base&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;cfcc784a39....&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hoge_api_key&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;hogehogehoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こう呼べる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;.&lt;/span&gt;secrets&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hoge_api_key
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;で、このsecrets.ymlをソース管理から外しておけばその他は公開できるよね、みたいな。他のサービスと連携するオープンソースなRailsアプリにするときなんかに使えばいいんだと思います。&lt;/p&gt;
&lt;h1 id="figaroと一緒では"&gt;Figaroと一緒では&lt;/h1&gt;
&lt;p&gt;同じことをするためのFigaroってgemあったじゃん。そう思って調べたら機能的にはほぼ一緒？みたいですね。&lt;/p&gt;
&lt;p&gt;Figaroの作者がsecrets.ymlに触れてたので読んでみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://collectiveidea.com/blog/archives/2013/12/18/the-marriage-of-figaro-and-rails/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://collectiveidea.com/blog/archives/2013/12/18/the-marriage-of-figaro-and-rails/" alt="The Marriage of Figaro… and Rails // Collective Idea | Crafting web and mobile software based in Holland, Michigan" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://collectiveidea.com/blog/archives/2013/12/18/the-marriage-of-figaro-and-rails/"&gt;The Marriage of Figaro… and Rails // Collective Idea | Crafting web and mobile software based in Holland, Michigan&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;で、この人が考えるsecrets.ymlのメリットとデメリットがこれです。&lt;/p&gt;
&lt;h2 id="メリット"&gt;メリット&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Railsが認めた規約になるので単なるgemより良い。HerokuとかTravisがサポートしてくれるようになるし&lt;/li&gt;
&lt;li&gt;ENVハッシュじゃなくてオブジェクトになるから便利&lt;/li&gt;
&lt;li&gt;secret_key_baseがデフォルトで隠せるからよりセキュアになる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="デメリット"&gt;デメリット&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://12factor.net/"&gt;The Twelve-Factor App&lt;/a&gt;ではENV使う方がいいよと言ってる&lt;/li&gt;
&lt;li&gt;ENVを使わないことで全てのアプリケーションサーバーに必ずsecrets.ymlが必要になる&lt;/li&gt;
&lt;li&gt;デフォルトで&lt;code&gt;.gitignore&lt;/code&gt;に&lt;code&gt;secrets.yml&lt;/code&gt;がないのでうっかりソース管理に追加してしまう可能性がある（正式なリリース時にはなおると思う）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最後の1つですが、正式リリースの4.1を試したところ&lt;code&gt;.gitignore&lt;/code&gt;に&lt;code&gt;secrets.yml&lt;/code&gt;はいませんでした。気をつけないといけないっぽい。&lt;/p&gt;
&lt;h1 id="ちゃんとissueでの議論を読んでみる"&gt;ちゃんとissueでの議論を読んでみる&lt;/h1&gt;
&lt;p&gt;ここまで書いておいてなんですが、secrets.ymlのproductionのところにこんな風にかいてありました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Do not keep production secrets in the repository,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# instead read values from the environment.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;production&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;secret_key_base&lt;/span&gt;: &lt;span style="color:#f92672"&gt;&amp;lt;%=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;SECRET_KEY_BASE&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;%&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;「プロダクション環境の値はリポジトリにいれないで環境から読もうね」って書いてありますね。&lt;/p&gt;
&lt;p&gt;となるとこれまでの話には疑問が。本当に秘密にする値はENVから読んでsecrets.ymlはソース管理に入れるってことなんでしょうか？その辺の思想がよくわからないのでGitHubで関連のissueを読んでみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/rails/rails/pull/13388"&gt;Update the gitignore generator template to ignore secrets.yml by alexmcpherson · Pull Request #13388 · rails/rails · GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;が、よくわからんｗ ざっくり言うと、Railsとしてはそこはユーザーに選ばせればよくてこれまでのdatabase.ymlと同じように扱えばいいんだよ、みたいなことが書いてあったような気がします。仕組みは提供したからあとは好きにやってねってことなんでしょうか。&lt;/p&gt;
&lt;p&gt;できることはFigaroと同じだけど思想の違いからちょっとした差がでているようですね。と、逃げとく。&lt;/p&gt;</description></item><item><title>CocoaPodsの比較にGitHubのスター数を用いる</title><link>https://blog.piyo.tech/posts/2014-04-08-215547/</link><pubDate>Tue, 08 Apr 2014 21:55:47 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-08-215547/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7ee70e03-ec1c-41f2-885e-6607fb53af92/b83c508d8303d9d4b598713c49449bc9/deep/0/Octocat.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;iOS開発で使えそうなコントールを探すのにKFCocoaPodsPluginが便利でした。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-04-07-193002"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-04-07-193002" alt="CocoaPods用Xcodeプラグインがかなり便利 - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-04-07-193002"&gt;CocoaPods用Xcodeプラグインがかなり便利 - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;ところでこの検索ダイアログを使うと該当するPodがたくさん見つかって一体何を使っていいのかわからなくなるという事態が起こりました。UI系が特にそうなんですが、僕の場合ではGridっぽいビューを作りたくて
検索ダイアログにGridって入れたら20個ぐらいでてきました。&lt;/p&gt;
&lt;p&gt;この全てのプロジェクトページやサンプル、スクリーンショットを見るというのは現実的ではない感じがしたので、タイトルの通りプロジェクトについてるスターの数を判断基準にすることにしました。&lt;/p&gt;
&lt;p&gt;20個のうちの上位3個〜5個ぐらいを評価対象にするだけでもだいぶ楽なはずなので。&lt;/p&gt;
&lt;h1 id="スクリプト"&gt;スクリプト&lt;/h1&gt;
&lt;p&gt;Rubyでスクリプトを書きました。リポジトリについてはハードコーディングです。ここはKFCocoaPodsPluginの検索ダイアログからがんばってコピペしたもので、そこはすごくイケてないです。この部分は今度頑張って改造してみようと思っているところ。&lt;/p&gt;
&lt;p&gt;GitHubの問い合わせにはこのgemを使いました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/peter-murach/github"&gt;peter-murach/github&lt;/a&gt;&lt;/p&gt;
&lt;script src="https://gist.github.com/pi-chan/10015258.js"&gt;&lt;/script&gt;
&lt;p&gt;そして結果がこんな感じでした。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;2252: AlanQuatermain/AQGridView
2040: gmoledina/GMGridView
1728: mwaterfall/MWPhotoBrowser
1444: sobri909/MGBoxKit
826: kolinkrewinkel/KKGridView
740: rnystrom/RNGridMenu
475: norsez/BDDynamicGridViewController
365: joecarney/JCGridMenu
174: NOUSguide/NGVaryingGridView
139: ixnixnixn/IAInfiniteGridView
107: allaboutapps/A3GridTableView
91: phranck/CNGridView
49: brewster/SMGridView
19: kristopherjohnson/KJGridLayout
18: rhodgkins/RDHCollectionViewGridLayout
14: troyharris/THGridMenu
11: hirohisa/BrickView
4: youknowone/GridTableView
3: JackTeam/InstagramThumbnail
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;やっぱスクリプト書いてみてよかった！便利だわ〜&lt;/p&gt;</description></item><item><title>CocoaPods用Xcodeプラグインがかなり便利</title><link>https://blog.piyo.tech/posts/2014-04-07-193002/</link><pubDate>Mon, 07 Apr 2014 19:29:50 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-07-193002/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/54f4a189-121f-4108-a4eb-d73b4ae5a484/ad6af08ae4a6ec95e4e8d0352e1eaab4/deep/0/imgres.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;いきなり余談ですが、あとで試そうと思った拡張機能って大体試さないですよね。Xcodeプラグインのまとめページ見てはてブしようとしたら3ヶ月以上前にはてブしてたりして。。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qiita.com/cutmail/items/d8614d72c8f4a9e8348d"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://qiita.com/cutmail/items/d8614d72c8f4a9e8348d" alt="iOSアプリ開発が捗るXcodeプラグイン - Qiita" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://qiita.com/cutmail/items/d8614d72c8f4a9e8348d"&gt;iOSアプリ開発が捗るXcodeプラグイン - Qiita&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://qiita.com/cutmail/items/d8614d72c8f4a9e8348d" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://qiita.com/cutmail/items/d8614d72c8f4a9e8348d" alt="はてなブックマーク - iOSアプリ開発が捗るXcodeプラグイン - Qiita" title="はてなブックマーク - iOSアプリ開発が捗るXcodeプラグイン - Qiita" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;こりゃもったいないということで1つ試してみました。ターゲットにしたのはCocoaPods用のプラグインっす。&lt;/p&gt;
&lt;h1 id="kfcocoapodsplugin"&gt;KFCocoaPodsPlugin&lt;/h1&gt;
&lt;p&gt;XcodeのCocoaPods周りのメニューを追加するプラグインだそう。Podfileの編集なんてコマンドラインと適当なエディターで十分なのでいらないかなと思ったんですが、補完してくれるのが便利かも？と思っていれてみました。&lt;/p&gt;
&lt;h2 id="インストール"&gt;インストール&lt;/h2&gt;
&lt;p&gt;まずこちらからソースコードをゲットします。Download ZIPで良いかと。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ricobeck/KFCocoaPodsPlugin"&gt;ricobeck/KFCocoaPodsPlugin&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;次にZIPを展開しプロジェクトルートで&lt;code&gt;$ pod install&lt;/code&gt;します。個々はコマンドラインが必要ですね。&lt;/p&gt;
&lt;p&gt;その後、&lt;code&gt;KFCocoaPodsPlugin.xcworkspace&lt;/code&gt;ファイルを開いてビルドし、Xcodeを再起動。これだけです。&lt;/p&gt;
&lt;p&gt;再起動後のXcodeには&lt;code&gt;Product&lt;/code&gt;メニューの中に&lt;code&gt;CocoaPods&lt;/code&gt;のサブメニューが登場します。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/36692ef1-267f-482f-ba3c-0b34c3c6cf1c/2e94e1503b6fc89ccf67c4dc405b3b69/deep/0/CocoaPods-Submenu-%E3%81%A8-Product.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="edit-podfile"&gt;Edit Podfile&lt;/h2&gt;
&lt;p&gt;メニューに有る&lt;code&gt;Edit Podfile&lt;/code&gt;をするとXcodeのエディターでPodfileが開きます。そして編集時に補完をかけてくれるようになります。&lt;/p&gt;
&lt;p&gt;公式のアニメーションGIFでその様子がわかります↓&lt;/p&gt;
&lt;p&gt;&lt;img src="https://github.com/ricobeck/KFCocoaPodsPlugin/raw/master/Screenshots/Animation-Completion.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;うろ覚えでもいけるのでちょっとだけ便利。&lt;/p&gt;
&lt;h2 id="search-pod"&gt;Search Pod&amp;hellip;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Search Pod...&lt;/code&gt;からPodの検索ができます。&lt;/p&gt;
&lt;p&gt;検索バーにキーワードになりそうな言葉を入れて検索するとヒットしたPodが一覧で表示されます。こんな感じに。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/5b72791b-e40c-4864-aa93-428d3417f797/48bae96e9dd773dc7bf2f7fd393c620f/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-04-06-10-52.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;これのいいところは使いたい機能に合うPodが探しやすくなることと、ライセンスがパッと見でわかるこでしょうか。特にPodを探すのは結構苦労します。Google検索では探しきれないことも多いし、CocoaControlsは少し重いので手間がかかります。&lt;/p&gt;
&lt;p&gt;この検索ダイアログは具体的なPodが決まっていないときに便利そうです。&lt;/p&gt;
&lt;h2 id="その他"&gt;その他&lt;/h2&gt;
&lt;p&gt;インストール/アップデートやPodfileの初期設定などもできます。一度このプラグインを入れてしまえばコンソールから&lt;code&gt;$ pod install&lt;/code&gt;する必要がなくなるかもしれないので、コンソールが好きでない人にはいいかも。&lt;/p&gt;
&lt;h1 id="まとめ"&gt;まとめ&lt;/h1&gt;
&lt;p&gt;Search Podがめちゃくちゃ良い！試してみるもんですね。&lt;/p&gt;</description></item><item><title>Pryからソースコードをエディタで開く</title><link>https://blog.piyo.tech/posts/2014-04-06-201206/</link><pubDate>Sun, 06 Apr 2014 20:11:56 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-06-201206/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/3103251e-4496-4497-8c5f-648e919c26d9/0ea843ee5272db6594bdff695126ee61/deep/0/ruby.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;RubyのREPLは&lt;code&gt;pry&lt;/code&gt;を使っています。&lt;/p&gt;
&lt;p&gt;pryを使うことで&lt;code&gt;show-source&lt;/code&gt;というコマンドを使えるようになります。このコマンドを使うとRuby本体のコードではないコードに限りすぐに参照できるというものです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;$ pry
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&amp;gt; show-source Pry
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;From: /Users/hiromasa/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/pry-0.9.12.6/lib/pry/pry_instance.rb @ line 24:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;Class name: Pry
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;Number of monkeypatches: 8. Use the &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;-a&lt;span style="color:#e6db74"&gt;`&lt;/span&gt; option to display all available monkeypatches
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;Number of lines: &lt;span style="color:#ae81ff"&gt;742&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;class Pry
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; attr_accessor :input
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; attr_accessor :output
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; attr_accessor :commands
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とまあこんな具合。&lt;/p&gt;
&lt;p&gt;これでもかなり便利なんですが、関連してその周辺のファイルのコードを読むことも多いので実行環境でページャで読めるだけでは足りない場合もあります。&lt;/p&gt;
&lt;p&gt;そこで！&lt;/p&gt;
&lt;p&gt;show-sourceを参考にちょっと作ってやるか！と思っていろいろ中身を見ていたら、どうやらそんなことは普通にできるみたいですね(´・ω・｀)&lt;/p&gt;
&lt;h1 id="エディタを設定する"&gt;エディタを設定する&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;~/.pryrc&lt;/code&gt;でエディターを設定しておきます。デフォルトではvimなのでそのまま環境内で開きます。僕はSublime Text3を使うため、&lt;code&gt;subl&lt;/code&gt;を指定しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ~/.pryrc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;Pry.config.editor &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;subl&amp;#34;&lt;/span&gt;☄
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="editコマンドを使う"&gt;editコマンドを使う&lt;/h1&gt;
&lt;p&gt;Pryのエディタでソースコードを開くには&lt;code&gt;edit&lt;/code&gt;コマンドを使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ pry
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&amp;gt; edit Pry
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;おっと、Pryが待ち状態になってしまいました。これはSublimeから処理が返ってくるのを待っているという意味です。これにより、気になるファイルをコマンドで開いて編集を完了し、Pryに処理が戻った時点で該当ファイルを自動でリロードする（デフォルトの挙動）ような流れでコードを書くことができるようです。かっこいい。&lt;/p&gt;
&lt;p&gt;けど、じっくり周辺のコードを読みたい場合は処理待ちになってほしくありません。そういうときは&lt;code&gt;--no-reload&lt;/code&gt;オプション（または&lt;code&gt;-n&lt;/code&gt;）をつけることでエディタで開いたらお終いな挙動をさせることができます。&lt;/p&gt;
&lt;p&gt;RailsなんかではPryで色々やりながら動きを確認したりするので、&lt;code&gt;show-source&lt;/code&gt;や&lt;code&gt;edit -n&lt;/code&gt;でさらに捗りますね。もっと早く知りたかったわ。。。。&lt;/p&gt;</description></item><item><title>組み込みのrmが怖すぎるので代替ツールを使う</title><link>https://blog.piyo.tech/posts/2014-04-05-194907/</link><pubDate>Sat, 05 Apr 2014 19:48:57 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-05-194907/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9ed57bc1-993a-406d-b127-979f4d06ec78/debf2ee6fc7002b0f9fb8b66b62a620e/deep/0/2013_mac_pro.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rm -rf&lt;/code&gt;の引数間違えて大惨事、とはいかなくてもそれに近い経験がある人は多いはず。僕もたまーにやります。致命的なことはやったことないけど、さっきダウンロードしてきたばかりのファイルを消してめんどくせーとなったり、Gitで管理中のファイルを消したり。その程度で良かったですが。&lt;/p&gt;
&lt;p&gt;いろいろ代替のツールがあるんですが、それらを試した上で自作スクリプトを書いて使っている方がいました。それを紹介します。&lt;/p&gt;
&lt;p&gt;と思ったらこの方、以前書いた&lt;code&gt;sd_cl&lt;/code&gt;と同じ人だ！お世話になります。それについてはこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-01-28-232914"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-01-28-232914" alt="tmuxやscreenでも使えるpopd、pushdの強化版 - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-01-28-232914"&gt;tmuxやscreenでも使えるpopd、pushdの強化版 - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h1 id="削除コマンド"&gt;削除コマンド&lt;/h1&gt;
&lt;p&gt;閑話休題、削除コマンドに戻ります。詳しいことはこちらにありますが、&lt;code&gt;trash&lt;/code&gt;というスクリプトを導入してそちらを使おうよという話です。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://rcmdnk.github.io/blog/2014/01/12/computer-bash/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://rcmdnk.github.io/blog/2014/01/12/computer-bash/" alt="コマンドラインで使うゴミ箱コマンド - rcmdnk's blog" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://rcmdnk.github.io/blog/2014/01/12/computer-bash/"&gt;コマンドラインで使うゴミ箱コマンド - rcmdnk&amp;rsquo;s blog&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://rcmdnk.github.io/blog/2014/01/12/computer-bash/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://rcmdnk.github.io/blog/2014/01/12/computer-bash/" alt="はてなブックマーク - コマンドラインで使うゴミ箱コマンド - rcmdnk's blog" title="はてなブックマーク - コマンドラインで使うゴミ箱コマンド - rcmdnk's blog" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;結果としてどうなるかというと、&lt;code&gt;trash&lt;/code&gt;で削除したファイルはMacの場合はゴミ箱フォルダの中に更にフォルダを掘ってその日の名前のフォルダに移動してくれる仕組みになっています。&lt;/p&gt;
&lt;p&gt;WindowsやLinuxでもそのまま動くそうですが、ゴミ箱ディレクトリは適当な場所になるのだとか。&lt;/p&gt;
&lt;p&gt;使い方は&lt;code&gt;rm&lt;/code&gt;コマンドに近いので僕はそのまま&lt;code&gt;rm&lt;/code&gt;のエイリアスとして使っています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# .bashrc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;alias rm&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;trash -i&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# -i は削除時に確認するオプション&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="インストール"&gt;インストール&lt;/h2&gt;
&lt;p&gt;この方のHomebrewのリポジトリからインストール可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ brew tap rcmdnk/rcmdnkpac &lt;span style="color:#75715e"&gt;# リポジトリを追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ brew install rcmdnk-trash &lt;span style="color:#75715e"&gt;# trashコマンド&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ brew install sentaku &lt;span style="color:#75715e"&gt;# 依存モジュール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>masuidriveさんのスクーの授業が面白かったのでメモるよ</title><link>https://blog.piyo.tech/posts/2014-04-04-191507/</link><pubDate>Fri, 04 Apr 2014 19:14:57 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-04-191507/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/bab093e1-60d2-4644-abf2-f6789b2b02eb/bf675cc766b2d49e9b6138d751842eac/deep/0/schoo-hikarie-thumb-960x540-751.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;2014/04/01にスクーにて増井さんの配信がありました。期待を上回る面白さだったのでちょっとメモっておきます。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;スクーのページと資料&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://schoo.jp/class/597"&gt;増井雄一郎の「wri.pe」を事例に学ぶ、自作サービスの作り方〜サービスデザイン編 増井 雄一郎 先生 - 無料動画学習｜schoo（スクー）&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;質問に対する回答（増井さんのブログ）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.masuidrive.jp/2014/04/01/answers-in-schoo/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://blog.masuidrive.jp/2014/04/01/answers-in-schoo/" alt="4/1のスクー 「wri.peの作り方」で拾いきれなかった質問 | @masuidrive blog" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://blog.masuidrive.jp/2014/04/01/answers-in-schoo/"&gt;4/1のスクー 「wri.peの作り方」で拾いきれなかった質問 | @masuidrive blog&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://blog.masuidrive.jp/2014/04/01/answers-in-schoo/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://blog.masuidrive.jp/2014/04/01/answers-in-schoo/" alt="はてなブックマーク - 4/1のスクー 「wri.peの作り方」で拾いきれなかった質問 | @masuidrive blog" title="はてなブックマーク - 4/1のスクー 「wri.peの作り方」で拾いきれなかった質問 | @masuidrive blog" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;ちなみにスクーってのはオンラインの授業を見られるサービスで、リアルタイム視聴は無料、録画視聴は月1回までは無料です。なかなか良いですよ。&lt;/p&gt;
&lt;p&gt;増井さんが個人で作ったメモサービスwri.peを事例に話をしてくれるってことでその第1回を見てみました。&lt;/p&gt;
&lt;p&gt;全4回の内訳はこんな感じだったかと。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;企画・デザイン（第1回）←今回&lt;/li&gt;
&lt;li&gt;開発（第2、第3回？）&lt;/li&gt;
&lt;li&gt;プロモーション（第4回）&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="なるほどポイント"&gt;なるほどポイント&lt;/h1&gt;
&lt;p&gt;資料に載っていないことを含め、なるほどなと思ったことをメモっておきます。&lt;/p&gt;
&lt;h2 id="きちんと仕上げるにはプロトタイプの10倍ぐらいの時間がかかる"&gt;きちんと仕上げるには、プロトタイプの10倍ぐらいの時間がかかる&lt;/h2&gt;
&lt;p&gt;これはご本人の経験・感覚らしいんですが、製品版として完成させるのにはプロトタイプの10倍程度の時間がかかると見ておけば良いってことでした。wri.peをGWの1週間で作るにあたりプロトが半日ぐらいで作れるものでないといけないってことで、もう1つの候補だったチャット系のサービスは諦めたらしいです。&lt;/p&gt;
&lt;h2 id="dribbbleで気に入ったデザインを探"&gt;dribbbleで気に入ったデザインを探&lt;/h2&gt;
&lt;p&gt;dribbbleというのは名前しか知りませんでした。デザイナーがデザインを公開するような場所らしいです。普段からここを眺めてお気に入りのデザインをブックマークしておき、あとでそれらの共通点を抽出することで自分の好みのデザインを見つける、というようなことをしていたようです。このやり方は良さそう。&lt;/p&gt;
&lt;h2 id="作りたいものリスト"&gt;作りたいものリスト&lt;/h2&gt;
&lt;p&gt;作りたいものリストは良い試みかも。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自分の興味の整理&lt;/li&gt;
&lt;li&gt;もうあるよ、っていうフィードバック&lt;/li&gt;
&lt;li&gt;同じことに興味を持っている人と協業できる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;まあ僕がやったところであまり見てもらえないとは思いますが、今度やってみようかな。&lt;/p&gt;
&lt;h1 id="おわりに"&gt;おわりに&lt;/h1&gt;
&lt;p&gt;スクーとは関係ないけどIKEAオフィスやりたいなー。うちの問題はスペースがないことですね&lt;/p&gt;</description></item><item><title>Railsで"invalid byte sequence in UTF-8"</title><link>https://blog.piyo.tech/posts/2014-04-03-191210/</link><pubDate>Thu, 03 Apr 2014 19:12:10 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-03-191210/</guid><description>&lt;p&gt;これ面白かったので紹介。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://dev.mensfeld.pl/2014/03/rack-argument-error-invalid-byte-sequence-in-utf-8/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://dev.mensfeld.pl/2014/03/rack-argument-error-invalid-byte-sequence-in-utf-8/" alt="Rack/Ruby on Rails: ArgumentError: invalid byte sequence in UTF-8 | Running with Rails - Dev Blog not only for Rails fanatics!" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://dev.mensfeld.pl/2014/03/rack-argument-error-invalid-byte-sequence-in-utf-8/"&gt;Rack/Ruby on Rails: ArgumentError: invalid byte sequence in UTF-8 | Running with Rails - Dev Blog not only for Rails fanatics!&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;RailsアプリケーションのURLにこのパラメータ=&amp;gt;&lt;code&gt;?%28t%B3odei%29&lt;/code&gt;をつけるとエラーになることがあるよということらしいです。セキュリティのような大きな問題にはつながらないはず。変なリクエストをされると場合によっては500が返るよってことでしょうか。&lt;/p&gt;
&lt;p&gt;元記事を読むと基本的にはRails4のバグっぽい？ですね。Rails3で作ったサービスでは起こりませんでした。くれぐれもRailsで動いていると思われるサービスで試さないように。&lt;/p&gt;
&lt;p&gt;このバグを踏んでいる場合は、Rackミドルウェアを書いてパラメータをちょっといじれば回避できるようになります。多分置き場所は&lt;code&gt;app/middleware/sanitizer.rb&lt;/code&gt;とかで大丈夫です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Utf8Sanitizer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SANITIZE_ENV_KEYS&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;%w(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; HTTP_REFERER
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; PATH_INFO
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; REQUEST_URI
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; REQUEST_PATH
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; QUERY_STRING
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; )&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;initialize&lt;/span&gt;(app)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; @app &lt;span style="color:#f92672"&gt;=&lt;/span&gt; app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;call&lt;/span&gt;(env)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SANITIZE_ENV_KEYS&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;key&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; string &lt;span style="color:#f92672"&gt;=&lt;/span&gt; env&lt;span style="color:#f92672"&gt;[&lt;/span&gt;key&lt;span style="color:#f92672"&gt;].&lt;/span&gt;to_s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; valid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;URI&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;decode(string)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;force_encoding(&lt;span style="color:#e6db74"&gt;&amp;#39;UTF-8&amp;#39;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;valid_encoding?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Don&amp;#39;t accept requests with invalid byte sequence&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;400&lt;/span&gt;, { }, &lt;span style="color:#f92672"&gt;[&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Bad request&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; valid
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; @app&lt;span style="color:#f92672"&gt;.&lt;/span&gt;call(env)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;で、上のミドルウェアを使うようにすれば一応リクエストが悪いよーということで返すことができるようになるわけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# in config/application.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;module&lt;/span&gt; AppName
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Application&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Application&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;middleware&lt;span style="color:#f92672"&gt;.&lt;/span&gt;use &lt;span style="color:#e6db74"&gt;&amp;#34;Utf8Sanitizer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Rubyの知られざるコマンドラインオプション</title><link>https://blog.piyo.tech/posts/2014-04-02-200902/</link><pubDate>Wed, 02 Apr 2014 20:08:58 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-04-02-200902/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/3103251e-4496-4497-8c5f-648e919c26d9/0ea843ee5272db6594bdff695126ee61/deep/0/ruby.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;知られざるとか言ってるけど自分が知らなかっただけです。&lt;/p&gt;
&lt;p&gt;グローバル変数やらコマンドラインオプションやらを駆使して、10数行あるコードを最終的には1行にまで圧縮するという技をやってのけている記事がめっちゃ面白かったので、登場したオプションなんかを整理してみようと思います。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://arjanvandergaag.nl/blog/using-ruby-command-line-options.html"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://arjanvandergaag.nl/blog/using-ruby-command-line-options.html" alt="Using Ruby command line options by Arjan van der Gaag" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://arjanvandergaag.nl/blog/using-ruby-command-line-options.html"&gt;Using Ruby command line options by Arjan van der Gaag&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://arjanvandergaag.nl/blog/using-ruby-command-line-options.html" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://arjanvandergaag.nl/blog/using-ruby-command-line-options.html" alt="はてなブックマーク - Using Ruby command line options by Arjan van der Gaag" title="はてなブックマーク - Using Ruby command line options by Arjan van der Gaag" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h1 id="記事のネタ"&gt;記事のネタ&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;あるCSVを読み込んで&lt;/li&gt;
&lt;li&gt;コメント行と条件を満たさない行を除外して&lt;/li&gt;
&lt;li&gt;区切り文字を変えて出力&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;というお題です。&lt;/p&gt;
&lt;h2 id="before"&gt;before&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/usr/bin/env ruby -w&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# This tranforms input files that look like CSV and strips comments and&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# filters out every line not about &amp;#34;Suriname&amp;#34;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Define some basic variables that control how records and fields&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# are defined.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;input_record_separator &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;field_separator &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;output_record_separator &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;output_field_separator &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;filename &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ARGV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;open(filename, &lt;span style="color:#e6db74"&gt;&amp;#39;r+&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;f&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Read the entire contents of the file in question&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# in an input array.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; input &lt;span style="color:#f92672"&gt;=&lt;/span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;readlines(input_record_separator)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; output &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Loop over all the lines in the file with a counter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; input&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each_with_index &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;last_read_line, i&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Remove the ending newline from the line for easier&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# processing.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; last_read_line&lt;span style="color:#f92672"&gt;.&lt;/span&gt;chomp!(input_record_separator)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Extract all fields in this record.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; fields &lt;span style="color:#f92672"&gt;=&lt;/span&gt; last_read_line&lt;span style="color:#f92672"&gt;.&lt;/span&gt;split(field_separator)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Only proceed for non-comment lines about Suriname&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; fields&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Suriname&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;(last_read_line &lt;span style="color:#f92672"&gt;=~&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/^# /&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Write the output lines including the line number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# and combine fields using our custom separator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; fields&lt;span style="color:#f92672"&gt;.&lt;/span&gt;unshift i
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; output &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; fields&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(output_field_separator)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; output &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; output_record_separator
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Rewind back to the start of the file and replace all its&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;42&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# contents with the content in `output`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;43&lt;/span&gt;&lt;span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;rewind
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;44&lt;/span&gt;&lt;span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;write output
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;45&lt;/span&gt;&lt;span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;flush
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;46&lt;/span&gt;&lt;span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;truncate(f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pos)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;47&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="after"&gt;after&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/usr/bin/env ruby -w -n -i -F, -l -a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;BEGIN&lt;/span&gt; { $, &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;;&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;print $., &lt;span style="color:#f92672"&gt;*&lt;/span&gt;$F &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; $F&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Suriname&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/^# /&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="なにがどうなったの"&gt;なにがどうなったの？&lt;/h2&gt;
&lt;p&gt;afterの方を擬似コードだと思って読んでみると、「&lt;code&gt;index==5&lt;/code&gt;の要素の条件に合わない」ときや「正規表現にマッチしない」とき「でなければ」何かをprintするという処理になっているのがわかります。&lt;/p&gt;
&lt;p&gt;それ以外の、ファイルを読んだり行をループしたりカンマでsplitしたりという処理は全て、コマンドラインオプションや内部で使われるグローバル変数で処理されてしまっているということになります。&lt;/p&gt;
&lt;h1 id="具体的に見てみる"&gt;具体的に見てみる&lt;/h1&gt;
&lt;h2 id="グローバル変数"&gt;グローバル変数&lt;/h2&gt;
&lt;p&gt;Rubyにはシステム内部で使われるグローバル変数があります。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Variables_and_Constants#Pre-defined_Variables"&gt;Ruby Programming/Syntax/Variables and Constants - Wikibooks, open books for an open world&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;例えば&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$/&lt;/code&gt; 入力データの行セパレータ&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$\&lt;/code&gt; 出力データの行セパレータ&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$,&lt;/code&gt; 出力行のセパレータ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などなどいろいろあります。&lt;/p&gt;
&lt;p&gt;before/afterであれだけ省略できたのはこのあたりのグローバル変数をうまく使ったから、というのが1つです。beforeのコードにあったセパレータなど変数がafterのコードでほとんどなくなっているのは、コマンドラインの指定により暗黙的にRubyのデフォルト値を使ったからなんですね〜。&lt;/p&gt;
&lt;h2 id="コマンドラインオプション"&gt;コマンドラインオプション&lt;/h2&gt;
&lt;p&gt;beforeが&lt;code&gt;ruby -w&lt;/code&gt;であるのに対し、afterでは&lt;code&gt;ruby -w -n -i -F, -l -a&lt;/code&gt;とオプションがかなり増えています。変わった分を見てみます。&lt;/p&gt;
&lt;h3 id="-n"&gt;-n&lt;/h3&gt;
&lt;p&gt;入力を読んで処理をループするような部分を省略して書くことができるようになります。&lt;/p&gt;
&lt;p&gt;ファイル各行を&lt;code&gt;puts&lt;/code&gt;するだけのプログラムを書くとしたらこうなりますが、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; gets
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; puts $_
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;-n&lt;/code&gt;オプションをつけることでこうなってしまいます。ちなみに&lt;code&gt;$_&lt;/code&gt;は最後に読み込んだ行を表すRubyのグローバル変数。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;puts $_
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="-i"&gt;-i&lt;/h3&gt;
&lt;p&gt;-iオプションを使うと標準出力への書き込み処理をファイル対しての処理にしてくれます。&lt;/p&gt;
&lt;p&gt;例えば各行に&amp;quot;hoge&amp;quot;と追加して出力するだけのプログラムがあるとします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# main.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;puts &lt;span style="color:#e6db74"&gt;&amp;#34;hoge &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;$_&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;-n&lt;/code&gt;オプションをつけて普通に呼び出すと標準出力に結果が出ます。これは想定通り。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ ruby -w -n main.rb data.csv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これに&lt;code&gt;-i&lt;/code&gt;をつけることで元ファイルが標準出力先のような感じになり上書きされます。読み込みと書き込みを同時に行えるようになるわけです。&lt;/p&gt;
&lt;p&gt;ちなみに&lt;code&gt;-i&lt;/code&gt;のあとに文字列を続けて入力すると、元ファイル名+付加した文字列のファイルが書き出し先になります。&lt;code&gt;-i.bak&lt;/code&gt;のような感じ。&lt;/p&gt;
&lt;h3 id="-f"&gt;-F&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;-F&lt;/code&gt;の直後に指定した文字を入力行のデフォルトセパレータとして用いるというオプションです。例のケースではCSVなのでカンマ&lt;code&gt;,&lt;/code&gt;を指定します。&lt;/p&gt;
&lt;h3 id="-l"&gt;-l&lt;/h3&gt;
&lt;p&gt;このオプションをつけると入力の際はからは行区切り（改行）を除去し、出力の際は行区切りを付加するという処理になります。データ処理に必ず必要な改行文字の処理を代わりにやってくれるというわけ。&lt;/p&gt;
&lt;h3 id="-a"&gt;-a&lt;/h3&gt;
&lt;p&gt;入力行を自動でSplitするためのオプションです。コードで書くとこう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$F &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $_&lt;span style="color:#f92672"&gt;.&lt;/span&gt;split
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここで&lt;code&gt;$F&lt;/code&gt;が出てきました。&lt;code&gt;＄F&lt;/code&gt;にはSplit後の文字列が入っていたということです。そしてこのSplitに用いられる文字は&lt;code&gt;-F&lt;/code&gt;オプションで指定したものです。&lt;/p&gt;
&lt;h1 id="まとめ"&gt;まとめ&lt;/h1&gt;
&lt;p&gt;ファイルを読み込んで処理して出力するという定番の処理のためにこんなコマンドラインオプションが用意されているらしい、ということでまとめてみました。こんなん覚えらんねーよと思いましたが、知ってるとちょっとだけドヤれるかも。&lt;/p&gt;</description></item><item><title>XMLとRubyのHashを相互変換する方法</title><link>https://blog.piyo.tech/posts/2014-03-31-205837/</link><pubDate>Mon, 31 Mar 2014 20:58:37 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-31-205837/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/71c22075-094d-4a09-8a63-85c0237df6b2/70573ce80ebf54187c868bf9a638b930/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-03-31-13-09.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;XMLからHashへの変換とその逆変換を考えます。ここでは2つの方法を取り上げますが、結論としてはXmlSimpleを使うほうがよさそうです。&lt;/p&gt;
&lt;h1 id="サンプルxml"&gt;サンプルXML&lt;/h1&gt;
&lt;p&gt;XMLのサンプルとしてはてなブログのAPIで返ってくるXMLを使います。入っている値は実際とは異なっていますがフォーマットは同じです。&lt;/p&gt;
&lt;script src="https://gist.github.com/9884034.js"&gt;&lt;/script&gt;
&lt;h1 id="1-activesupportを使う"&gt;1. ActiveSupportを使う&lt;/h1&gt;
&lt;p&gt;Railsに一緒に入っているActiveSupportを使ってXML文字列をRubyのHashに変換できるようになります。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;require &amp;quot;active_support/core_ext/hash/conversions&amp;quot;&lt;/code&gt;により&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Hash.from_xml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Hash#to_xml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらのメソッドが使えるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;active_support/core_ext/hash/conversions&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;xml &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;%Q{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;utf-8&amp;#34;?&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;lt;feed xmlns=&amp;#34;http://www.w3.org/2005/Atom&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; xmlns:app=&amp;#34;http://www.w3.org/2007/app&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;lt;/feed&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;hash &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Hash&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;from_xml(xml)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;xml2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; hash&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_xml(hash)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上のように使い方は簡単ですが結果に癖があります。&lt;/p&gt;
&lt;p&gt;上の&lt;code&gt;hash&lt;/code&gt;変数を見てみるとわかるのですが、XMLのattributeが潰れることもあれば残っている場合もあり得ます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;feed&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;xmlns&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://www.w3.org/2005/Atom&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;xmlns:app&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://www.w3.org/2007/app&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;link&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;first&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.hatena.ne.jp/hatena_id/blog_id.hatenablog.com/atom/entry&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;next&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.hatena.ne.jp/hatena_id/blog_id.hatenablog.com/atom/entry?page=2&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;alternate&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://blog_id.hatenablog.com/&amp;#34;&lt;/span&gt;}&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ブログタイトル&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;updated&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;2013-08-27T15:17:06+09:00&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;author&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hatena_id&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;generator&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Hatena::Blog&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hatenablog://blog/2000000000000&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;entry&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;tag:blog.hatena.ne.jp,2013:blog-hatena_id-20000000000000-3000000000000000&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;link&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;edit&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.hatena.ne.jp/hatena_id/blog_id.hatenablog.com/atom/edit/2500000000&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;alternate&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/html&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://blog_id.hatenablog.com/entry/2013/09/02/112823&amp;#34;&lt;/span&gt;}&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;author&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hatena_id&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;記事タイトル&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;updated&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;2013-09-02T11:28:23+09:00&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;published&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;2013-09-02T11:28:23+09:00&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;edited&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;2013-09-02T11:28:23+09:00&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;summary&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hoge &amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt; hoge&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;formatted_content&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt; hoge&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;control&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;draft&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;yes&amp;#34;&lt;/span&gt;}}}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ケース1"&gt;ケース1 &lt;link&gt;&lt;/h2&gt;
&lt;p&gt;この部分（タイトル部分を除く）が&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;link&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rel=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;first&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.hatena.ne.jp/hatena_id/blog_id.hatenablog.com/atom/entry&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;link&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rel=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;next&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.hatena.ne.jp/hatena_id/blog_id.hatenablog.com/atom/entry?page=2&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;ブログタイトル&lt;span style="color:#f92672"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;link&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rel=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;alternate&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://blog_id.hatenablog.com/&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こうなっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;link&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;first&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.hatena.ne.jp/hatena_id/blog_id.hatenablog.com/atom/entry&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;next&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.hatena.ne.jp/hatena_id/blog_id.hatenablog.com/atom/entry?page=2&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;alternate&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://blog_id.hatenablog.com/&amp;#34;&lt;/span&gt;}&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このケースでは&lt;code&gt;rel&lt;/code&gt;や&lt;code&gt;href&lt;/code&gt;が残っています。&lt;/p&gt;
&lt;h2 id="ケース2"&gt;ケース2 &lt;content&gt;&lt;/h2&gt;
&lt;p&gt;それに対してこの部分では、、、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;content&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/x-hatena-syntax&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; hoge
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/content&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次のようになってしまいます。&lt;code&gt;type&lt;/code&gt;attributeが残っていません。同じように&lt;code&gt;&amp;lt;generator&amp;gt;&lt;/code&gt;タグでもattributeが消えてしまっていることがわかります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt; hoge&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ActiveSupportを使う場合には注意が必要と言えそうです。&lt;/p&gt;
&lt;h1 id="2-xmlsimpleを使う"&gt;2. XmlSimpleを使う&lt;/h1&gt;
&lt;p&gt;xmlsimpleというgemで似たようなことができます。attributeもちゃんと残せます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ gem install xml-simple
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;xmlsimple&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;hash &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;XmlSimple&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;xml_in(xml, options) &lt;span style="color:#75715e"&gt;# XML文字列をHashに変換&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;xml &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;XmlSimple&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;xml_out(hash, options) &lt;span style="color:#75715e"&gt;# HashをXMLに変換&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;オプションが豊富で全てを説明しきれないので詳細はこちらで→&lt;a href="http://xml-simple.rubyforge.org/"&gt;XmlSimple - XML made easy&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;xml &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#75715e"&gt;# さっきと一緒の文字列&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;hash &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;XmlSimple&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;xml_in(xml, &lt;span style="color:#e6db74"&gt;ContentKey&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;__content__&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;xml2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;XmlSimple&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;xml_out(hash, &lt;span style="color:#e6db74"&gt;ContentKey&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;__content__&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;RootName&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;feed&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここで使っているオプションは次の通り。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ContentKey&lt;/code&gt;: 値を表すキーでデフォルト値は&lt;code&gt;content&lt;/code&gt;です。元々のXMLにある&lt;code&gt;content&lt;/code&gt;タグと重複するのでそれとは異なるキーを指定します。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RootName&lt;/code&gt;: HashをXMLに変換する際のRootノードの名前はデフォルトでは&lt;code&gt;&amp;lt;opt&amp;gt;&lt;/code&gt;となっています。元のXMLに合わせるために&lt;code&gt;feed&lt;/code&gt;を指定しています。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;xml_in&lt;/code&gt;で変換したHashはこうなりました。長くてすいません。ActiveSupportのときに潰れていたような&lt;code&gt;&amp;lt;content type=&amp;quot;&amp;quot;&amp;gt;&lt;/code&gt;や&lt;code&gt;&amp;lt;generator uri=&amp;quot;&amp;quot;&amp;gt;&lt;/code&gt;などがちゃんと残っています。&lt;/p&gt;
&lt;p&gt;また、要素が1つであろうが複数であろうが配列になっているので、単一の値なのか配列なのかを区別してプログラムを書く必要がありません。&lt;/p&gt;
&lt;p&gt;ActiveSupportに依存する必要もなくなるのでこちらがオススメかと。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;xmlns&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://www.w3.org/2005/Atom&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;xmlns:app&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://www.w3.org/2007/app&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;link&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;first&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.hatena.ne.jp/hatena_id/blog_id.hatenablog.com/atom/entry&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;next&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.hatena.ne.jp/hatena_id/blog_id.hatenablog.com/atom/entry?page=2&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;alternate&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://blog_id.hatenablog.com/&amp;#34;&lt;/span&gt;}&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ブログタイトル&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;updated&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;2013-08-27T15:17:06+09:00&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;author&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hatena_id&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;}&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;generator&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;uri&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://blog.hatena.ne.jp/&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;100000000&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;__content__&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Hatena::Blog&amp;#34;&lt;/span&gt;}&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hatenablog://blog/2000000000000&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;entry&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;tag:blog.hatena.ne.jp,2013:blog-hatena_id-20000000000000-3000000000000000&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;link&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;edit&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.hatena.ne.jp/hatena_id/blog_id.hatenablog.com/atom/edit/2500000000&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;alternate&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/html&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://blog_id.hatenablog.com/entry/2013/09/02/112823&amp;#34;&lt;/span&gt;}&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;author&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hatena_id&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;}&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;記事タイトル&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;updated&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;2013-09-02T11:28:23+09:00&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;published&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;2013-09-02T11:28:23+09:00&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;edited&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;2013-09-02T11:28:23+09:00&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;summary&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;__content__&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hoge &amp;#34;&lt;/span&gt;}&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/x-hatena-syntax&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;__content__&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt; hoge&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&lt;/span&gt;}&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;formatted-content&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/html&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;xmlns:hatena&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://www.hatena.ne.jp/info/xmlns#&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;__content__&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt; hoge&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&lt;/span&gt;}&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;control&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;draft&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&amp;gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;yes&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;}&lt;span style="color:#f92672"&gt;]&lt;/span&gt;}&lt;span style="color:#f92672"&gt;]&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Evernoteで親子リンク付きマンダラート</title><link>https://blog.piyo.tech/posts/2014-03-29-201508/</link><pubDate>Sat, 29 Mar 2014 20:15:05 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-29-201508/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/402601e9-ab61-4a28-accd-c9be901e8659/5c5ba17a928b1724fbb8b80eeb952c96/deep/0/images.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;アイデア出しツールのマンダラートをEvernoteで作った上、親子関係のリンクもつけられるというハックです。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://memogakisouko.appspot.com/Evernote.html"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://memogakisouko.appspot.com/Evernote.html" alt="Evernoteでいろいろ遊ぶ - Mac OS X版のEvernoteをAppleScriptを使ったりしていろいろしてみます" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://memogakisouko.appspot.com/Evernote.html"&gt;Evernoteでいろいろ遊ぶ - Mac OS X版のEvernoteをAppleScriptを使ったりしていろいろしてみます&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://memogakisouko.appspot.com/Evernote.html" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://memogakisouko.appspot.com/Evernote.html" alt="はてなブックマーク - Evernoteでいろいろ遊ぶ - Mac OS X版のEvernoteをAppleScriptを使ったりしていろいろしてみます" title="はてなブックマーク - Evernoteでいろいろ遊ぶ - Mac OS X版のEvernoteをAppleScriptを使ったりしていろいろしてみます" style="border:none" /&gt;&lt;/a&gt;&lt;blockquote&gt;
マンダラート自体は3x3のマスでいいので作るのは簡単ですが、マンダラートの階層へのリンクもついてワンクリックで階層を移動できたらより便利だろうということで、リンクをつける機能も付けました。ただ、子へのリンクはクリップボードに入るけど、Evernoteへの挿入は手動となりました。&lt;/p&gt;
&lt;/blockquote&gt;&lt;br style="clear:left;"&gt;
&lt;p&gt;こちらで紹介されているAppleScriptでリンク付きマンダラートを実現できます。使い方もURLを参考に。&lt;/p&gt;
&lt;p&gt;ただし、Evernote3時代のスクリプトなのでそのままではうまく動きませんでした。2014/03/29時点で最新のEvernote、そしてOS X10.9で動くようにしたものがこちらです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/pi-chan/9797841"&gt;EvernoteでマンダラートするスクリプトEvernote5対応版&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="使うときにやること"&gt;使うときにやること&lt;/h1&gt;
&lt;h2 id="ノートブックを変更する"&gt;ノートブックを変更する&lt;/h2&gt;
&lt;p&gt;スクリプトのトップにマンダラートノートを作るノートブック名が決め打ちで書いてあります。ここは各自好みのものに変えたほうがいいはず。&lt;/p&gt;
&lt;h2 id="automatorでapp化する"&gt;Automatorでapp化する&lt;/h2&gt;
&lt;p&gt;アプリケーション化しておくと便利かもしれません。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Automatorを開く&lt;/li&gt;
&lt;li&gt;新規作成でアプリケーションを選ぶ&lt;/li&gt;
&lt;li&gt;AppleScriptを追加する&lt;/li&gt;
&lt;li&gt;先ほど紹介したスクリプトを全文コピペ&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>ctagsをObjective-Cに対応させる</title><link>https://blog.piyo.tech/posts/2014-03-28-194605/</link><pubDate>Fri, 28 Mar 2014 19:46:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-28-194605/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b276eb89-40b7-44c1-8642-14f3ef2305a0/ee169a7ddc336d6ef0bc5afbf45335ea/deep/0/ctags.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ソースコードにタグ付けするctagsはObjective-Cに対応していませんが、設定ファイルにパターンを書くことである程度対応させることができるようです。&lt;/p&gt;
&lt;p&gt;設定ファイル&lt;code&gt;~/.ctags&lt;/code&gt;に以下を貼り付けます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ~/.ctags&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;--langdef&lt;span style="color:#f92672"&gt;=&lt;/span&gt;objc
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;--langmap&lt;span style="color:#f92672"&gt;=&lt;/span&gt;objc:.m.h
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;--regex-objc&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/^&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#f92672"&gt;[&lt;/span&gt;-+&lt;span style="color:#f92672"&gt;][[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#ae81ff"&gt;\(&lt;/span&gt;&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:alpha:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;+&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#ae81ff"&gt;\*&lt;/span&gt;?&lt;span style="color:#ae81ff"&gt;\)&lt;/span&gt;&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#f92672"&gt;([[&lt;/span&gt;:alnum:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;+&lt;span style="color:#f92672"&gt;)&lt;/span&gt;:&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#ae81ff"&gt;\(&lt;/span&gt;/&lt;span style="color:#ae81ff"&gt;\1&lt;/span&gt;/m,method/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;--regex-objc&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/^&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#f92672"&gt;[&lt;/span&gt;-+&lt;span style="color:#f92672"&gt;][[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#ae81ff"&gt;\(&lt;/span&gt;&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:alpha:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;+&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#ae81ff"&gt;\*&lt;/span&gt;?&lt;span style="color:#ae81ff"&gt;\)&lt;/span&gt;&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#f92672"&gt;([[&lt;/span&gt;:alnum:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;+&lt;span style="color:#f92672"&gt;)[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#ae81ff"&gt;\{&lt;/span&gt;/&lt;span style="color:#ae81ff"&gt;\1&lt;/span&gt;/m,method/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;--regex-objc&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/^&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#f92672"&gt;[&lt;/span&gt;-+&lt;span style="color:#f92672"&gt;][[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#ae81ff"&gt;\(&lt;/span&gt;&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:alpha:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;+&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#ae81ff"&gt;\*&lt;/span&gt;?&lt;span style="color:#ae81ff"&gt;\)&lt;/span&gt;&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#f92672"&gt;([[&lt;/span&gt;:alnum:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;+&lt;span style="color:#f92672"&gt;)[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#ae81ff"&gt;\;&lt;/span&gt;/&lt;span style="color:#ae81ff"&gt;\1&lt;/span&gt;/m,method/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;--regex-objc&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/^&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#ae81ff"&gt;\@&lt;/span&gt;property&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;+.*&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;+&lt;span style="color:#ae81ff"&gt;\*&lt;/span&gt;?&lt;span style="color:#f92672"&gt;(&lt;/span&gt;.*&lt;span style="color:#f92672"&gt;)&lt;/span&gt;;$/&lt;span style="color:#ae81ff"&gt;\1&lt;/span&gt;/p,property/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;--regex-objc&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/^&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#ae81ff"&gt;\@&lt;/span&gt;implementation&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;+&lt;span style="color:#f92672"&gt;(&lt;/span&gt;.*&lt;span style="color:#f92672"&gt;)&lt;/span&gt;$/&lt;span style="color:#ae81ff"&gt;\1&lt;/span&gt;/c,class/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;--regex-objc&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/^&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;*&lt;span style="color:#ae81ff"&gt;\@&lt;/span&gt;interface&lt;span style="color:#f92672"&gt;[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;+&lt;span style="color:#f92672"&gt;(&lt;/span&gt;.*&lt;span style="color:#f92672"&gt;)[[&lt;/span&gt;:space:&lt;span style="color:#f92672"&gt;]]&lt;/span&gt;+:.*&lt;span style="color:#f92672"&gt;{&lt;/span&gt;/&lt;span style="color:#ae81ff"&gt;\1&lt;/span&gt;/i,interface/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この状態で普通に使えばobjcをいい感じに処理してくれます。&lt;/p&gt;
&lt;h1 id="beforeafter"&gt;before/after&lt;/h1&gt;
&lt;p&gt;検証にということでオープンソースのライブラリ、SVProgressHUDのソースコードにctagsをかけてみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/samvermette/SVProgressHUD"&gt;samvermette/SVProgressHUD&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ctagsのコマンドなどは次の通りです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ git clone https://github.com/samvermette/SVProgressHUD.git
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ co SVProgressHUD
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ ctags -R -f tag-file-name .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="before"&gt;before&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;~/.ctags&lt;/code&gt;へ設定を書く前の結果がこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/pi-chan/9796636"&gt;https://gist.github.com/pi-chan/9796636&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;インデックスは18行分作られています。ヘッダーファイルしか解析できない上、Objective−Cの文法を解釈してくれないので必要な情報がほとんどとれていません。&lt;/p&gt;
&lt;h2 id="after"&gt;after&lt;/h2&gt;
&lt;p&gt;それに対して、&lt;code&gt;~/.ctags&lt;/code&gt;へObjective-Cの設定を書いたあとで作ったタグファイルがこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/pi-chan/9796649"&gt;https://gist.github.com/pi-chan/9796649&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;インデックスファイルは119行あります。設定を書く前には解釈出来なかった部分を解釈できるようになっているということがわかります。&lt;/p&gt;
&lt;h1 id="参考"&gt;参考&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://ctags.sourceforge.net/EXTENDING.html"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://ctags.sourceforge.net/EXTENDING.html" alt="Exuberant Ctags: Adding support for a new language" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://ctags.sourceforge.net/EXTENDING.html"&gt;Exuberant Ctags: Adding support for a new language&lt;/a&gt;&lt;blockquote&gt;
How to Add Support for a New Language to Exuberant Ctags&lt;/p&gt;
&lt;/blockquote&gt;&lt;br style="clear:left;"&gt;
&lt;p&gt;&lt;a href="http://www.gregsexton.org/2011/04/objective-c-exuberant-ctags-regex/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://www.gregsexton.org/2011/04/objective-c-exuberant-ctags-regex/" alt="Objective-C Exuberant Ctags Regex | gregsexton.org" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://www.gregsexton.org/2011/04/objective-c-exuberant-ctags-regex/"&gt;Objective-C Exuberant Ctags Regex | gregsexton.org&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://www.gregsexton.org/2011/04/objective-c-exuberant-ctags-regex/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://www.gregsexton.org/2011/04/objective-c-exuberant-ctags-regex/" alt="はてなブックマーク - Objective-C Exuberant Ctags Regex | gregsexton.org" title="はてなブックマーク - Objective-C Exuberant Ctags Regex | gregsexton.org" style="border:none" /&gt;&lt;/a&gt;&lt;blockquote&gt;
I just finished taking a look at improving my Objective-C ctags regex, as Exuberant Ctags doesn’t support the language directly. I wasn’t really able to find anything helpful so for anyone interested these are the lines in my ~/.ctags file that I use for Objective-C tags creation. They’re certainly not perfect but they do a reasonable job for me. Suggestions and improvements are very welcome.&lt;/p&gt;
&lt;/blockquote&gt;&lt;br style="clear:left;"&gt;</description></item><item><title>SublimeTextのペイン分割をマシにするOrigamiとそのEmacsキーバインド版</title><link>https://blog.piyo.tech/posts/2014-03-27-211804/</link><pubDate>Thu, 27 Mar 2014 21:18:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-27-211804/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/e94d4022-1325-4827-8f46-180bfacbd961/922fc0d5ecc7a5a2bec6f57bc081d6d3/deep/0/%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Sublime Textはすごくいいんだけどペイン分割がなってない！と思って使っていませんでしたが、、よくよく調べたらプラグインがあるじゃないですか。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/SublimeText/Origami"&gt;SublimeText/Origami&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;そもそも、デフォルトのどこがイケてないのかというと&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;キーバインドが複雑（これは設定で変えられるが）&lt;/li&gt;
&lt;li&gt;同じファイルを複数ペインで編集できない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;というあたりです。&lt;/p&gt;
&lt;p&gt;Origamiを入れると好きな方向にペイン分割をしたりファイルを別のペインにもクローンしたりできます。&lt;/p&gt;
&lt;p&gt;でもこれだけだと惜しい。分割のキーバインドが&lt;code&gt;コマンドK+コマンド矢印&lt;/code&gt;なのでキーボード上でのポジション移動が多すぎてダメです。&lt;/p&gt;
&lt;p&gt;できれば慣れた（慣れてしまった）Emacsなキーバインドでやりたいというのが本音のところ。自分で設定もできますが、OrigamiのForkにEmacsキーバインド版があったのでそちらを使うことにします。&lt;/p&gt;
&lt;p&gt;SublimeTextから&lt;code&gt;Package Control:Install Package&lt;/code&gt;を実行し、&lt;code&gt;OrigamiEmacs&lt;/code&gt;をインストールします。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/kevincobain2000/Origami-Emacs"&gt;kevincobain2000/Origami-Emacs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;するとこれらのキーバインドが使えるようになります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-x 0&lt;/code&gt; カレントペインを閉じる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-x 1&lt;/code&gt; ペインを1つにまとめる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-x 2&lt;/code&gt; カレントペインを上に分割&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-x 3&lt;/code&gt; カレントペインを左に分割&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="ペイン間の移動"&gt;ペイン間の移動&lt;/h1&gt;
&lt;p&gt;ペイン間の移動のキーバインドもあまりホームポジションフレンドリーではありません。オプションキーや矢印キーを使ったりするので。&lt;/p&gt;
&lt;p&gt;そこで、Emacsで使っていたキーを設定しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; { &lt;span style="color:#f92672"&gt;&amp;#34;keys&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;super+ctrl+k&amp;#34;&lt;/span&gt;], &lt;span style="color:#f92672"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;travel_to_pane&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;: {&lt;span style="color:#f92672"&gt;&amp;#34;direction&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;up&amp;#34;&lt;/span&gt;} },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; { &lt;span style="color:#f92672"&gt;&amp;#34;keys&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;super+ctrl+l&amp;#34;&lt;/span&gt;], &lt;span style="color:#f92672"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;travel_to_pane&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;: {&lt;span style="color:#f92672"&gt;&amp;#34;direction&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;right&amp;#34;&lt;/span&gt;} },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; { &lt;span style="color:#f92672"&gt;&amp;#34;keys&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;super+ctrl+j&amp;#34;&lt;/span&gt;], &lt;span style="color:#f92672"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;travel_to_pane&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;: {&lt;span style="color:#f92672"&gt;&amp;#34;direction&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;down&amp;#34;&lt;/span&gt;} },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; { &lt;span style="color:#f92672"&gt;&amp;#34;keys&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;super+ctrl+h&amp;#34;&lt;/span&gt;], &lt;span style="color:#f92672"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;travel_to_pane&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;: {&lt;span style="color:#f92672"&gt;&amp;#34;direction&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;left&amp;#34;&lt;/span&gt;} },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;command+ctrl+k&lt;/code&gt; で上のペイン&lt;/li&gt;
&lt;li&gt;&lt;code&gt;command+ctrl+l&lt;/code&gt; で右のペイン&lt;/li&gt;
&lt;li&gt;&lt;code&gt;command+ctrl+j&lt;/code&gt; で下のペイン&lt;/li&gt;
&lt;li&gt;&lt;code&gt;command+ctrl+h&lt;/code&gt; で左のペイン&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;hjkl&lt;/code&gt;はVimのカーソル移動のアレに相当します。便利よ、これ。&lt;/p&gt;</description></item><item><title>xcodebuildコマンドで便利になるケース</title><link>https://blog.piyo.tech/posts/2014-03-23-194807/</link><pubDate>Sun, 23 Mar 2014 19:47:52 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-23-194807/</guid><description>&lt;p&gt;ようやくコマンドラインからのビルドがわかったので使えそうケースを考えてみました。&lt;/p&gt;
&lt;h1 id="ciで使う"&gt;CIで使う&lt;/h1&gt;
&lt;p&gt;これ王道ね。ほとんどの人がこのためにやってると思います。JenkinsやTravisCIなどでpushするたびにテストさせるにはコマンドラインからテストできないといけません。&lt;/p&gt;
&lt;h1 id="testflightへのアップロード"&gt;TestFlightへのアップロード&lt;/h1&gt;
&lt;p&gt;TestFlightなどの配布ツールへのアップロードも、毎回手動でやるとなると結構面倒です。「よし配布しよう」って思うところまで開発が進んだらコマンド一発で配布できるようにしておくとかなりいけてます。&lt;/p&gt;
&lt;p&gt;これはまだやったことが無いので実際のスクリプトはありませんが、&lt;code&gt;$ rake flight&lt;/code&gt;みたいに実行できたらよさそう。&lt;/p&gt;
&lt;h1 id="全プロジェクトのipaを書き出す"&gt;全プロジェクトのipaを書き出す&lt;/h1&gt;
&lt;p&gt;特定のディレクトリ配下にある全てのプロジェクトのipaを書き出すなんてことができるかもしれません。各プロジェクトそれぞれにちゃんとスクリプトを作っておけば、ディレクトリを辿りながらスクリプトを実行していくだけだし。&lt;/p&gt;
&lt;h1 id="スクリーンショットを撮りまくる"&gt;スクリーンショットを撮りまくる&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-03-19-194505"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-03-19-194505" alt="KIFを使ったスクリーンショットの自動撮影 - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-03-19-194505"&gt;KIFを使ったスクリーンショットの自動撮影 - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;先日UIテストをテストではなくスクリーンショットの撮影に使うというTipsを紹介しました。テストをコマンドラインで実行した場合でもスクリーンショットはうまく撮れるので、ディレクトリをたどったりブランチを切り替えたりしながらスクリーンショットを撮りまくることができます。&lt;/p&gt;</description></item><item><title>xcodebuildまとめ</title><link>https://blog.piyo.tech/posts/2014-03-22-201207/</link><pubDate>Sat, 22 Mar 2014 20:11:54 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-22-201207/</guid><description>&lt;p&gt;先日xctoolについて書きました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-03-20-200406"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-03-20-200406" alt="（少し追記）Xcodeのプロジェクトをコマンドラインからビルド・テストする - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-03-20-200406"&gt;（少し追記）Xcodeのプロジェクトをコマンドラインからビルド・テストする - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;ところが、xcodebuildそのもの自体もいい感じになってきていてxctoolとの違いはなくなって来ているようです。Xcodeのコマンドラインビルドのジャンルは最近追い始めたので情報が整理しきれていないので間違っていたらすいません。&lt;/p&gt;
&lt;p&gt;xctoolを使うメリットはというと、このあたりはあるのかな。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;出力フォーマットを変えられる&lt;/li&gt;
&lt;li&gt;テストの並列実行が可能&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そういうわけでxcodebuildについて個人的にまとめておこうと思います。&lt;/p&gt;
&lt;h1 id="ビルド"&gt;ビルド&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ xcodebuild -project MyProject.xcodeproj -scheme MyScheme
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# または&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ xcodebuild -workspace MyProject.xcworkspace -scheme MyScheme
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;基本は&lt;code&gt;-project&lt;/code&gt;でプロジェクト、または&lt;code&gt;-workspace&lt;/code&gt;でワークスペースを指定します。またビルドスキームも指定します。とりあえずこれでビルドが動きます。&lt;/p&gt;
&lt;p&gt;そのほか、コンフィギュレーションやSDKの指定なども可。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ xcodebuild -workspace MyProject.xcworkspace -scheme MyScheme &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;-configuration Release &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#75715e"&gt;# Debugなど&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;-sdk iphoneos &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#75715e"&gt;# iphonesimulator7.0など&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="テスト"&gt;テスト&lt;/h1&gt;
&lt;p&gt;基本はあまり変わりませんが、&lt;code&gt;-destination（配置先）&lt;/code&gt;でシミュレータを指定しておくと間違いないっぽいです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ xcodebuild -workspace MyProject.xcworkspace -scheme MyScheme &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;-destination &lt;span style="color:#e6db74"&gt;&amp;#39;platform=iOS Simulator,name=iPhone Retina (4-inch),OS=7.1&amp;#39;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#75715e"&gt;# 必要に応じて変更&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;test
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="アーカイブ"&gt;アーカイブ&lt;/h1&gt;
&lt;p&gt;これも基本は一緒。&lt;code&gt;-sdk&lt;/code&gt;は自動的に&lt;code&gt;iphoneos&lt;/code&gt;となりますが、明示的に&lt;code&gt;iphonesimulator&lt;/code&gt;を指定すると失敗します。&lt;/p&gt;
&lt;p&gt;また&lt;code&gt;-archivePath&lt;/code&gt;オプションで出力ファイルのパスを指定できます。一見出力ディレクトリぽいのですが、ちょっと挙動がおかしい感じです。&lt;code&gt;-archivePath ~/Desktop&lt;/code&gt;という指定で&lt;code&gt;~/Desktop.xcarchive&lt;/code&gt;ができました。謎。&lt;code&gt;.&lt;/code&gt;指定によりカレントディレクトリの上のディレクトリにxcarchiveができました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ xcodebuild -workspace MyProject.xcworkspace -scheme MyScheme &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;-sdk iphoneos &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;-configuration Release &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;archive -archivePath archive
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="アーカイブからipaの作成"&gt;アーカイブからipaの作成&lt;/h1&gt;
&lt;p&gt;こちらでも触れたとおりipaもコマンドから作ることができます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-03-21-195304"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-03-21-195304" alt="ipa書き出しをxcodebuildとxcrunで自動化する - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-03-21-195304"&gt;ipa書き出しをxcodebuildとxcrunで自動化する - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;先ほど紹介した方法でarchiveを作り、カレントディレクトリの&lt;code&gt;archive.xcarchive&lt;/code&gt;にアーカイブがあるとします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ xcrun -sdk iphoneos &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;PackageApplication archive.xcarchive/Products/Applications/MyApp.app &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;-o MyApp.ipa &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;-embed &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;PROVISIONING_PATH&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;PROVISIONING_PATHについてはリンクを参考にしてください。&lt;/p&gt;</description></item><item><title>ipa書き出しをxcodebuildとxcrunで自動化する</title><link>https://blog.piyo.tech/posts/2014-03-21-195304/</link><pubDate>Fri, 21 Mar 2014 19:52:52 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-21-195304/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/2d342f01-367e-499a-a121-71af2dd91824/4701b9334fb41abf00a69d8aed78a7e2/deep/0/imgres-1.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;昨日紹介したxctoolはxcodebuildというコマンドを便利にラップしてくれるのですが、ipa書き出しまでは行ってくれないらしい（伝聞）です。&lt;code&gt;xcodebuild&lt;/code&gt;と&lt;code&gt;xcrun&lt;/code&gt;を使えばコマンドラインから実行できるそうなのでやってみました。&lt;/p&gt;
&lt;p&gt;というか、ほぼここに書いてある通りです。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.ryoabe.com/iphone/37.html"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://blog.ryoabe.com/iphone/37.html" alt="Ryo's Blog » Blog Archive » XcodeのArchiveを自動化しよう" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://blog.ryoabe.com/iphone/37.html"&gt;Ryo&amp;rsquo;s Blog » Blog Archive » XcodeのArchiveを自動化しよう&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://blog.ryoabe.com/iphone/37.html" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://blog.ryoabe.com/iphone/37.html" alt="はてなブックマーク - Ryo's Blog » Blog Archive » XcodeのArchiveを自動化しよう" title="はてなブックマーク - Ryo's Blog » Blog Archive » XcodeのArchiveを自動化しよう" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html"&gt;xcodebuild(1) Mac OS X Developer Tools Manual Page&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man1/xcrun.1.html"&gt;xcrun(1) Mac OS X Developer Tools Manual Page&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;で、実際のシェルスクリプトがこちら。&lt;code&gt;xcodeproj&lt;/code&gt;だけでなく、&lt;code&gt;xcworkspace&lt;/code&gt;でももちろん実行可能。&lt;/p&gt;
&lt;script src="https://gist.github.com/pi-chan/9658403.js"&gt;&lt;/script&gt;
&lt;h1 id="プロビジョニングプロファイルの見分け方"&gt;プロビジョニングプロファイルの見分け方&lt;/h1&gt;
&lt;p&gt;面倒なのはプロビジョニングプロファイルの指定ですね。ビルドするアプリ用のプロファイルを指定しなければいけませんが、該当のディレクトリ&lt;code&gt;~/Library/MobileDevice/...&lt;/code&gt;に置かれているプロファイルがランダムな文字列のようなファイル名になっているのでどれが本物か一見してもわかりません。&lt;/p&gt;
&lt;p&gt;仕方ないので、予めXcodeでビルド対象のプロビジョニングプロファイルを設定しておいた上で、生のproject.pbxproj`を覗いてみましょう。&lt;/p&gt;
&lt;p&gt;例で言えば、&lt;code&gt;SampleApp/project.pbxproj&lt;/code&gt;というファイルです。このファイルをエディタで開いて&lt;code&gt;PROVISIONING_PROFILE&lt;/code&gt;という文字列を検索すると2箇所見つかると思います。&lt;/p&gt;
&lt;p&gt;少し下あるnameというところを見ると、Debugの設定なのか、Releaseの設定なのかがわかりますので、自分が設定した正しいものを選んで文字列を控えておきます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
ONLY_ACTIVE_ARCH = YES;
PROVISIONING_PROFILE = &amp;#34;VVVVVVVV-WWWW-XXXX-YYYY-ZZZZZZZZZZZZ&amp;#34;;
SDKROOT = iphoneos;
VALID_ARCHS = &amp;#34;arm64 armv7 armv7s i386&amp;#34;;
};
name = Debug;
};
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>（少し追記）Xcodeのプロジェクトをコマンドラインからビルド・テストする</title><link>https://blog.piyo.tech/posts/2014-03-20-200406/</link><pubDate>Thu, 20 Mar 2014 20:03:54 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-20-200406/</guid><description>&lt;p&gt;前々からXcodeのプロジェクトをコマンドラインからビルドしたりテストを実行したりしたいなーと思っていたのですが、以前調べたときにお手軽な情報が見つからなくて諦めていました。調べたりなかっただけだとは思うのですが。&lt;/p&gt;
&lt;p&gt;（追記：Xcode5でxcodebuildがマシになったそうです。調べたのはそれ以前だったはずなのでしょうがない…！）&lt;/p&gt;
&lt;p&gt;最近はCIツールなどが普及してきてさすがにiOSのプロジェクトでもCI使ってるだろうから、コマンドラインからテストを実行する方法も変わってきてるだろうと思い改めて調べてみました。&lt;/p&gt;
&lt;h1 id="xctoolの導入"&gt;xctoolの導入&lt;/h1&gt;
&lt;p&gt;xctoolというxcodebuildを良くしたようなツールがあって、それをつかうといい感じらしいです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/facebook/xctool"&gt;facebook/xctool&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;xctoolはHomebrewで導入できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ brew update
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ brew install xctool
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;※注意&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2014/03/20時点ではXcode5.1をインストール済みの場合インストールに失敗します。こちらのForkからDownload Zipして適当なところにおいて使ってください。&lt;code&gt;xctool.sh&lt;/code&gt;を使います。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/jcayzac/xctool/tree/067e6bbb26fed73b5f617d377ddd0569da2b8eec"&gt;jcayzac/xctool at 067e6bbb26fed73b5f617d377ddd0569da2b8eec&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="使い方"&gt;使い方&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ xctool -project ProjectName.xcodeproj &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; -scheme ProjectName &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; clean build test &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; ONLY_ACTIVE_ARCH&lt;span style="color:#f92672"&gt;=&lt;/span&gt;NO
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こんな感じでプロジェクト名やスキーム名、ビルドやクリーンなどのアクションを指定して実行します。CocoaPodsを使用しているなどの理由でprojectではなくworkspaceを使いたい場合は&lt;code&gt;-workspace ProjectName.xcworkspace&lt;/code&gt;とします。&lt;/p&gt;
&lt;p&gt;毎回これをタイプするのは面倒なのでMakefileやRakefileを作っておくと便利です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Rakefile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;desc &lt;span style="color:#e6db74"&gt;&amp;#39;Build&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;task &lt;span style="color:#e6db74"&gt;:build&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; exec(&lt;span style="color:#e6db74"&gt;&amp;#39;xctool -workspace MyApp.xcworkspace -scheme MyApp -sdk iphonesimulator build ONLY_ACTIVE_ARCH=NO&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;task &lt;span style="color:#e6db74"&gt;:default&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;:build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>KIFを使ったスクリーンショットの自動撮影</title><link>https://blog.piyo.tech/posts/2014-03-19-194505/</link><pubDate>Wed, 19 Mar 2014 19:44:55 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-19-194505/</guid><description>&lt;p&gt;昨日書いたの記事では、Objective-Cのコードを用いてスクリーンショットを撮影する方法を紹介しました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-03-18-202606"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-03-18-202606" alt="iPhoneアプリの画面をObjective-Cでキャプチャ - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-03-18-202606"&gt;iPhoneアプリの画面をObjective-Cでキャプチャ - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;今日はそのTipsを用いて各画面のスクリーンショットを自動的に撮る方法を紹介します。&lt;/p&gt;
&lt;p&gt;スクリーンショットを撮影してドキュメントなどに使うというケースはそこそこ起こりえることだと思いますが、見た目に手をいれるたびに撮影するのは大変面倒な作業です。コードでスクリーンショットを撮れるのであれば半自動化してしまおうと思い、今日のネタを思いつきました。&lt;/p&gt;
&lt;h1 id="自動化の方法"&gt;自動化の方法&lt;/h1&gt;
&lt;p&gt;KIFという受け入れテストのライブラリを使います。このブログでも2度取り上げました。導入はこちらを参考にしてもらえるといいと思います。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-12-11-070003"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2013-12-11-070003" alt="XCode5対応！KIFでiPhoneアプリの受け入れ（統合）テスト - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2013-12-11-070003"&gt;XCode5対応！KIFでiPhoneアプリの受け入れ（統合）テスト - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-12-15-214107"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2013-12-15-214107" alt="iOS用UIテストフレームワークKIFで色々な要素をタップさせる方法 - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2013-12-15-214107"&gt;iOS用UIテストフレームワークKIFで色々な要素をタップさせる方法 - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h1 id="スクリーンショットを撮る"&gt;スクリーンショットを撮る&lt;/h1&gt;
&lt;p&gt;KIFを使うことでシミュレータや実機で実際にアプリを起動してUIを操作させることができます。あとは任意のタイミングでスクリーンショットを撮影するコードを呼び出せば今回の目的を果たせるというわけです。&lt;/p&gt;
&lt;h2 id="ソースコード"&gt;ソースコード&lt;/h2&gt;
&lt;p&gt;実行できるソースコードはここにあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/ios-sandbox/tree/master/CaptureScreenshots"&gt;ios-sandbox/CaptureScreenshots at master · xoyip/ios-sandbox&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;サンプルとしてナビゲーションで画面を3つ持ったアプリを考えます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/855d2ede-722f-4e2e-baa3-07c88240ec51/e323e5f0421f45cdaf3ff709f696e490/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-03-17-23-13.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;このアプリの全ての画面のスクリーンショットを自動で撮ることにしましょう。&lt;/p&gt;
&lt;p&gt;事前準備として、最初のViewと2番目のViewのUIButtonにAccessibilityLabelを設定します。それぞれ、&lt;code&gt;ToSecondView&lt;/code&gt;、&lt;code&gt;ToThirdView&lt;/code&gt;としました。&lt;/p&gt;
&lt;p&gt;テストコードは次のようになります。少し長いですが。。。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;captureScreen&lt;/strong&gt;は、現在の画面のキャプチャ画像をアプリのディレクトリに保存するためのメソッドで、キャプチャを撮りたいタイミングで呼びます。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;test&lt;/strong&gt;メソッドでは、ボタンタップによる画面移動と、キャプチャメソッドの呼び出しを行っています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;XCTest/XCTest.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;KIF.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CaptureScreenshotsTests&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;KIFTestCase&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@implementation&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CaptureScreenshotsTests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;captureScreen:&lt;/span&gt;(NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; NSArray&lt;span style="color:#f92672"&gt;*&lt;/span&gt; paths &lt;span style="color:#f92672"&gt;=&lt;/span&gt; NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt; dir &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [paths objectAtIndex:&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; UIWindow&lt;span style="color:#f92672"&gt;*&lt;/span&gt; window &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[UIApplication sharedApplication] keyWindow];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; UIGraphicsBeginImageContextWithOptions(window.bounds.size, NO, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; CGContextRef context &lt;span style="color:#f92672"&gt;=&lt;/span&gt; UIGraphicsGetCurrentContext();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (UIWindow&lt;span style="color:#f92672"&gt;*&lt;/span&gt; win &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; [[UIApplication sharedApplication] windows]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; [win.layer renderInContext:context];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; UIImage&lt;span style="color:#f92672"&gt;*&lt;/span&gt; image &lt;span style="color:#f92672"&gt;=&lt;/span&gt; UIGraphicsGetImageFromCurrentImageContext();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; UIGraphicsEndImageContext();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; [UIImagePNGRepresentation(image) writeToFile:[dir stringByAppendingPathComponent:name] atomically:YES];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; [self captureScreen:&lt;span style="color:#e6db74"&gt;@&amp;#34;first_view.png&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; [tester waitForViewWithAccessibilityLabel:&lt;span style="color:#e6db74"&gt;@&amp;#34;ToSecondView&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; [tester tapViewWithAccessibilityLabel:&lt;span style="color:#e6db74"&gt;@&amp;#34;ToSecondView&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; [self captureScreen:&lt;span style="color:#e6db74"&gt;@&amp;#34;second_view.png&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; [tester waitForViewWithAccessibilityLabel:&lt;span style="color:#e6db74"&gt;@&amp;#34;ToThirdView&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; [tester tapViewWithAccessibilityLabel:&lt;span style="color:#e6db74"&gt;@&amp;#34;ToThirdView&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; [self captureScreen:&lt;span style="color:#e6db74"&gt;@&amp;#34;third_view.png&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="結果"&gt;結果&lt;/h2&gt;
&lt;p&gt;今回はシミュレータで実行しましたので、シミュレータ用のディレクトリの中を覗いてみましょう。&lt;/p&gt;
&lt;p&gt;ちなみに、シミュレータで動かしているアプリのドキュメントディレクトリを見るのにはこちらが便利です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-01-18-210504"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-01-18-210504" alt="iOSシミュレータのアプリディレクトリ探しから開放される - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-01-18-210504"&gt;iOSシミュレータのアプリディレクトリ探しから開放される - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;該当のディレクトリをFinderで開いてみると、ちゃんと撮れていますね。これを応用すれば何枚でも自動でスクリーンショットを撮ることができますね。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/904255d1-34d7-4fc9-aaaf-5bebabfcf9df/e8a638aa5f33cac3559f393aa1d1e21f/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-03-17-23-21.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>iPhoneアプリの画面をObjective-Cでキャプチャ</title><link>https://blog.piyo.tech/posts/2014-03-18-202606/</link><pubDate>Tue, 18 Mar 2014 20:25:58 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-18-202606/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0dfda19d-5ff6-4abb-86f3-29e8bbbf3a1c/6b622c79485e99b7810120eee9617cf3/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-03-17-22-49.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;コードからでもスクリーンショット風の画像を得ることができます。ステータスバーはUIApplicationのwindow外なのか、画像の中には含まれません。&lt;/p&gt;
&lt;p&gt;CGContextを新たに作成し、アプリケーション内のWindowsの内容をそのコンテキストに描画していくという感じでキャプチャのようなことができます。コードは以下の通り。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;captureScreen:&lt;/span&gt;(NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)savePath
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; UIWindow&lt;span style="color:#f92672"&gt;*&lt;/span&gt; window &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[UIApplication sharedApplication] keyWindow];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; UIGraphicsBeginImageContextWithOptions(window.bounds.size, NO, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; CGContextRef context &lt;span style="color:#f92672"&gt;=&lt;/span&gt; UIGraphicsGetCurrentContext();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (UIWindow&lt;span style="color:#f92672"&gt;*&lt;/span&gt; win &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; [[UIApplication sharedApplication] windows]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; [win.layer renderInContext:context];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; UIImage&lt;span style="color:#f92672"&gt;*&lt;/span&gt; image &lt;span style="color:#f92672"&gt;=&lt;/span&gt; UIGraphicsGetImageFromCurrentImageContext();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; UIGraphicsEndImageContext();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; [UIImagePNGRepresentation(image) writeToFile:savePath atomically:YES];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>RSpec SonicGarden Study</title><link>https://blog.piyo.tech/posts/2014-03-17-213457/</link><pubDate>Mon, 17 Mar 2014 21:34:57 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-17-213457/</guid><description>&lt;p&gt;UStreamでやってたので参加しました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sonicgarden.doorkeeper.jp/events/9696?utm_campaign=event_9696&amp;amp;utm_medium=email&amp;amp;utm_source=registered_message_6167"&gt;RSpec初心者に送るRSpec最強チュートリアル ～RubyMineもあるよ！～ SonicGarden Study #08 - SonicGarden Study | Doorkeeper&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;勉強会の内容自体は復習的なものだったので自分にとっての新しさはありませんでしたが、Q&amp;amp;Aや他の参加者の方とのやり取りなどがいい感じで参加してよかったと思いました。ありがとうございました。&lt;/p&gt;
&lt;p&gt;あと、西脇市の写真が自然豊かでいいところでした。&lt;/p&gt;
&lt;h1 id="内容"&gt;内容&lt;/h1&gt;
&lt;p&gt;参考資料であるRSpecの書籍の公開されている部分と、そのサンプルアプリを題材にモデルのバリデーションを書くライブコーディング。コード自体は基礎の基礎だけど、RubyMineでコマンドをパパっと実行したり、バリデーションのテストは書くのか？といった議論ができたりしてなかなかよかったです。&lt;/p&gt;
&lt;h1 id="qa"&gt;Q&amp;amp;A&lt;/h1&gt;
&lt;p&gt;UStreamでも伊藤さんがおっしゃっていましたが、自分で書かないとわかるようにならないというのはよくあります。とはいえ一人でやっているとわからないとき、壁にぶつかったときにその壁を超えられないときもあったり。そういうときに参考になるものが欲しいと思ってこのような質問をしてみました。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-partner="tweetdeck"&gt;&lt;p&gt;RSpec使っているいい感じのRailsのOSSってありませんか？書き方、書くべきテストの参考になるようなものです。&lt;a href="https://twitter.com/search?q=%23sg_study&amp;amp;src=hash"&gt;#sg_study&lt;/a&gt;&lt;/p&gt;&amp;mdash; piyopiyo (@pi_cha_n) &lt;a href="https://twitter.com/pi_cha_n/statuses/445522450042732544"&gt;March 17, 2014&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;そしたら参加者の方がこのように答えてくれました。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-conversation="none" data-cards="hidden" data-partner="tweetdeck"&gt;&lt;p&gt;&lt;a href="https://twitter.com/pi_cha_n"&gt;@pi_cha_n&lt;/a&gt; &lt;a href="https://twitter.com/search?q=%23sg_study&amp;amp;src=hash"&gt;#sg_study&lt;/a&gt; &amp;#10;まだよく見てないですが、そのうち見ようと思ってるのは。publify（ブログ）, fat_free_crm（CRM）、spree（EC）、CrowdhosterがRspecですよ。&lt;/p&gt;&amp;mdash; 村上健太 (@kntmrkm) &lt;a href="https://twitter.com/kntmrkm/statuses/445523860704612352"&gt;March 17, 2014&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;blockquote class="twitter-tweet" data-conversation="none" data-partner="tweetdeck"&gt;&lt;p&gt;&lt;a href="https://twitter.com/pi_cha_n"&gt;@pi_cha_n&lt;/a&gt; 個人的にこちらのリポジトリは非常に参考になりました。&lt;a href="https://t.co/JXy3nTZZT7"&gt;https://t.co/JXy3nTZZT7&lt;/a&gt;&lt;/p&gt;&amp;mdash; ネコゲルゲ (@nekogeruge_987) &lt;a href="https://twitter.com/nekogeruge_987/statuses/445526513136320512"&gt;March 17, 2014&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;まだ見ていませんが、まずはチラ見しておきたいと思っています。よさそうであれば、実際にコードを書くときに参考にできるかも。&lt;/p&gt;
&lt;p&gt;コードの書き方というより、実際のところどういう粒度でテストを書いているかということがわかるものだといいなーと思っています。&lt;/p&gt;
&lt;h1 id="参考資料"&gt;参考資料&lt;/h1&gt;
&lt;h2 id="勉強会の資料"&gt;勉強会の資料&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/everydayrails/rspec_rails_4"&gt;everydayrails/rspec_rails_4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leanpub.com/everydayrailsrspec-jp/"&gt;Everyday Rails… Aaron Sumnerによる et al. [Leanpub PDF/iPad/Kindle]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="rspecの参考になるかもしれないoss"&gt;RSpecの参考になるかもしれないOSS&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/publify/publify/"&gt;publify/publify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/fatfreecrm/fat_free_crm"&gt;fatfreecrm/fat_free_crm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/spree/spree"&gt;spree/spree&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/crowdtilt/crowdtiltopen"&gt;Crowdtilt/CrowdtiltOpen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/heartsentwined/ember-auth-rails-demo"&gt;heartsentwined/ember-auth-rails-demo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="本"&gt;本&lt;/h2&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4798121932/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/71DnbfLNAIL._SL1200_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;The RSpec Book (Professional Ruby Series)&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>__bridgeキャスト</title><link>https://blog.piyo.tech/posts/2014-03-16-201103/</link><pubDate>Sun, 16 Mar 2014 20:10:57 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-16-201103/</guid><description>&lt;p&gt;C++をある程度知っているというものあってObjective-Cの言語的なところはほぼスキップしてiOSの開発をしているという側面が僕にはあります。&lt;/p&gt;
&lt;p&gt;で、Xcodeの警告でたまに出てくる&lt;code&gt;__bridge&lt;/code&gt;キャストってなんじゃいなと思いながらもIDEに任せて直してもらっていたのですが…&lt;/p&gt;
&lt;p&gt;さすがにそれじゃまずいよねということで少し調べました。&lt;/p&gt;
&lt;p&gt;まず、Objective-CにはFoundationフレームワークのオブジェクトがObjective-Cオブジェクト、CoreFoundationフレームワークのオブジェクトをCoreFoundationオブジェクトがあります。&lt;/p&gt;
&lt;p&gt;これらは内部的な違いはあまりないけれど、参照カウントの方法が微妙に違うということらしいです。ARCが無効の場合はこの差異は基本的には問題ありません。&lt;/p&gt;
&lt;p&gt;最近のデフォルトとなっているARCが有効な場合、Objective-CオブジェクトはARCの管理対象になります。しかしCoreFoundationオブジェクトはARCの管理対象になりません。&lt;/p&gt;
&lt;p&gt;そこで必要となるのが&lt;code&gt;__bridge&lt;/code&gt;キャストです。&lt;code&gt;__bridge&lt;/code&gt;キャストには3種類あります。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;__bridge&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;このキャストは所有権を変えません。suggestionで1番目にするのもこれかな？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;__bridge_retained&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;このキャストはObjective-CオブジェクトをCFオブジェクトが参照する場合に使います。ARCで管理されていたオブジェクトがARC管理外のCFオブジェクトにも参照されるため、CFで参照カウントを上げるわけです。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;__bridge_transfer&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;このキャストは&lt;code&gt;__bridge_retained&lt;/code&gt;と逆で、CFオブジェクトをObjective-Cオブジェクトが参照する場合に使います。ARC管理外のオブジェクトがARC管理下におかれるので、参照カウントは減らします。&lt;/p&gt;
&lt;p&gt;ちなみに、下2つは使う場面に遭遇したことはありません。&lt;/p&gt;</description></item><item><title>LinqToObjectiveCの実装を覗く</title><link>https://blog.piyo.tech/posts/2014-03-15-204503/</link><pubDate>Sat, 15 Mar 2014 20:44:57 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-15-204503/</guid><description>&lt;p&gt;LinqToObjectiveCの中身を覗く&lt;/p&gt;
&lt;p&gt;Objective-CのNSArrayやNSDictionaryでwhereやselectなんかを使えるようにするカテゴリがあるという話をしました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-03-11-185204"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-03-11-185204" alt="ActiveRecordのようなselectやwhereをObjective-Cで使う - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-03-11-185204"&gt;ActiveRecordのようなselectやwhereをObjective-Cで使う - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;記事を書いたあと中身を覗いてみたのですが、なんのことはない普通のforループでしたｗｗ&lt;/p&gt;
&lt;p&gt;たとえば、引数に渡したブロックの戻り値が&lt;code&gt;YES&lt;/code&gt;となる要素だけを返す&lt;code&gt;linq_where&lt;/code&gt;の実装はこのようになっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (NSArray &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;linq_where:&lt;/span&gt;(LINQCondition)predicate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; NSMutableArray&lt;span style="color:#f92672"&gt;*&lt;/span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[NSMutableArray alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt; item &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; self) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (predicate(item)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; [result addObject:item];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; result;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;新しいNSArrayを作ってそこに必要なものだけ入れて返しているわけです。他のメソッドもほぼ同じでした。&lt;/p&gt;
&lt;h1 id="proscons"&gt;pros/cons&lt;/h1&gt;
&lt;p&gt;メリットは自前で書くときと同じようなループ処理を書かなくてよくなる、コードがすっきりすること。&lt;/p&gt;
&lt;p&gt;デメリットは多少のオーバーヘッドがあるかも？というところかな。特殊な実装をしているわけではないので敬遠する理由もないでしょうね。&lt;/p&gt;</description></item><item><title>Chrome別プロファイル用ランチャーを作るAutomatorアプリ</title><link>https://blog.piyo.tech/posts/2014-03-13-195304/</link><pubDate>Thu, 13 Mar 2014 19:53:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-13-195304/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/5517605a-d3b7-479a-bac3-629eea5d24d9/4a0f2e242c290ec5dc198635b8aefaee/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-03-11-13-26.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;昨日の記事ではシェルスクリプトを使ってChromeを別プロファイルで立ち上げるためのランチャーを作成しました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-03-12-185808"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2014-03-12-185808" alt="Google Chromeのプロファイルの切替方法とその使いどころ - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2014-03-12-185808"&gt;Google Chromeのプロファイルの切替方法とその使いどころ - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;この方法ではターミナルに馴染みがない人や面倒くさがりの人には使えない気がしたので、ダブルクリックするだけでランチャーを作ってくれるアプリケーションをAutomatorで作成しました。&lt;/p&gt;
&lt;h1 id="使い方"&gt;使い方&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;まずこれをダウンロードし、展開してください。
&lt;a href="https://drive.google.com/open?id=1As3juzlNYD-2SaEa9JAaZuF99asZ7LIT"&gt;create-new-profile-launcher.app.zip&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;現れたappファイルをダブルクリックすると、プロファイル名入力画面がでます。そこに好きな名前（多分英数字のみが良い）を入れます。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;すると同じフォルダに&lt;code&gt;Google Chrome (入力したプロファイル名).app&lt;/code&gt;ができます。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;それがランチャーです。新しいプロファイルで起動できることを確認してみてください。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;アプリケーションフォルダに移動させておくといいかも。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;実際にやっていることは中身はシェルスクリプトと同じです。Automatorで開けば中身を見られるので怪しいと思う人は覗いてくれればおkです。&lt;/p&gt;</description></item><item><title>Google Chromeのプロファイルの切替方法とその使いどころ</title><link>https://blog.piyo.tech/posts/2014-03-12-185808/</link><pubDate>Wed, 12 Mar 2014 18:58:07 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-12-185808/</guid><description>&lt;p&gt;Google Chromeのプロファイルの切替方法とその使いどころ&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/3a341e83-a344-4cf0-9e78-41dc59f8ae11/a0bfeaeeaa7b061ec389d83fab0ce76f/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-03-11-12-52.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ChromeやFirefoxなどのウェブブラウザではブックマークや履歴、拡張機能プロファイルというものに紐付いて管理されています。となればプロファイルを使い分けることで全く異なるブラウザ環境を手に入れることができる、という仕組みになっているわけです。&lt;/p&gt;
&lt;h1 id="別プロファイルでchromeを起動する"&gt;別プロファイルでChromeを起動する&lt;/h1&gt;
&lt;p&gt;プロファイルの切替にはプロファイルをコピーして、起動時に引数で使用するプロファイルを指定して〜みたいな面倒なステップを踏まなければいけないかと思いきや。&lt;/p&gt;
&lt;p&gt;MacのGoogleChromeにおいてはメインとは別のプロファイルでChromeを起動するMacのアプリケーションパッケージ（なんて言えばいいの？）を作ってくれるシェルスクリプトを公開してくれている人がいますので、ありがたく使わせてもらうことで一瞬で別プロファイルで起動するChromeを用意できます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/uasi/882672"&gt;Create an .app that launches Google Chrome with a specified profile&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここにあるシェルスクリプトを使います。ターミナル（黒い画面）を使うので不慣れな人にはちょっと難しいかもしれません。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;create-chrome-launcher.sh&lt;/code&gt;をどこかに置いて実行してみましょう。いくつか聞かれますが、最初の&lt;code&gt;Enter profile name:&lt;/code&gt;で好きな名前を付けてあげる以外はEnter連打で良いです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;$ sh create-chrome-launcher.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;$ sh create-chrome-launcher.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;Enter profile name: private01
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;Enter launcher name &lt;span style="color:#f92672"&gt;[&lt;/span&gt;Google Chrome &lt;span style="color:#f92672"&gt;(&lt;/span&gt;private01&lt;span style="color:#f92672"&gt;)]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;Enter boot options &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;Enter dist dir &lt;span style="color:#f92672"&gt;[&lt;/span&gt;.&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;Create profile at /Users/hiromasa/Library/Application Support/Google/Chrome/private01
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;Create launcher at ./Google Chrome &lt;span style="color:#f92672"&gt;(&lt;/span&gt;private01&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;Copy resources from Google Chrome
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;Write Info.plist
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;Write executable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;Done
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここでは&lt;code&gt;private01&lt;/code&gt;という名前にしてみました。スクリプトが終わるとカレントディレクトリに&lt;code&gt;Google Chrome (private01).app&lt;/code&gt;というディレクトリができているのでそれをアプリケーションフォルダ（&lt;code&gt;/Applications&lt;/code&gt;）に移しておくといいでしょう。&lt;/p&gt;
&lt;p&gt;あとは通常のChromeを起動するときと同じように&lt;code&gt;Google Chrome (private01).app&lt;/code&gt;を起動できます。これで何も情報がない新しい環境を手に入れることができました。&lt;/p&gt;
&lt;h1 id="使い分けるメリット"&gt;使い分けるメリット&lt;/h1&gt;
&lt;h2 id="仕事とプライベート"&gt;仕事とプライベート&lt;/h2&gt;
&lt;p&gt;一番多い使い分けは仕事とプライベートを切り替えるというところでしょうか。&lt;/p&gt;
&lt;p&gt;仕事用のプロファイルでは仕事用のGmailアカウントでのみログインしておくとか、Facebookにログインしておかないとか。広報用Twitterにログインしておくのは仕事用プロファイルにしておくとか。&lt;/p&gt;
&lt;p&gt;どうしてもふとしたときにSNSにアクセスして時間を無駄にしてしまうようなケースが起こりますが、セッション情報やクッキーが残っていないブラウザであればわざわざログインしようという気も起こらずに仕事に集中できるというわけです。&lt;/p&gt;
&lt;h2 id="仕事によって使い分ける"&gt;仕事によって使い分ける&lt;/h2&gt;
&lt;p&gt;仕事とプライベートではなく仕事Aと仕事Bで切り替えるというのもありかなと思います。&lt;/p&gt;
&lt;p&gt;例えばのケースですが、普段はサーバーサイドの開発をしている人が、ある一定期間だけフロントエンド周りの開発に入るという場合。フロントの開発ってブラウザ拡張を使わないとやってられないところもあったりして、拡張機能をガンガンに入れていくことになったりするわけです。ところがフロントの開発が一段落したらまたメインのサーバーサイドに戻ることになります。&lt;/p&gt;
&lt;p&gt;さて、フロントの開発中に大量に導入した拡張機能はしばらく使うことはありません。では捨てますか？無効にしますか？&lt;/p&gt;
&lt;p&gt;いや、最初からプロファイルを分けれておけばいいんです。そうすれば拡張機能を捨ててしまって次回また入れなおすなんてことはしなくて済みます。&lt;/p&gt;
&lt;h2 id="たまにしか使わない拡張機能を切り離してメモリ削減"&gt;たまにしか使わない拡張機能を切り離してメモリ削減&lt;/h2&gt;
&lt;p&gt;僕のケースがこれです。MacbookAirのメモリが8GBなんですが、これでは全然足りないというのが今の状況です。アクティビティモニタによるとGoogle Chrome Helperがそこそこのメモリを食っていて、Chromeのタスクマネージャーで見ると拡張機能がメモリを使っていたりするわけです。&lt;/p&gt;
&lt;p&gt;ところがその拡張機能は極稀にしか使わないものだったりするわけです。先ほどの例と同じで捨てるのは勿体ないけど滅多に使わないという場合ですね。&lt;/p&gt;
&lt;p&gt;この目的でスクロールがあるWebページ全体のスクリーンショットを撮る機能やフロント開発系の拡張は切り離しました。&lt;/p&gt;</description></item><item><title>ActiveRecordのようなselectやwhereをObjective-Cで使う</title><link>https://blog.piyo.tech/posts/2014-03-11-185204/</link><pubDate>Tue, 11 Mar 2014 18:52:05 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-11-185204/</guid><description>&lt;p&gt;RailsのActiveRecordやC#のLINQではデータ列に対して選択や絞り込みなどを行う際、SelectやWhereなどを用いて要素を絞りこんだり要素のプロパティの集合を取り出したりできます。言い換えるとある集合に対する操作の結果として別の集合（または値）を取り出すための操作が用意されています。&lt;/p&gt;
&lt;p&gt;Lispのような関数型言語のリスト操作のような感じもありますね。標準のRubyでいうと&lt;code&gt;Array#map&lt;/code&gt;とか&lt;code&gt;Array#all?&lt;/code&gt;あたりがこれに該当します。&lt;/p&gt;
&lt;p&gt;これと同じようなことをObjective-CのNSArrayに対して出来ないかなーと思って調べたところこんなライブラリが見つかりました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ColinEberhardt/LinqToObjectiveC"&gt;ColinEberhardt/LinqToObjectiveC&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このカテゴリを導入すると、NSArrayやNSDictionaryに&lt;code&gt;linq_where&lt;/code&gt;や&lt;code&gt;linq_select&lt;/code&gt;なるメソッドが追加されます。&lt;/p&gt;
&lt;p&gt;これ使いたいなーとおもった場面を、使い方の説明も兼ねて紹介します。&lt;/p&gt;
&lt;h1 id="登場人物"&gt;登場人物&lt;/h1&gt;
&lt;p&gt;こんな感じの役に立たないほげクラスがあったとしましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NS_ENUM&lt;/span&gt;(NSUInteger, HogeType){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; HogeFirst,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; HogeSecond
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Hoge&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;NSObject&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; HogeType type;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;name;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;+ (&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;hogeWithType:&lt;/span&gt;(HogeType)type;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="準備"&gt;準備&lt;/h1&gt;
&lt;p&gt;そして、次のように2種類のほげオブジェクトをたくさん保持する配列があるとします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;doSomething&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; NSMutableArray &lt;span style="color:#f92672"&gt;*&lt;/span&gt;array &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSMutableArray new];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; [array addObject:[Hoge hogeWithType:HogeFirst];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; [array addObject:[Hoge hogeWithType:HogeSecond];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// このあとランダムに詰め込む
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="hogefirstのみの配列にしたい"&gt;HogeFirstのみの配列にしたい&lt;/h1&gt;
&lt;p&gt;いよいよ&lt;code&gt;linq_where&lt;/code&gt;の出番です。あなたはHogeFirstのみを集めた配列を用意したく。ループで愚直に書くとこうなります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (NSArray&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;getHogeFirstArray&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// array にはランダムなHogeが入っている
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; NSMutableArray &lt;span style="color:#f92672"&gt;*&lt;/span&gt;results &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSMutableArray new];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (Hoge &lt;span style="color:#f92672"&gt;*&lt;/span&gt;hoge &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; array) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (hoge.type &lt;span style="color:#f92672"&gt;==&lt;/span&gt; HogeFirst) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; [results addObject:hoge];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; results;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これに対し&lt;code&gt;linq_where&lt;/code&gt;を使ったバージョンをこのようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (NSArray&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;getHogeFirstArray&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// array にはランダムなHogeが入っている
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [array linq_where:&lt;span style="color:#f92672"&gt;^&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt;(Hoge &lt;span style="color:#f92672"&gt;*&lt;/span&gt;hoge){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; hoge.type &lt;span style="color:#f92672"&gt;==&lt;/span&gt; HogeFirst;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; }];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="さいごに"&gt;さいごに&lt;/h1&gt;
&lt;p&gt;パフォーマンスはまだ調べていませんが、書き方としては少しスマートになった気がします。僕はこちらのほうが好み。&lt;/p&gt;
&lt;p&gt;selectやwhere以外にもたくさんのメソッドが提供されているので試す価値あり、です。&lt;/p&gt;</description></item><item><title>RubyのOPMLパーサー</title><link>https://blog.piyo.tech/posts/2014-03-10-204507/</link><pubDate>Mon, 10 Mar 2014 20:45:07 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-10-204507/</guid><description>&lt;h1 id="結論"&gt;結論&lt;/h1&gt;
&lt;p&gt;これ使えば一発です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/feedbin/opml_saw"&gt;feedbin/opml_saw&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="あとは雑談"&gt;あとは雑談&lt;/h1&gt;
&lt;p&gt;2013年6月末のGoogleリーダーのシャットダウンの際、OPMLというフォーマットを初めて知りました。なんのことはないただのXMLなんですが、一応アウトラインプロセッサーのためのMLということでOPMLという名前になっているらしいです。&lt;/p&gt;
&lt;p&gt;RSSフィードの購読データのエクスポートやインポートに使われているのしか見たことがありません。GoogleリーダーやFeedlyでも購読しているフィードをOPMLファイルで出力できるようになっています。&lt;/p&gt;
&lt;p&gt;昨年僕が開発していたRSSリーダーでもOPMLのインポート機能を実装していました。これを実装するにあたりやるべきステップは3つありました。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;OPMLをパースする&lt;/li&gt;
&lt;li&gt;フィードのフォルダを作る&lt;/li&gt;
&lt;li&gt;フィードを購読する&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;このうち2と3はOPML対応前から持っていた機能だったのでOPMLインポート機能のためにはパース処理のみを書けばよかったわけです。&lt;/p&gt;
&lt;p&gt;XMLなのでNokogiriで簡単にパースできるのでしょうが、RSSリーダーのFeedbinがちょうどぴったりなライブラリ、&lt;a href="https://github.com/feedbin/opml_saw"&gt;feedbin/opml_saw&lt;/a&gt;というものを公開していたのでこちらを使うことにしました。&lt;/p&gt;
&lt;p&gt;使い方は至ってシンプルで、OPMLファイルの中身を渡すとフィードのArrayが返ってくるというものです。&lt;/p&gt;
&lt;p&gt;READMEから拝借しますが、これだけです。Nokogiriで頑張るよりも更に楽なので良いですね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;file &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;open(&lt;span style="color:#e6db74"&gt;&amp;#39;subscriptions.xml&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;contents &lt;span style="color:#f92672"&gt;=&lt;/span&gt; file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;read
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;opml &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;OpmlSaw&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Parser&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(contents)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;opml&lt;span style="color:#f92672"&gt;.&lt;/span&gt;parse
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;pp opml&lt;span style="color:#f92672"&gt;.&lt;/span&gt;feeds&lt;span style="color:#960050;background-color:#1e0010"&gt;☄&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;opmlsawのおかげでほとんど実装要らずでOPMLインポートの機能を実装できたという話でした。&lt;/p&gt;
&lt;p&gt;ちなみに、OPMLインポート自体はとても重い処理なのでバックグラウンドに回しました。実装は簡単だったものの、バックグラウンドジョブでエラーになったりしてそっちの解消が大変だったりしました。例えばOPMLファイルがでかすぎてインポートが全然終わらないとか…。懐かしい。&lt;/p&gt;</description></item><item><title>調整が面倒すぎるのでUIViewのframe用のカテゴリを導入</title><link>https://blog.piyo.tech/posts/2014-03-09-223905/</link><pubDate>Sun, 09 Mar 2014 22:39:06 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-09-223905/</guid><description>&lt;p&gt;こういうスライドとか&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.slideshare.net/YoshinoriImajo/ios7-30039408"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://www.slideshare.net/YoshinoriImajo/ios7-30039408" alt="やはりお前らのiOS7対応は間違っている" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://www.slideshare.net/YoshinoriImajo/ios7-30039408"&gt;やはりお前らのiOS7対応は間違っている&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://www.slideshare.net/YoshinoriImajo/ios7-30039408" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://www.slideshare.net/YoshinoriImajo/ios7-30039408" alt="はてなブックマーク - やはりお前らのiOS7対応は間違っている" title="はてなブックマーク - やはりお前らのiOS7対応は間違っている" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;さらには解説記事とか&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qiita.com/yimajo/items/254c7cebab7864678246"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://qiita.com/yimajo/items/254c7cebab7864678246" alt="やはりお前らのiOS7対応は間違っている(解説編) - Qiita" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://qiita.com/yimajo/items/254c7cebab7864678246"&gt;やはりお前らのiOS7対応は間違っている(解説編) - Qiita&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://qiita.com/yimajo/items/254c7cebab7864678246" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://qiita.com/yimajo/items/254c7cebab7864678246" alt="はてなブックマーク - やはりお前らのiOS7対応は間違っている(解説編) - Qiita" title="はてなブックマーク - やはりお前らのiOS7対応は間違っている(解説編) - Qiita" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;読んでもやっぱりうまくいかなくてコードで調整しちゃうときあるよね。&lt;/p&gt;
&lt;p&gt;でもCGRectの更新って本質的にめんどくさいんです。originを変えるなら&lt;code&gt;CGRectOffset&lt;/code&gt;で多少ましにかけますが、heightを変えるとなると読みやすく書くなら3行要るという。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;CGRect rect &lt;span style="color:#f92672"&gt;=&lt;/span&gt; view.frame;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;rect.size.height &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;view.frame &lt;span style="color:#f92672"&gt;=&lt;/span&gt; rect;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;いよいよイライラが募ったのでUIViewのカテゴリ使って&lt;code&gt;view.height = 100;&lt;/code&gt;みたいに書けるようにするかーと思って、一応既存のものがないか調べてみたら余裕でありました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qiita.com/CarmineScarlet/items/360c20e0ed15b33d9eaf"&gt;iOS - メモ：UIView.frame 用の便利カテゴリ - Qiita&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ありがとうございます。&lt;/p&gt;</description></item><item><title>ウェブサイトやブログ記事中の本文を抽出するgem</title><link>https://blog.piyo.tech/posts/2014-03-08-204704/</link><pubDate>Sat, 08 Mar 2014 20:45:44 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-08-204704/</guid><description>&lt;p&gt;大元はこちらで、&lt;/p&gt;
&lt;p&gt;&lt;a href="http://labs.cybozu.co.jp/blog/nakatani/2007/09/web_1.html"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://labs.cybozu.co.jp/blog/nakatani/2007/09/web_1.html" alt="Webページの本文抽出 (nakatani @ cybozu labs)" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://labs.cybozu.co.jp/blog/nakatani/2007/09/web_1.html"&gt;Webページの本文抽出 (nakatani @ cybozu labs)&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://labs.cybozu.co.jp/blog/nakatani/2007/09/web_1.html" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://labs.cybozu.co.jp/blog/nakatani/2007/09/web_1.html" alt="はてなブックマーク - Webページの本文抽出 (nakatani @ cybozu labs)" title="はてなブックマーク - Webページの本文抽出 (nakatani @ cybozu labs)" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;Ruby1.9対応され、gemになったものがこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mono0x/extractcontent"&gt;mono0x/extractcontent&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Bundlerを使ってリポジトリ指定でインストールできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;extractcontent&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:git&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;https://github.com/mono0x/extractcontent.git&amp;#39;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;☄&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="使い方"&gt;使い方&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;html &lt;span style="color:#f92672"&gt;=&lt;/span&gt; open(url)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;read
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;body, title &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ExtractContent&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;analyse(html)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これだけでタイトルと本文を持ってきてくれます。精度も悪くなさそう。&lt;/p&gt;
&lt;h1 id="htmlタグを残したい"&gt;HTMLタグを残したい&lt;/h1&gt;
&lt;p&gt;純粋に文章のみを残すという作りになっているため、抽出された本文からはHTMLタグがなくなっています。画像も無くなってしまいます。&lt;/p&gt;
&lt;p&gt;少し話がそれますが、この本文抽出の機能を使って、「あとで読む」つもりの記事の本文を1ファイルのHTMLにまとめて、それをPDFやepubにしてKindleで読むというハックをやりたいなと思っています。&lt;/p&gt;
&lt;p&gt;そのためには本文はHTMLのままでなければいけません。見出しや画像、箇条書きなどはしっかり残っていて欲しいのです。そういうわけで、この部分に少し手を入れます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mono0x/extractcontent/blob/master/lib/extractcontent.rb#L126"&gt;extractcontent/lib/extractcontent.rb at master · mono0x/extractcontent&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;analyse&lt;/span&gt;(html, opt&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 変更前&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;strip_tags(body&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;, dom_separator), title&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 変更後&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;body&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;, title&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;タグを除去するメソッドを呼ばなければいいわけですね。&lt;/p&gt;
&lt;p&gt;これで本文HTMLを抽出する準備ができました。スクリプトはまだ途中です。&lt;/p&gt;</description></item><item><title>CocoaPodsのライブラリを編集して使いたいとき</title><link>https://blog.piyo.tech/posts/2014-03-07-194911/</link><pubDate>Fri, 07 Mar 2014 19:47:53 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-07-194911/</guid><description>&lt;p&gt;この間書いたように、&lt;a href="https://github.com/mwaterfall/MWFeedParser"&gt;mwaterfall/MWFeedParser&lt;/a&gt;というCocoaPodsでも扱えるRSSフィード解析のライブラリに機能が足りなくて困ったのですが、実装が簡単だったこともあってささっと書いてプルリクを出しておきました。&lt;/p&gt;
&lt;p&gt;ところが、このプルリクエストがすぐにマージされたとしてもCocoaPodsで参照できるバージョンがすぐに変わるとは限りませんし、現時点ではプルリクは完全にスルーされているのでforkを使うしかありません。&lt;/p&gt;
&lt;h1 id="podfileでgitリポジトリを指定"&gt;PodfileでGitリポジトリを指定&lt;/h1&gt;
&lt;p&gt;CocoaPods（およびPodfile）には、CocoaPodsに登録されていないバージョンを使うための記述が用意されています。このあたりはRubyのgemと同じような仕組みになっているようですね。&lt;/p&gt;
&lt;p&gt;今回のケースでいうと、元々はPodfileこのような記述をしていたところを、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;MWFeedParser&amp;#39;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;☄&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↓のように書き換えます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;MWFeedParser&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:git&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://github.com/pi-chan/MWFeedParser.git&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:branch&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;usable&amp;#34;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;☄&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;:git&lt;/code&gt;指定でリポジトリのURLを、&lt;code&gt;:branch&lt;/code&gt;で対象ブランチを指定できます。何も指定しなければmasterを使います。&lt;/p&gt;
&lt;p&gt;これで&lt;code&gt;$ pod install&lt;/code&gt;をすれば全てうまくいく、というわけです。&lt;/p&gt;
&lt;h1 id="うまくいかないケース"&gt;うまくいかないケース&lt;/h1&gt;
&lt;p&gt;先ほど紹介した&lt;code&gt;MWFeedParser&lt;/code&gt;のケースではまくいくのですが、そうでないケースも多々ありそうです。というのは、リポジトリがそのままCocoaPodsに使える構成になっていないこともあるからです。&lt;/p&gt;
&lt;p&gt;例えば上に引っ張って更新するコントロールのための&lt;a href="https://github.com/pilot34/MNMBottomPullToRefresh"&gt;pilot34/MNMBottomPullToRefresh&lt;/a&gt;は、Forkしたリポジトリを指定しても正しくインストールしてくれません。&lt;/p&gt;
&lt;p&gt;このような場合はForkリポジトリ専用のpodspecを用意してあげるしかありません。&lt;/p&gt;
&lt;h2 id="podspecを探す"&gt;podspecを探す&lt;/h2&gt;
&lt;p&gt;CocoaPodsに登録されているすべてのpodspecはここにあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/CocoaPods/Specs"&gt;CocoaPods/Specs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここから探せばいいのですが数が多くて探すのも一手間かかるので、&lt;code&gt;MNMBottomPullToRefresh podspec&lt;/code&gt;などとGoogleで検索するのが早いでしょう。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/CocoaPods/Specs/blob/master/MNMBottomPullToRefresh/0.0.1/MNMBottomPullToRefresh.podspec"&gt;Specs/MNMBottomPullToRefresh/0.0.1/MNMBottomPullToRefresh.podspec at master · CocoaPods/Specs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;で、出てきたpodspecをGistなどのパブリックなところに置きます。実際に僕が使っているのがこれ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/pi-chan/9225911"&gt;MNMBottomPullToRefresh.podspec&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;元のpodspecと変えたところが一箇所あります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 変更前&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;s&lt;span style="color:#f92672"&gt;.&lt;/span&gt;source &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#e6db74"&gt;:git&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://github.com/emenegro/bottom-pull-to-refresh.git&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:commit&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;82d5fed6dd7f4a4df531a6954398b60b9aecec6d&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 変更後&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;s&lt;span style="color:#f92672"&gt;.&lt;/span&gt;source &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#e6db74"&gt;:git&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://github.com/pi-chan/bottom-pull-to-refresh.git&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:branch&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;custom-text&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;リポジトリを自分のForkに書き換え、&lt;code&gt;:commit&lt;/code&gt;指定の代わりにブランチ指定に変えてあげました。もちろん&lt;code&gt;:commit&lt;/code&gt;をそのまま使ってもいいですが。&lt;/p&gt;
&lt;p&gt;そしてPodfileをこのように書き換えます。今度はpodspecを直で指定してあげます。このときはgistのrawのURLを使ってください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 変更前&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;MNMBottomPullToRefresh&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 変更後&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;MNMBottomPullToRefresh&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:podspec&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://gist.githubusercontent.com/xoyip/9225911/raw/a2b35c7bf1b6d207402f6400f4386f6900fe2ac8/MNMBottomPullToRefresh.podspec&amp;#34;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;☄&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="まとめ"&gt;まとめ&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;拡張したかったらforkする&lt;/li&gt;
&lt;li&gt;Podfileをリポジトリ、ブランチorコミット指定にする&lt;/li&gt;
&lt;li&gt;だめならpodspecを書き換えてpodspec指定！&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>コマンドラインでcssやjsをminifyできるYUI Compressor</title><link>https://blog.piyo.tech/posts/2014-03-06-233824/</link><pubDate>Thu, 06 Mar 2014 23:38:24 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-06-233824/</guid><description>&lt;p&gt;RailsとかではCSSやJavasciptのファイルを圧縮というかMinifyしてくれますが、ちょっとしたときのやり方がわからなくていつもWebサービスを使ったりしていました。&lt;/p&gt;
&lt;p&gt;で、よく探したらコマンドラインでやるツールを見つけたので紹介します。&lt;/p&gt;
&lt;h1 id="yui-compressor"&gt;YUI Compressor&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://yui.github.io/yuicompressor/"&gt;YUI Compressor&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;MacではHomebrewで入れられます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ brew install yuicompressor
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使い方はこんな感じで、引数にファイルを渡すだけ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ yuicompressor style.css
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これだと標準出力に出ます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ yuicompressor style.css -o style.min.css
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これだとファイルに書き出します。&lt;/p&gt;
&lt;p&gt;コマンドでできると楽でいいですね。&lt;/p&gt;</description></item><item><title>Objective-Cでの正規表現によるマッチ文字列取り出し</title><link>https://blog.piyo.tech/posts/2014-03-05-202304/</link><pubDate>Wed, 05 Mar 2014 20:21:49 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-05-202304/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/5b1cce8f-fab5-4a6e-b97b-8585919769b1/99f0afa39584d23be59a0a985d983744/deep/0/ogp.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Objective-Cの&lt;a href="https://github.com/mwaterfall/MWFeedParser"&gt;mwaterfall/MWFeedParser&lt;/a&gt;というRSSフィード解析ライブラリを使っていて不便だったことに、本文中の画像URLを得る方法がないというものがありました。幸いHTMLタグ付きの本文を持っていたのでその中から&lt;code&gt;img&lt;/code&gt;タグをもってきてやろうということでインターフェースを用意して実装しプルリクしておきました。&lt;/p&gt;
&lt;p&gt;プルリクの件はさておき、Objective-Cの正規表現がRubyやPerlと比べるとそれはもう使いづらかったのでメモっておきます。何しろ普通の文字列抽出からして辛かったので。。。&lt;/p&gt;
&lt;h1 id="正規表現を"&gt;正規表現を&lt;/h1&gt;
&lt;h2 id="nsregularexpression"&gt;NSRegularExpression&lt;/h2&gt;
&lt;p&gt;正規表現オブジェクトは&lt;code&gt;NSRegularExpression&lt;/code&gt;で作ります。&lt;/p&gt;
&lt;p&gt;例えばこんなふうに書きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt; pattern &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;(&amp;lt;img.*?src=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\\\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;)(.*?)(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\\\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.*?&amp;gt;)&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;NSRegularExpression&lt;span style="color:#f92672"&gt;*&lt;/span&gt; regex &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;error];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rubyだとこうですね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;regex &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Regexp&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#e6db74"&gt;&amp;#34;(&amp;lt;img.*?src=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\\\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;)(.*?)(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\\\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.*?&amp;gt;)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="マッチングする"&gt;マッチングする&lt;/h2&gt;
&lt;p&gt;マッチングには&lt;code&gt;firstMatchInString&lt;/code&gt;や&lt;code&gt;matchesInString&lt;/code&gt;を使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;NSTextCheckingResult &lt;span style="color:#f92672"&gt;*&lt;/span&gt;match&lt;span style="color:#f92672"&gt;=&lt;/span&gt; [regex firstMatchInString:self.content options:NSMatchingReportProgress range:NSMakeRange(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, self.content.length)];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;NSArray &lt;span style="color:#f92672"&gt;*&lt;/span&gt;matches &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [regex matchesInString:self.content options:&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; range:NSMakeRange(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, self.content.length)];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これがもうわけわかんなくて、&lt;code&gt;NSTextCheckingResult&lt;/code&gt;という全く直感的ではない名前のオブジェクトが返ってきます。こいつは&lt;code&gt;rangeAtIndex&lt;/code&gt;というのを持っていて、&lt;code&gt;index=0&lt;/code&gt;を渡すとマッチ全体が、&lt;code&gt;index=1&lt;/code&gt;などとすると括弧でグループにした部分マッチの&lt;strong&gt;文字列中のインデックス&lt;/strong&gt;をRangeで返してくれます。&lt;/p&gt;
&lt;p&gt;なのでマッチした文字列そのものを取り出す場合は元の文字列の&lt;code&gt;substringWithRange&lt;/code&gt;を使う必要があるわけです。&lt;/p&gt;
&lt;p&gt;Rubyならそんなことはしなくてもいいですね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;regex &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/ho(geho)/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;str &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hogehoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;m &lt;span style="color:#f92672"&gt;=&lt;/span&gt; str&lt;span style="color:#f92672"&gt;.&lt;/span&gt;match(regex)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;m&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#75715e"&gt;# =&amp;gt; &amp;#34;hogeho&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;m&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#75715e"&gt;# =&amp;gt; &amp;#34;geho&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;```☄
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;# 追加したコード全文
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;HTML文書から`&lt;/span&gt;img&lt;span style="color:#e6db74"&gt;`タグの`&lt;/span&gt;src&lt;span style="color:#e6db74"&gt;`を引っ張ってくるコードは次のようになりました。`&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;content&lt;span style="color:#e6db74"&gt;`にHTMLの本文が入っています。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;```&lt;/span&gt;objc
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;NSArray&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)images {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;content){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;NSMutableArray&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;results &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;NSMutableArray&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;NSString&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; pattern &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;(&amp;lt;img.*?src=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\\\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;)(.*?)(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\\\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.*?&amp;gt;)&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;NSError&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; error &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;NSRegularExpression&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; regex &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;NSRegularExpression&lt;/span&gt; &lt;span style="color:#e6db74"&gt;regularExpressionWithPattern&lt;/span&gt;:pattern &lt;span style="color:#e6db74"&gt;options&lt;/span&gt;:&lt;span style="color:#66d9ef"&gt;NSRegularExpressionCaseInsensitive&lt;/span&gt; &lt;span style="color:#e6db74"&gt;error&lt;/span&gt;:&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;error&lt;span style="color:#f92672"&gt;]&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (error &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;NSArray&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;matches &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;regex &lt;span style="color:#e6db74"&gt;matchesInString&lt;/span&gt;:self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;content &lt;span style="color:#e6db74"&gt;options&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#e6db74"&gt;range&lt;/span&gt;:&lt;span style="color:#66d9ef"&gt;NSMakeRange&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;content&lt;span style="color:#f92672"&gt;.&lt;/span&gt;length)&lt;span style="color:#f92672"&gt;]&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;NSTextCheckingResult&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;match &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; matches){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;results &lt;span style="color:#e6db74"&gt;addObject&lt;/span&gt;:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;content &lt;span style="color:#e6db74"&gt;substringWithRange&lt;/span&gt;:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;match &lt;span style="color:#e6db74"&gt;rangeAtIndex&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#f92672"&gt;]]]&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; results;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt;@end&lt;span style="color:#960050;background-color:#1e0010"&gt;☄&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="正規表現といえば"&gt;正規表現といえば&lt;/h1&gt;
&lt;p&gt;昔作ったこんなのがあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://regex-replace.herokuapp.com/"&gt;Regex Replace&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;それについて書いたポスト。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-04-07-100000"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2013-04-07-100000" alt="Rubyの正規表現でテキストの置換ができるWebサイト - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2013-04-07-100000"&gt;Rubyの正規表現でテキストの置換ができるWebサイト - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;</description></item><item><title>自炊してできたPDFファイルの文字が薄くて読みづらい状態を解消するには</title><link>https://blog.piyo.tech/posts/2014-03-04-214111/</link><pubDate>Tue, 04 Mar 2014 21:39:55 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-04-214111/</guid><description>&lt;p&gt;自炊した本のPDFが薄くて読みづらいことが多々あります。スキャナの設定によったりもするみたいなんですが、業者に頼んだものとかだとどうしようもないとう。そんなときはちょっと面倒ですが画像処理をかけてあげることで見やすいものにできます。&lt;/p&gt;
&lt;p&gt;全体の流れはこんな感じ。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;PDFの各ページを画像に変換する&lt;/li&gt;
&lt;li&gt;各画像の裏写りや紙やけを解消&lt;/li&gt;
&lt;li&gt;各画像の二値化とファイルサイズ削減&lt;/li&gt;
&lt;li&gt;すべての画像を結合しPDF化&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="下準備"&gt;下準備&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;Xpdf&lt;/code&gt;に付属する&lt;code&gt;pdfimages&lt;/code&gt;というツールと、&lt;code&gt;ImageMagick&lt;/code&gt;のmogrify（convert）を使用します。どちらもHomebrewでインストールできるので入れておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ brew install imagemagick
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ brew install xpdf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="pdfの各ページを画像に変換する"&gt;PDFの各ページを画像に変換する&lt;/h1&gt;
&lt;p&gt;対象のPDFファイルと出力ファイル名を指定して実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ pdfimages -j target.pdf out☄
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この場合対象のPDFと同じディレクトリに&lt;code&gt;out-000001.jpg&lt;/code&gt;などが連番で出力されます。&lt;/p&gt;
&lt;h1 id="各画像の裏写りや紙やけを解消"&gt;各画像の裏写りや紙やけを解消&lt;/h1&gt;
&lt;p&gt;さきほど出力したjpgファイルを対象としてImageMagickで処理をけていきます。こちらをそのまま参考にしました&lt;/p&gt;
&lt;p&gt;&lt;a href="http://netbuffalo.doorblog.jp/archives/4033031.html"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://netbuffalo.doorblog.jp/archives/4033031.html" alt="スキャナで自炊した画像をキンドル向けにImageMagickで最適化してみる" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://netbuffalo.doorblog.jp/archives/4033031.html"&gt;スキャナで自炊した画像をキンドル向けにImageMagickで最適化してみる&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://netbuffalo.doorblog.jp/archives/4033031.html" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://netbuffalo.doorblog.jp/archives/4033031.html" alt="はてなブックマーク - スキャナで自炊した画像をキンドル向けにImageMagickで最適化してみる" title="はてなブックマーク - スキャナで自炊した画像をキンドル向けにImageMagickで最適化してみる" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;すべての画像を対象に&lt;code&gt;mogrify&lt;/code&gt;で一括変換をかけます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ mogrify -channel Red -separate -modulate &lt;span style="color:#ae81ff"&gt;110&lt;/span&gt; out-*.jpg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="各画像の二値化とファイルサイズ削減"&gt;各画像の二値化とファイルサイズ削減&lt;/h1&gt;
&lt;p&gt;こちらも同様の記事を参考にしました。二値化することで文字の部分が読みやすくなります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ mogrify -threshold &lt;span style="color:#ae81ff"&gt;50000&lt;/span&gt; -quality &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; out*.jpg☄
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;-quality&lt;/code&gt;オプションによりサイズ軽減のためにつけています。元より読みやすくなるから粗くなってもOKというわけです。気に入らなければ&lt;code&gt;-quality&lt;/code&gt;オプションをなくせばいいかも。&lt;/p&gt;
&lt;h1 id="すべての画像を結合しpdf化"&gt;すべての画像を結合しPDF化&lt;/h1&gt;
&lt;p&gt;最後は処理済みの画像をPDFにまとめるだけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ convert out*.jpg out.pdf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;パラメータの調整が必要かもしれませんがこれで薄くて読みづらいということはなくなると思います。文字自体は元よりも少し潰れているような感じもうけますが、背景とのコントラストが強くなっている分読みやすいはず。&lt;/p&gt;
&lt;p&gt;といいたいところですが、ここでの&lt;code&gt;convert&lt;/code&gt;がすごく重いのでまともには使えません。幸いMacのPreview.appで結合が可能なのでそちらを使うほうがいいでしょう。&lt;/p&gt;
&lt;p&gt;やり方は、&lt;code&gt;out*.jpg&lt;/code&gt;を全て選択して、「このアプリケーションで開く」→「プレビュー.app」で全て開いたあと、再び全て選択して「プリント」からPDFを作成するだけです。こちらはすぐにできあがります。&lt;/p&gt;</description></item><item><title>Macで開発用に通信速度をエミュレートするNetwork Link Conditioner</title><link>https://blog.piyo.tech/posts/2014-03-03-201105/</link><pubDate>Mon, 03 Mar 2014 20:09:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-03-201105/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/a6a7157a-750f-4bea-ab42-c7200dd5d384/6433a39016c57a18eedff404575a0178/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-25-14-59.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;開発用に使っているiPhoneではデベロッパメニューから通信速度を変更できます。Macの場合iPhoneシミュレータにそういったメニューはありませんが、Mac自体にその機能を入れることができます。公式の開発ツールなので安心して使えます&lt;/p&gt;
&lt;h1 id="導入"&gt;導入&lt;/h1&gt;
&lt;p&gt;ここから最新のツールをダウンロード（要ログイン）。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://developer.apple.com/downloads/index.action?q=Network%20Link%20Conditioner"&gt;Downloads&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ダウロードしたdmgを展開するといくつかのファイルが現れます。それぞれ開発用に使えるツールだと思いますが、今回使うのは&lt;code&gt;Network Link Conditioner.prefPane&lt;/code&gt;です。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/8fc31aa4-335f-4eca-99d9-09594996e6bf/467a575b62d9ccfdfe9b79fd87ff700c/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-25-14-56.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;これをダブルクリックするとシステム環境設定が立ち上がり、インストールしていいかみたいな確認がでるので許可してあげます。するとこのように新たな項目が追加されました。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0bf884bd-bef4-4d50-b773-e4c1e81a2cbc/901bde0e72357d7895fc87e0f821b0f4/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-25-14-58.png" alt=""&gt;&lt;/p&gt;
&lt;h1 id="使い方"&gt;使い方&lt;/h1&gt;
&lt;p&gt;iPhoneと同じで、プリセットを選んでONしてあげるだけでOK。これでiPhoneシミュレータでもネットワークが不安定な状態をテストできます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/84603acb-82ab-48db-9a8c-2f47fb43df2f/dca15d0c9b72d90fb2343a812c617adc/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-25-14-57.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>Rails form_forでの数値用のコントロールとvalidates numericality</title><link>https://blog.piyo.tech/posts/2014-03-02-204503/</link><pubDate>Sun, 02 Mar 2014 20:43:49 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-02-204503/</guid><description>&lt;p&gt;form_forで何が使えるのかって全然把握していなかったのですが、&lt;code&gt;number_field&lt;/code&gt;ってのがあるんですね。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0bc3832e-d434-41f3-93c4-87f2ccfca506/3975e7c6828df8e4ccf90eabba60a043/deep/0/%E3%81%AF%E3%81%A6%E3%81%AA%E3%83%96%E3%83%AD%E3%82%B0%E4%BA%88%E7%B4%84%E6%8A%95%E7%A8%BF-%CE%B1-.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Hamlで書くとこういう感じに。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-haml" data-lang="haml"&gt;= form_for @my_model, method: :put, role:&amp;#34;form&amp;#34;, remote:true, class:&amp;#34;form-horizontal&amp;#34; do |f|
.form-group
= f.label :my_value, &amp;#34;値&amp;#34;, class:&amp;#34;control-label col-sm-2&amp;#34;
.col-sm-2
= f.number_field :my_value, class:&amp;#34;form-control&amp;#34;, required:true, min:&amp;#34;0&amp;#34;
.col-sm-2
= f.submit &amp;#34;設定&amp;#34;, class:&amp;#34;form-control btn btn-default&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ブラウザによっては数値を操作するボタンを置いてくれるのでちょっとだけ便利です。&lt;/p&gt;
&lt;h1 id="ちゃんとバリデーションする"&gt;ちゃんとバリデーションする&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyModel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; validates &lt;span style="color:#e6db74"&gt;:my_value&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;numericality&lt;/span&gt;:{&lt;span style="color:#e6db74"&gt;only_integer&lt;/span&gt;:&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;greater_than_or_equal_to&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;モデルのほうでちゃんとバリデーションしといたほうがいいですね。&lt;/p&gt;</description></item><item><title>あのFontAwesomeがiOSで使える！</title><link>https://blog.piyo.tech/posts/2014-03-01-204506/</link><pubDate>Sat, 01 Mar 2014 20:43:53 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-03-01-204506/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/dc1a70b4-dad7-457e-a023-74e6f875e0e6/bd06cd0eb5b1c0a184c988f9425f0355/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-22-23-00.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;あのFontAwesomeをiOSでも使えます！ちょっとしたアイコンならほぼまかなえるのでこれが使えるってのは大きいです。導入はCocoaPodsで一発というわけにはいかないが少し不便なところです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/daltoniam/FontAwesome-iOS"&gt;daltoniam/FontAwesome-iOS&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="導入手順"&gt;導入手順&lt;/h1&gt;
&lt;p&gt;ますはCocoaPodsでソースコードを入れる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;FontAwesome&lt;span style="color:#f92672"&gt;-&lt;/span&gt;iOS&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ pod install☄
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;続いてFontAwesomeのフォントファイルをダウンロードしてきます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/FortAwesome/Font-Awesome/raw/master/fonts/fontawesome-webfont.ttf"&gt;fontawesome-webfont.ttf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ダウンロードしたファイルをプロジェクトに追加しメインターゲットに含めるようにします。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/3bf425db-766b-40cc-a417-47d98cef23d1/59f45ec35b22a648f057bd3a46820b8e/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-22-22-56.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;最後に、plistに追記を行います。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/47108348-aae6-4589-a8f6-062badce0a48/fa542b10b31c99f807e70715dcb7a049/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-22-22-56.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Fonts provided by application&lt;/code&gt;の項目を追加し、&lt;code&gt;Item 0&lt;/code&gt;に先ほど追加したフォントファイル名を指定しておきます。&lt;/p&gt;
&lt;p&gt;ここまでで準備完了。&lt;/p&gt;
&lt;h1 id="使い方"&gt;使い方&lt;/h1&gt;
&lt;p&gt;使い方のポイントは2つ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;フォントに&lt;code&gt;FontAwesome&lt;/code&gt;を指定&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[NSString awesomeIcon:FaXXXXXX]&lt;/code&gt;を使って文字を選ぶ&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;FontAwesome-iOS/NSString+FontAwesome.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; [super viewDidLoad];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Do any additional setup after loading the view, typically from a nib.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; self.label.font &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [UIFont fontWithName:&lt;span style="color:#e6db74"&gt;@&amp;#34;FontAwesome&amp;#34;&lt;/span&gt; size:&lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; self.label.text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSString stringWithFormat:&lt;span style="color:#e6db74"&gt;@&amp;#34;%@,%@,%@,%@,%@&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; [NSString awesomeIcon:FaChevronLeft],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; [NSString awesomeIcon:FaWrench],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; [NSString awesomeIcon:FaFacebook],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; [NSString awesomeIcon:FaGift],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; [NSString awesomeIcon:FaPrint]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; ];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;}&lt;span style="color:#960050;background-color:#1e0010"&gt;☄&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/f0e9b726-a96e-454b-9bb1-300a65be0b9e/f075dbf8db557d3d649ed88e881168b2/deep/0/screenshot_325.jpg" alt=""&gt;&lt;/p&gt;</description></item><item><title>Macでメニューバーのアイコンを全て見たいときに使うアプリ</title><link>https://blog.piyo.tech/posts/2014-02-28-204406/</link><pubDate>Fri, 28 Feb 2014 20:42:54 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-28-204406/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c2e6c551-cd65-4dc4-8b1e-5cd72fd4fcfd/9168c60b18b0325adbd41f5e6f881618/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-24-15-34.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;常駐型のアプリをたくさん使っているのでメニューバーに大量のアイコンがあるのですが、他のアプリのメニューの下に隠れてしまって見えていないものがたくさんあります。&lt;/p&gt;
&lt;p&gt;これってすごく不便で、たとえばメモリクリーン系のソフトがクリーンアップしている最中ってMacが重くなるのですが、クリーンアップ中を示す表示がメニューに隠れて見えないせいで重くなっている理由がわからなくて困る、みたいなケースが多発します。&lt;/p&gt;
&lt;p&gt;メニューバーのアイコンが隠れていて困るという問題を少しだけ解決するアプリケーションがあります。それがこれ。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.ortisoft.de/accessmenubarapps/"&gt;AccessMenuBarApps&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;すごくシンプルなアプリケーションで、アプリ名を最短にしてメニューも全くないというものです。このアプリをアクティブにすることでメニューバーを広く使えるというわけです。&lt;/p&gt;
&lt;p&gt;百聞は一見にしかずというやつなので見てもらったほうがいいですね。&lt;/p&gt;
&lt;p&gt;普段はこうなっているメニューバーが、、、&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/53b43930-ae5e-4bdb-a137-30660c3955b9/863074ce953bcd25ea13ddab2085071d/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-24-15-32.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;AccessMenuBarAppsをアクティブにすると、、、&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/8f58fe64-8497-4f37-9053-311e4b12a5aa/0968757e5af5f725eb3a3ab0c237a0de/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-24-15-32.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;こうなります。&lt;/p&gt;
&lt;p&gt;ホットキーでアプリを起動するSnapと組み合わせることでストレスなくメニューバーを確認できます。&lt;/p&gt;</description></item><item><title>Objective-Cでの自前のイベントっぽい仕組み</title><link>https://blog.piyo.tech/posts/2014-02-27-192505/</link><pubDate>Thu, 27 Feb 2014 19:23:55 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-27-192505/</guid><description>&lt;p&gt;非同期でネットワークからデータを取ってくる系の処理が終わったときに&lt;code&gt;UITableView&lt;/code&gt;の&lt;code&gt;reloadData&lt;/code&gt;を呼びたいみたいなとき。どうやってやるのがいいんでしょうか？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;delegate&lt;/li&gt;
&lt;li&gt;observerパターン&lt;/li&gt;
&lt;li&gt;KVO&lt;/li&gt;
&lt;li&gt;ReactiveCocoa&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自前でなんか作ったやつ&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;iOSでよくあるのはdelegateなんでしょうが、非同期処理をするクラスと&lt;code&gt;UITableView&lt;/code&gt;を持ってる&lt;code&gt;UIViewController&lt;/code&gt;が結構遠いのでdelegateにすると引きずり回すことになってあまりよくない気がしました。この方法って片方がもう片方を直接参照できるときじゃないと使いにくいですよね？&lt;/p&gt;
&lt;p&gt;KVOとかReactiveCocoaもそんな感じがしました。&lt;/p&gt;
&lt;h1 id="自前で作ったやつ"&gt;自前で作ったやつ&lt;/h1&gt;
&lt;p&gt;なんかもやもやしたのでとりあえず自分で作ってみました。これ全然ダメじゃんみたいなことはすごくありそうなのでそういうときは誰か突っ込んでくれると嬉しい。&lt;/p&gt;
&lt;h2 id="実装"&gt;実装&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;EventManager&lt;/code&gt;みたいな登録と呼出の口がついているシングルトンを用意しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EventManager&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;NSObject&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;+ (&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;sharedInstance&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;add:&lt;/span&gt;(NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)key &lt;span style="color:#a6e22e"&gt;target:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)target &lt;span style="color:#a6e22e"&gt;selector:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;SEL&lt;/span&gt;)sel;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;call:&lt;/span&gt;(NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)key &lt;span style="color:#a6e22e"&gt;args:&lt;/span&gt;(NSArray &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)args;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;☄&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実装はこうなっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;add:&lt;/span&gt;(NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)key &lt;span style="color:#a6e22e"&gt;target:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)target &lt;span style="color:#a6e22e"&gt;selector:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;SEL&lt;/span&gt;)sel
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; [self.targets setObject:target forKey:key];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; [self.selectors setObject:NSStringFromSelector(sel) forKey:key];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)call:(NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)key args:(NSArray &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)args {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;id&lt;/span&gt; target &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [self.targets valueForKey:key];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;SEL&lt;/span&gt; selector &lt;span style="color:#f92672"&gt;=&lt;/span&gt; NSSelectorFromString([self.selectors valueForKey:key]);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; [target performSelector:selector withObject:args];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;}&lt;span style="color:#960050;background-color:#1e0010"&gt;☄&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;エラー処理とかそういうのは勘弁してください。&lt;/p&gt;
&lt;h2 id="使い方"&gt;使い方&lt;/h2&gt;
&lt;p&gt;冒頭に述べたようなケース、非同期処理が終わったら遠いところにいる&lt;code&gt;UITableView&lt;/code&gt;の再描画ってやつの例です。&lt;/p&gt;
&lt;p&gt;まず登録のほう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; [[EventManager sharedInstance] add:&lt;span style="color:#e6db74"&gt;@&amp;#34;reload&amp;#34;&lt;/span&gt; target:self selector:&lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(reloadTable)];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;reloadTable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; [self.tableView reloadData];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;続いて呼び出し。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;hogeDidFinish:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)sender {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; [[EventManager sharedInstance] call:&lt;span style="color:#e6db74"&gt;@&amp;#34;reload&amp;#34;&lt;/span&gt; args:nil ];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;}&lt;span style="color:#960050;background-color:#1e0010"&gt;☄&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;お互いが直接知らなくても&lt;code&gt;EventManager&lt;/code&gt;と文字列を介してなんとか&lt;code&gt;reloadData&lt;/code&gt;にまで辿り着くことができました。&lt;/p&gt;
&lt;h2 id="mediatorパターン"&gt;Mediatorパターン？&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;EventManager&lt;/code&gt;は直接知らない人同士のやりとりを仲介するためのクラスでした。ってか、これって&lt;code&gt;Mediatorパターン&lt;/code&gt;になるんですかね。&lt;/p&gt;
&lt;p&gt;書いていて気がついたのですがdelegateを使う場合だと仲介者がいれば参照できなくても書けそうですね。今回の場合は文字列を使ったのでよりなんでも有りな書き方ができてしまいそうですが、delegateを使うとなるとプロトコルをいくつも用意することになってイマイチかも。&lt;/p&gt;
&lt;h1 id="notification-centerに気づく"&gt;Notification Centerに気づく&lt;/h1&gt;
&lt;p&gt;↑まで書いたあとで&lt;code&gt;NSNotificationCenter&lt;/code&gt;の存在を知る。いやいや、その名前じゃiPhoneで見るあの通知画面のことかと思っていたよ。ということで使い方を見てみたらさっきの&lt;code&gt;EventManger&lt;/code&gt;とほぼ一緒でした。&lt;/p&gt;
&lt;p&gt;それなら標準のほうがロバストだろうし自作することはありませんね。さようなら&lt;code&gt;EventManager&lt;/code&gt;。。。&lt;/p&gt;</description></item><item><title>ホットキーで指定したアプリを起動・アクティブにできるMacアプリSnap</title><link>https://blog.piyo.tech/posts/2014-02-26-205002/</link><pubDate>Wed, 26 Feb 2014 20:48:51 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-26-205002/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/ee510732-e35f-4930-a465-a44fff6896db/213e1540d15e232526d23794345c0104/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-24-15-26.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;タイトルで全てを語ってしまいました。ホットキーに紐付けておいたアプリを起動したりアクティブにしてくれるMacアプリがあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://itunes.apple.com/jp/app/snap/id418073146?mt=12"&gt;Mac App Store - Snap&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;僕が設定しているのはこの辺り。なお、&lt;code&gt;ctrl&lt;/code&gt;+&lt;code&gt;shift&lt;/code&gt;+&lt;code&gt;command&lt;/code&gt;は全てに共通しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;E&lt;/code&gt;: Evernote&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M&lt;/code&gt;: AirMail&lt;/li&gt;
&lt;li&gt;&lt;code&gt;P&lt;/code&gt;: KeePassX&lt;/li&gt;
&lt;li&gt;&lt;code&gt;W&lt;/code&gt;: Wunderlist&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Q&lt;/code&gt;: GQueues&lt;/li&gt;
&lt;li&gt;&lt;code&gt;A&lt;/code&gt;: AccessMenuBarApps&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;よく使うアプリを指定しておくと便利です。Tab切り替えよりも圧倒的に早いです。&lt;/p&gt;</description></item><item><title>検索されやすいプログラミング系記事のタイトルの付け方</title><link>https://blog.piyo.tech/posts/2014-02-24-190506/</link><pubDate>Mon, 24 Feb 2014 19:04:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-24-190506/</guid><description>&lt;p&gt;ブログ記事のタイトルの付け方に関してはこんなんとかでいろいろ言われていますよね。数字を入れるとか釣りタイトルとかもありますね。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://naifix.com/hatebu-top100-title/"&gt;アクセス爆発！はてブ年間TOP100から学ぶバズるタイトルのつけ方&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;でもこのブログで主に取り上げているようなネタ、例えばObjective−Cで何をどうするみたいなネタの場合、上のようなタイトルの付け方をしてもあまり意味はありません。&lt;/p&gt;
&lt;p&gt;大抵は「◯◯ってどうやるんだろ？」と検索した人が流れてくるようなイメージなので、むしろそういう人に直接的な解がわかりそうだと思わせることが大事っぽいです。当たり前かもしれませんが、釣りタイトルっぽいタイトルよりも内容に直結していたほうがよさそうといったところです。&lt;/p&gt;
&lt;p&gt;このあたりをちょっと参考にしました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://takahirosuzuki.com/2014/0209110003"&gt;過去記事のタイトルを変えるだけで検索流入が倍増した話とそのやり方[SEO]&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="実例"&gt;実例&lt;/h1&gt;
&lt;p&gt;で、実際にいくつかの記事のタイトルを付け替えてみたのでその前後の検索流入を調べてみます。&lt;/p&gt;
&lt;p&gt;例にするのはこの記事。&lt;/p&gt;
&lt;p&gt;変更後のタイトルは**「Unityの開発環境がひどい！脱MonoDevelop。SublimeTextおすすめ」**です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-10-18-215707"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?https://blog.piyo.tech/posts/2013-10-18-215707" alt="Unityの開発環境がひどい！脱MonoDevelop。SublimeTextおすすめ - ぴよログ" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="https://blog.piyo.tech/posts/2013-10-18-215707"&gt;Unityの開発環境がひどい！脱MonoDevelop。SublimeTextおすすめ - ぴよログ&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;2014年2月11日にタイトルを変更して2014年2月24日までに185件のPVがありました。&lt;/p&gt;
&lt;p&gt;ちなみに変更前のタイトルは**「Unity環境がひどすぎたので全体的にSublimeTextにカバーしてもらう」**です。投稿したときからタイトルを変更するまでの期間（2013年10月18日から2014年2月11日まで）のPVは337PVでした。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;&lt;/th&gt;
&lt;th style="text-align: center"&gt;変更前&lt;/th&gt;
&lt;th style="text-align: center"&gt;変更後&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;期間&lt;/td&gt;
&lt;td style="text-align: center"&gt;117日&lt;/td&gt;
&lt;td style="text-align: center"&gt;14日&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;PV&lt;/td&gt;
&lt;td style="text-align: center"&gt;337&lt;/td&gt;
&lt;td style="text-align: center"&gt;185&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;1日あたり&lt;/td&gt;
&lt;td style="text-align: center"&gt;2.88PV/日&lt;/td&gt;
&lt;td style="text-align: center"&gt;13.2PV/日&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;倍増どころじゃねえ！&lt;/p&gt;
&lt;p&gt;Unity環境がひどいという表現よりも、開発環境であるMonoDevelop名指しでDisってSublimeがいいよという表現にしたことが大きかったのかなと。より具体的にしたというところでしょうか。&lt;/p&gt;
&lt;p&gt;この事例を実際に経験できたのでタイトルには少し気をつけるようにしました。まあそれも思いついたときだけなんですけどね。具体的にしようとしすぎて詰め込み感満載なタイトルしか思いつかなくて、さっぱりしたタイトルで妥協するってことも多々。。&lt;/p&gt;</description></item><item><title>iPhoneで左右にサイドバーを簡単に作る</title><link>https://blog.piyo.tech/posts/2014-02-23-200107/</link><pubDate>Sun, 23 Feb 2014 19:59:54 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-23-200107/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/e2a1ae9d-051c-443e-a098-ba70f914c04c/effe5b1390523ed6d24cddec97751dce/deep/0/images20131114133441.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;MMDrawerControllerというライブラリがあります。これを使うと左右のサイドバー（英語ではDrawerと呼ぶことが多いようです。引き出しですね。）を簡単に導入できる上、特別な設定をしなくてもそれなりのクオリティになるとても良いライブラリでうす。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mutualmobile/MMDrawerController"&gt;mutualmobile/MMDrawerController&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ライブラリのプロジェクトと一緒に&lt;code&gt;KitchenSink&lt;/code&gt;というサンプルコードも入っているので、使い方はそちらを参考にするのがいいですね。何しろいろいろやってくれているので一記事では説明しきれないのです。&lt;/p&gt;
&lt;p&gt;サンプルを動かしてみるとこういう風になっているんですねー。左右両サイドにメニューなどを置けるわけです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/cd136160-08c2-415f-9ce6-cb2f5d87cb9c/13cdf181946fb10ee0972aa18bec556e/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-22-22-28.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;動画を撮ってみるとこんな感じ。アニメーションとかもいくつか用意してくれていていい感じです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/aPqvFBVGtQuc-F7j0XnvY-fb56XJWxzu9GpM8P228X-1CmmmPNzQYmRVrSbAgN1XmH3HXw6CrXCRsiZTpRuz9GutNJLYQjovUKR-_nvEOzfYka4CU-w4Tykpo1jieMMOjkNtHhRsPxQQq8CGCiwSb1yf_t2rmGDVaoEhb1HLzuG4iKlA3AydEpATG8xYUkPqzgdkTXIBcUAotS4_9bJtmgGUvIjj4r3c-N_GnhXqQgAAHRk1m_I3166qmh8gF4SbgNPlkLXmoza7_4jwTRXHna1d9HhxZIVIj9vHWMdoCozyNCqafEpUdQS1YEWl-fUZ_0SP2w9z6eabdstzS5fyTsQqM7TTv0l6AzLcIYo4dlIYyDOdBXcSw6o_flKRhhCztGOc9WIRwrP6K5NYosD18gnM_e79FX2cnHfTELtvUirGmILvOMUSfTE2IHNppMYdBEwb1P9au-d1J3E6yBQEKLXedxPzUGiioT4HrSID5DicRAdkG6vhQSI2nnb2SL8Z339HLHiUCyoM6k6RmXW2P1d_ZkiOOxFcDCVPxBcDVfi8E_13Avii37MwX-qQ7u-arHUXPLQIf3XaGZYyOtcR1tbbtXNMf_103BHO9Ki-GhHzIhpklSgYao39P0Q5XF9Fo32DCVMz-c7yw40voQqp2KA52fTkykI5Bw=w182-h324-no" alt=""&gt;&lt;/p&gt;</description></item><item><title>NSLogデバッグのときに便利なCGRect→NSStringの変換</title><link>https://blog.piyo.tech/posts/2014-02-22-221010/</link><pubDate>Sat, 22 Feb 2014 22:08:51 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-22-221010/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b670ac8d-c132-4a06-82c4-d5edd2c3742a/6735c780dda29323f36bc69e1860e31a/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-20-10-15.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;NSLogデバッグの良し悪しは置いておくとして、CGRectとかNSDictionaryとかの値をちょっと確認するのにNSLog使ったりしますよね。CGRectの値を確認するときに一生懸命&lt;code&gt;NSLog(&amp;quot;%f&amp;quot;, rect.size.width)&lt;/code&gt;みたいにやってたりマクロ書いたりしていたんですが、もっといい方法があるのを最近知りました。なんてこったい状態。&lt;/p&gt;
&lt;p&gt;例えばCGRectでは&lt;code&gt;NSStringFromCGRect&lt;/code&gt;というメソッドがありまして、これを使うとこんな風に書けるわけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;CGRect rect &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CGRectMake(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;%@&amp;#34;&lt;/span&gt;, NSStringFromCGRect(rect));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// {{0, 0}, {200, 100}} と出力される
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;めちゃ楽ですね。これまでの時間返せっていう。&lt;/p&gt;
&lt;p&gt;調べてみたらNSStringFromXXXXX系はこれだけありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NSStringFromCGPoint&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NSStringFromCGSize&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NSStringFromCGRect&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NSStringFromCGAffineTransform&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NSStringFromUIEdgeInsets&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NSStringFromUIOffset&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;じゃあDictionaryやArrayはどうすんの？っていうと、こちらも一気に全ダンプできます。どちらも&lt;code&gt;description&lt;/code&gt;を呼び出すと&lt;code&gt;NSString*&lt;/code&gt;に変換してくれるようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;NSArray&lt;span style="color:#f92672"&gt;*&lt;/span&gt; array &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;@[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;@&amp;#34;hoge&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;@&amp;#34;fuga&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;@&amp;#34;foobar&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;@[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;@&amp;#34;hogehoge&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;@&amp;#34;aaaaaa&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;]]&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;%@&amp;#34;&lt;/span&gt;, [array description]);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;NSDictionary&lt;span style="color:#f92672"&gt;*&lt;/span&gt; dic &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;@{&lt;/span&gt;&lt;span style="color:#e6db74"&gt;@&amp;#34;key1&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;@&amp;#34;value1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;key2&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;@&amp;#34;value2&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;key3&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;@{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;innerkey1&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;@&amp;#34;innervalue1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;innerkey2&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;@&amp;#34;innervalue2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;}&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;%@&amp;#34;&lt;/span&gt;, [dic description]);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// array
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; hoge,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; fuga,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; foobar,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; hogehoge,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; aaaaaa
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// dic
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; key1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; value1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; key2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; value2;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; key3 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; innerkey1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; innervalue1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; innerkey2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; innervalue2;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="文字列からcgrectへの変換"&gt;文字列からCGRectへの変換&lt;/h1&gt;
&lt;p&gt;逆もできます。&lt;/p&gt;
&lt;p&gt;先ほどの&lt;code&gt;NSStringFromCGRect&lt;/code&gt;で変換された文字列と同じ形式の文字列を用意して、&lt;code&gt;CGRectFromNSString&lt;/code&gt;を使えばCGRectができます！&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;CGRect rect2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CGRectFromString(&lt;span style="color:#e6db74"&gt;@&amp;#34;{{0, 0}, {320, 568}}&amp;#34;&lt;/span&gt;);&lt;span style="color:#960050;background-color:#1e0010"&gt;☄&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こちらも同じ数ターン用意されていました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CGPointFromString&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CGSizeFromString&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CGRectFromString&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CGAffineTransformFromString&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UIEdgeInsetsFromString&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UIOffsetFromString&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="おわり"&gt;おわり&lt;/h1&gt;
&lt;p&gt;こいつらを駆使して楽しましょう！&lt;/p&gt;</description></item><item><title>Objective-Cでenumを定義する</title><link>https://blog.piyo.tech/posts/2014-02-21-195704/</link><pubDate>Fri, 21 Feb 2014 19:55:56 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-21-195704/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b05d864b-c69f-4972-b665-31dc4cd8257d/7593851a3b1e75491c1417d0bc5f7561/deep/0/enum.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;使う機会が少なくていつも忘れてしまうし、どの書き方がいいのかよくわからなかったのでメモしとく！&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MMDrawerController&lt;/code&gt;のサンプル見ててみつけました。こんな感じで書けるみたい↓↓&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NS_ENUM&lt;/span&gt;(NSInteger, MMDrawerAnimationType){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; MMDrawerAnimationTypeNone,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; MMDrawerAnimationTypeSlide,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; MMDrawerAnimationTypeSlideAndScale,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; MMDrawerAnimationTypeSwingingDoor,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; MMDrawerAnimationTypeParallax,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>ポモドーロ用Chrome拡張「Strict Workflow」がいい感じ</title><link>https://blog.piyo.tech/posts/2014-02-20-204705/</link><pubDate>Thu, 20 Feb 2014 20:45:53 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-20-204705/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/2f23d372-7c33-4f82-b9d5-f53bc0c075ae/9e93e0a8318736e7c69d96ebcd1b62b1/deep/0/wudz1263448561656.jpg" alt=""&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;集中して仕事をこなすために、25分毎に時間を区切って仕事をする時間管理術。Francesco Cirillo氏が1992年、自身の勉強効率を上げるために考案した。&lt;/p&gt;
&lt;p&gt;#手順&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;25分を1ポモドーロとし、やるべきタスクを1ポモドーロ刻み（25分毎）に分ける。&lt;/li&gt;
&lt;li&gt;25分間は、他の事は一切やらず、タスクに集中する&lt;/li&gt;
&lt;li&gt;25分経てば、5分間の休憩を入れる&lt;/li&gt;
&lt;li&gt;4ポモドーロ毎（2時間毎）に30分程の長い休憩をとる&lt;/li&gt;
&lt;li&gt;後は上記を繰り返す&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://d.hatena.ne.jp/keyword/%A5%DD%A5%E2%A5%C9%A1%BC%A5%ED%A5%C6%A5%AF%A5%CB%A5%C3%A5%AF"&gt;ポモドーロテクニックとは - はてなキーワード&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ポモドーロはイタリア語でトマトのことで、使ったタイマーがトマトの形だったからという由来だった気がします。このテクニックは妙に意識が高まった1年前ほど前にしばらく実践して、なかなかに効果がありそうだということがわかっていましたが、どうも時間をはかるのが面倒くさくていつのまにかやらなくなってしまいました。&lt;/p&gt;
&lt;h1 id="昔使っていた方法"&gt;昔使っていた方法&lt;/h1&gt;
&lt;p&gt;時間を測る方法は2つ試してたんですが、どちらも面倒で。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Due (iPhone)&lt;/li&gt;
&lt;li&gt;focus booster (Mac)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;まずiPhoneアプリのDue、これはリマインダーとして使っているアプリなんですが、タイマー機能も持っています。25分と5分のタイマーを作っておいて適宜起動すればポモドーロテクニックに使えるのですが、、、&lt;/p&gt;
&lt;p&gt;基本Macで仕事をするのでいちいちiPhoneを触らないといけないという点がダメでした。つまりiPhoneのポモドーロ系アプリは全部だめ。&lt;/p&gt;
&lt;p&gt;次にMacのfocus boosterというアプリ。無料で使えるものをいくつか探した中で一番マシだったのがこれでした。起動するとこういうタイマーが出てきて順次25分と5分を切り替えながら時間を知らせてくれます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/31ed983e-5d6b-4910-bb37-6ea83de7e9e8/b6b1a7cb2b680f76cf63de6606a6eebb/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-19-8-34.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;欠点はAdobeAIRのソフトであることとなんとなく操作しづらいということ、だと思っていたのですが、、、これから紹介する「Strict Workflow」を使ってからわかったのは、通知がでなかったことが原因の1つだったかなと。&lt;/p&gt;
&lt;h1 id="strict-workflow"&gt;Strict Workflow&lt;/h1&gt;
&lt;p&gt;「Strict Workflow」というChrome拡張をいれました。&lt;/p&gt;
&lt;p&gt;これね。&lt;a href="https://chrome.google.com/webstore/detail/strict-workflow/cgmnfnmlficgeijcalkgnnkigkefkbhd"&gt;Chrome ウェブストア - Strict Workflow&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="通知が出る"&gt;通知が出る&lt;/h2&gt;
&lt;p&gt;これを入れるとChromeのバーにトマトのアイコンが出ます。クリックすると25分スタート、終わるとブラウザ通知が出て「次は休憩だよー（意訳）」と教えてくれます。もう1回クリックで5分がスタート、終わるとまた通知が出てくれます。この繰り返しです。&lt;/p&gt;
&lt;p&gt;ブラウザが隠れていても通知が出て、そこを触るとブラウザがアクティブになるという快適仕様。focus boosterはDockアイコンがぴょんぴょんなるのが鬱陶しいんですよ。でもぴょんぴょんは切りたくないし。&lt;/p&gt;
&lt;p&gt;通知機能がストレスを減らしてくれます。&lt;/p&gt;
&lt;h2 id="ウェブサイトをブロックできる"&gt;ウェブサイトをブロックできる&lt;/h2&gt;
&lt;p&gt;ウェブサイトをブロックする拡張ありますよね。朝9時から夕方5時は指定したサイトにアクセスできないようにする、みたいな。でもこれ入れるとちょっと休憩したいときに面倒だったりします。&lt;/p&gt;
&lt;p&gt;「Strict Workflow」では25分の集中フェーズのみブロック機能が働くのでまさにちょうど良いのです。&lt;/p&gt;</description></item><item><title>Mac版Evernoteにチェックボックス付きのノートを自動生成する</title><link>https://blog.piyo.tech/posts/2014-02-19-212516/</link><pubDate>Wed, 19 Feb 2014 21:25:16 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-19-212516/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/ae55bbfb-a57a-4246-a78f-6615ab4bc10f/f2970103ddb194027a83b3e8657dc5fa/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-18-8-57.png" alt=""&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Evernoteのチェックボックスを使う&lt;/li&gt;
&lt;li&gt;定期的に同じ形式のノートを作る&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こういった使い方をしている人はたくさんいると思います。前者は買い物リスト、後者は日記が定番でしょうか。&lt;/p&gt;
&lt;p&gt;チェックボックスを使うだけならEvernoteのエディタでチェックボックスを置くだけでいいですし、同じ形式のノートを作るならDashなどのスにペットアプリを使えば簡単です。&lt;/p&gt;
&lt;p&gt;ところがこれらを組み合わせようとすると急に大変になります。毎日チェックボックス付きの日記を書きたい、というような場合です。まあこれは僕の話なんですが。&lt;/p&gt;
&lt;p&gt;そもそもチェックボックス付きのスニペットというのは作ることができません。Evernoteのチェックボックスをテキストエディターにコピーすると&lt;code&gt;[]&lt;/code&gt;となりますが、その逆は成り立たないのでテキスト貼り付けでチェックボックスを置くことはできないのです。&lt;/p&gt;
&lt;p&gt;「テンプレート用のノートを一個作っておいてそれをコピーして毎日使えばいいじゃん」と思うのがほとんどの人ですが、極度の効率厨である僕にとってはそんなことやってられません。コマンド一発でその日の日付入りのノートを作って欲しいのです。&lt;/p&gt;
&lt;p&gt;前置きが長くなりました。結論を言えば、enmlとAutomatorとAppleScriptを使います。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/58c9c91f-d44b-4afb-a930-5bf2b08ae67b/e690865d6de1f2459c7d257b94cffc37/deep/0/%E3%83%97%E3%83%AC%E3%82%BC%E3%83%B3%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B31.png" alt=""&gt;&lt;/p&gt;
&lt;h1 id="enmlってなに"&gt;enmlってなに？&lt;/h1&gt;
&lt;p&gt;Evernoteのノートエクスポート機能を使うとXML形式で出力されるはずです。&lt;/p&gt;
&lt;p&gt;例えばこんなノート。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7cb8b8ee-c41d-4084-a55f-67dfd62ea318/b1e5efcb7d8e8159044573fd927bb595/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-18-10-02.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;エクスポートするとこのように出力されます。これがenmlで、チェックボックスなどのEvernote独自の要素もタグを使って表現できています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;!DOCTYPE en-export SYSTEM &amp;#34;http://xml.evernote.com/pub/evernote-export3.dtd&amp;#34;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;en-export&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;export-date=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;20140218T010326Z&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;application=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Evernote&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;version=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Evernote Mac 5.5.0 (402474)&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;note&amp;gt;&amp;lt;title&amp;gt;&lt;/span&gt;タイトルタイトル&lt;span style="color:#f92672"&gt;&amp;lt;/title&amp;gt;&amp;lt;content&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;![CDATA[&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34; standalone=&amp;#34;no&amp;#34;?&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;!DOCTYPE en-note SYSTEM &amp;#34;http://xml.evernote.com/pub/enml2.dtd&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;en-note style=&amp;#34;word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;b&amp;gt;太字&amp;lt;br/&amp;gt;&amp;lt;/b&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;div&amp;gt;&amp;lt;br/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;div&amp;gt;&amp;lt;en-todo/&amp;gt;ほげ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;div&amp;gt;&amp;lt;en-todo/&amp;gt;ふが&amp;lt;br/&amp;gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;div&amp;gt;&amp;lt;en-todo/&amp;gt;foo&amp;lt;br/&amp;gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;div&amp;gt;&amp;lt;en-todo/&amp;gt;bar&amp;lt;br/&amp;gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;div&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;/en-note&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;]]&amp;gt;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/content&amp;gt;&amp;lt;created&amp;gt;&lt;/span&gt;20140218T010211Z&lt;span style="color:#f92672"&gt;&amp;lt;/created&amp;gt;&amp;lt;updated&amp;gt;&lt;/span&gt;20140218T010237Z&lt;span style="color:#f92672"&gt;&amp;lt;/updated&amp;gt;&amp;lt;note-attributes&amp;gt;&amp;lt;author&amp;gt;&lt;/span&gt;author&lt;span style="color:#f92672"&gt;&amp;lt;/author&amp;gt;&amp;lt;reminder-order&amp;gt;&lt;/span&gt;0&lt;span style="color:#f92672"&gt;&amp;lt;/reminder-order&amp;gt;&amp;lt;/note-attributes&amp;gt;&amp;lt;/note&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/en-export&amp;gt;&lt;/span&gt;☄
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="automatorの全体の流れ"&gt;Automatorの全体の流れ&lt;/h1&gt;
&lt;p&gt;この2つのアクションを使います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;シェルスクリプトを実行&lt;/li&gt;
&lt;li&gt;AppleScriptを実行&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;シェルスクリプトを実行&lt;/strong&gt;でノートのタイトルに使う日付の文字列、ノートの本文にするenml形式の文字列を出力し、&lt;strong&gt;AppleScriptを実行&lt;/strong&gt;でEvernoteにノートを作るという流れです。&lt;/p&gt;
&lt;h2 id="applescriptでevernoteにノートを作る"&gt;AppleScriptでEvernoteにノートを作る&lt;/h2&gt;
&lt;p&gt;まずは後半のノートを作るところから紹介します。コードの全体はこれ&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-applescript" data-lang="applescript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;on&lt;/span&gt; run {input, parameters}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; ttl &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; item &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; input
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; body &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; item &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; input
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;tell&lt;/span&gt; application &lt;span style="color:#e6db74"&gt;&amp;#34;Evernote&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; notebook1 &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; notebook &lt;span style="color:#e6db74"&gt;&amp;#34;notebookname&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; note1 &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; create note &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt; ttl &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; enml body notebook notebook1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; open note &lt;span style="color:#a6e22e"&gt;window&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; note1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;tell&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt; run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;順番に解説していきます。&lt;/p&gt;
&lt;p&gt;最初の2行で標準入力の1行目と2行目を&lt;code&gt;ttl（タイトル）&lt;/code&gt;と&lt;code&gt;body（本文）&lt;/code&gt;に割り当てています。&lt;code&gt;title&lt;/code&gt;がEvernote側で使われているので苦肉の策で&lt;code&gt;ttl&lt;/code&gt;としています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-applescript" data-lang="applescript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; ttl &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; item &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; input
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; body &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; item &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; input
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次のブロックでEvernoteに対して命令を行うということを示しています。ブロック内に書いたコードはEvernoteに対して実行されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-applescript" data-lang="applescript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;tell&lt;/span&gt; application &lt;span style="color:#e6db74"&gt;&amp;#34;Evernote&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;tell&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;☄&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際にノートを作るところ。ノートブックを指定し、&lt;code&gt;ttl&lt;/code&gt;と&lt;code&gt;body&lt;/code&gt;を持つノートを作ります。最後に作ったノートを開いておしまい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-applescript" data-lang="applescript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; notebook1 &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; notebook &lt;span style="color:#e6db74"&gt;&amp;#34;notebookname&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; note1 &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; create note &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt; ttl &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; enml body notebook notebook1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;open note &lt;span style="color:#a6e22e"&gt;window&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; note1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="本文と日付を出力するスクリプト"&gt;本文と日付を出力するスクリプト&lt;/h2&gt;
&lt;p&gt;AppleScriptに渡すタイトルと本文を出力スクリプトを書きます。なんでもいいですが、ぼくは慣れているのでRubyを使いました。本文には先ほど紹介したenmlの&lt;code&gt;&amp;lt;en-note&amp;gt;&amp;lt;/en-note&amp;gt;&lt;/code&gt;タグの内部の文字列を使います。&lt;/p&gt;
&lt;p&gt;やっていることは日付の文字列生成・出力と本文の出力です。本文は本当は外部ファイルとかにしたほうがいいですね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;wdays &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;日&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;月&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;火&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;水&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;木&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;金&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;土&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;day &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Time&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;now
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;wday &lt;span style="color:#f92672"&gt;=&lt;/span&gt; wdays&lt;span style="color:#f92672"&gt;[&lt;/span&gt;day&lt;span style="color:#f92672"&gt;.&lt;/span&gt;wday&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;date_string &lt;span style="color:#f92672"&gt;=&lt;/span&gt; day&lt;span style="color:#f92672"&gt;.&lt;/span&gt;strftime(&lt;span style="color:#e6db74"&gt;&amp;#34;%Y/%m/%d（&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;wday&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;）&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;body &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;lt;&amp;lt;-EOS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;b&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;太字&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;br&lt;span style="color:#f92672"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/b&amp;gt;&amp;lt;div&amp;gt;&amp;lt;br/&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;&lt;/span&gt;div&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;&lt;/span&gt;en&lt;span style="color:#f92672"&gt;-&lt;/span&gt;todo&lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;ほげ&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;div&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;&lt;/span&gt;en&lt;span style="color:#f92672"&gt;-&lt;/span&gt;todo&lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;ふが&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;br&lt;span style="color:#f92672"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;en-todo/&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;foo&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;br&lt;span style="color:#f92672"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;en-todo/&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;bar&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;br&lt;span style="color:#f92672"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;br/&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/div&amp;gt;&amp;lt;/&lt;/span&gt;div&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;EOS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;puts &amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;date_string&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;の日記&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;puts body
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このスクリプトをAutomatorの1つ目のアクション、&lt;code&gt;シェルスクリプトを実行&lt;/code&gt;で実行します。&lt;/p&gt;
&lt;p&gt;シェルを&lt;code&gt;/usr/bin/ruby&lt;/code&gt;にして直接書いてもいいし、&lt;code&gt;/bin/sh&lt;/code&gt;にしておいて&lt;code&gt;/path/to/ruby /path/to/script.rb&lt;/code&gt;などとしてあげても大丈夫です。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7ff72366-799d-475a-9171-139c5d00d2e2/52a82964223a961102ab30ad1b0ee0c7/deep/0/OtherViews-%E3%81%A8-nk.app.png" alt=""&gt;&lt;/p&gt;
&lt;h1 id="仕上げアプリケーションにする"&gt;仕上げ：アプリケーションにする&lt;/h1&gt;
&lt;p&gt;Automatorで作ったワークフローをアプリケーション形式に変換し、アプリケーションディレクトリに置いておきましょう。そうするとSpotlightなりAlfredなりでコマンド一発で起動でき、Evernote新規作成されたノートのウィンドウが開いてすぐに書き始められます。&lt;/p&gt;
&lt;h1 id="さいごにコメント"&gt;さいごにコメント&lt;/h1&gt;
&lt;p&gt;AppleScript書いたけど相当だるいです。アプリケーションを操作するためには使わざるを得ないんだけど、別の手段も用意されていると嬉しい。URLスキームでいろいろできるとかね。&lt;/p&gt;</description></item><item><title>MacやWindowsでの行動ログ・作業ログをトラッキングするRescueTime</title><link>https://blog.piyo.tech/posts/2014-02-18-185002/</link><pubDate>Tue, 18 Feb 2014 18:49:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-18-185002/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/cb4ba9cb-f2e4-429d-922a-f9b5fa7dfe4b/f2c6d52ae1622322b579e89b8787f43f/deep/0/images-1.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Rescue Timeというサービスを利用するとMacでどんなウィンドウを開いていてどんなページを見ていたのか、その時間はどのぐらいだったのかを記録できます。&lt;/p&gt;
&lt;p&gt;MacやWindows、Linux、果てはAndroidまで対応しているようです。僕はMacで使っています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.rescuetime.com/"&gt;RescueTime : Time management software for staying productive and happy in the modern workplace&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;RescueTimeにサインアップしてMacにクライアントソフトをインストールします。このクライアントソフトが常駐しながらアクティブなアプリケーションの情報などをRescueTimeのサーバーに送っているようです。&lt;/p&gt;
&lt;h2 id="使うとどうなるか"&gt;使うとどうなるか&lt;/h2&gt;
&lt;p&gt;RescueTimeのダッシュボードはいくつかのチャートからなります。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/42402322-5fce-49ac-ba19-505d41fe57df/4d86af6c08f1152e2fbb473de19d8735/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-16-13-44.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;これは2014年2月の僕のトラッキング結果です。これを見ると70%の時間は生産的な活動に使えているらしいですね。実に生産的です。&lt;/p&gt;
&lt;p&gt;このように生産的な活動と非生産的な活動の割合を示してくれる上に、RescueTimeのクライアントをインストール済みのマシンに何時間ログインしているかを示してくれます。僕の場合でいうとMacbookAirの前に何時間いるかという意味になります。&lt;/p&gt;
&lt;p&gt;仕事の割合や仕事をしている時間などがわかるようになっているわけです。&lt;/p&gt;
&lt;h2 id="行動のカテゴライズ"&gt;行動のカテゴライズ&lt;/h2&gt;
&lt;p&gt;サインアップ後、自分にとっての生産的な活動、非生産的な活動をいくつかピックアップして分類します（登録したのが昔なのでその画面のキャプチャがありません…）。&lt;/p&gt;
&lt;p&gt;僕の場合、生産的な活動は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ソフトウェア開発&lt;/li&gt;
&lt;li&gt;Googleでの調べ物&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などで、非生産的な活動は、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SNS系のサービス・アプリの閲覧&lt;/li&gt;
&lt;li&gt;動画の閲覧&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などです。&lt;/p&gt;
&lt;p&gt;これらの設定は最初に大まかに行いますが、個別に設定を変更できます。&lt;/p&gt;
&lt;p&gt;基本的に全てのアプリケーション、全てのWebサイトがトラッキングされていて、RescueTimeの管理画面で見ることができるようになっています。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/cdc9ee9a-4dea-4d24-b732-27def06edb12/0ad8349e172d2983b93b5ee6073e1686/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-16-13-51.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;見ていくと、行動に対して&lt;code&gt;VERY PRODUCTIVE&lt;/code&gt;やら&lt;code&gt;NEWTRAL&lt;/code&gt;、&lt;code&gt;VERY DISTRACTING&lt;/code&gt;などが設定されていると思います。例えばFacebookは&lt;code&gt;VERY DISTRACTING&lt;/code&gt;、Xcodeは&lt;code&gt;VERY PRODUCTIVE&lt;/code&gt;みたいな。&lt;/p&gt;
&lt;p&gt;この分類をきちんと設定しておくことによって、より正確な生産性を測定できるわけです。&lt;/p&gt;
&lt;h2 id="ゴールの設定"&gt;ゴールの設定&lt;/h2&gt;
&lt;p&gt;RescueTimeにはゴールという概念があります。目標を設定しておいて、クリアしている日をカレンダーで見ることができたり、プレミアム版ではアラートを出したりできるようです。&lt;/p&gt;
&lt;p&gt;例えば僕の場合、ログイン時の設定で勝手にこんなゴールが作られていました。&lt;/p&gt;
&lt;p&gt;「毎日2時間はソフトウェア開発を行う」&lt;/p&gt;
&lt;p&gt;それに対する結果は…&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/48a74984-2893-42f9-a2c7-8794d9c6e220/03aad2355daab493b3da355ed23f567e/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-16-13-56.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;対象となった日のうち75%程度だということらしく、2時間すら開発できていない日があるということがわかって驚きました。&lt;/p&gt;
&lt;p&gt;他にも、非生産的な活動を2時間以内に抑えるなどの使い方ができます。そういう点でアラート機能は気になりますね。「今日は遊びすぎ」という通知を出してくれるなら、ちょっと気が引き締まるかも。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;RescueTimeを入れておくと日々の行動を整理できる&lt;/li&gt;
&lt;li&gt;入れてほうっておくだけでいいので楽&lt;/li&gt;
&lt;li&gt;ゴールを使うと結果を見やすい&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Rubyでcronのような定期実行を実現するclockwork</title><link>https://blog.piyo.tech/posts/2014-02-17-222721/</link><pubDate>Mon, 17 Feb 2014 22:27:21 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-17-222721/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/df3fb317-7efa-4614-9751-f2955f6e137b/96dcdb3b053039d28322e412caaa24de/deep/0/imgres-2.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;先日の記事でもちょろっと紹介しましたが、RSSリーダーを開発した際にフィード更新ジョブを定期的に発行するためにclockworkというgemを使用しました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-02-15-202607"&gt;RSSリーダーの記事更新のバックグラウンドジョブ概要 - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="単独で使う"&gt;単独で使う&lt;/h2&gt;
&lt;p&gt;まずはRuby単独で使う方法です。ローカルマシンで定期的にスクリプトを動かしたいときなどに使えます（そんなときあるか！？）。&lt;/p&gt;
&lt;p&gt;まずgemを導入します。普通に&lt;code&gt;gem install&lt;/code&gt;でいけます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ gem install clockwork
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次にコンフィグファイル的なものを書きます。例えば&lt;code&gt;clock.rb&lt;/code&gt;というような名前で作るとします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;clockwork&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;module&lt;/span&gt; Clockwork
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;one_minute&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; p &lt;span style="color:#e6db74"&gt;&amp;#34;minutely job&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;one_hour&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; p &lt;span style="color:#e6db74"&gt;&amp;#34;hourly job&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; handler &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;job&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;send(job&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_sym)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; every(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;minute, &lt;span style="color:#e6db74"&gt;&amp;#39;one_minute&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; every(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hour, &lt;span style="color:#e6db74"&gt;&amp;#39;one_hour&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最後の2行で1分ごとのジョブと1時間ごとのジョブを設定しています。そして&lt;code&gt;handler&lt;/code&gt;に処理記述します。この例ではジョブ名と同じメソッドを定義しておいて、&lt;code&gt;send&lt;/code&gt;によってそちらを呼ぶようにしています。&lt;/p&gt;
&lt;h3 id="フォアグラウンド実行"&gt;フォアグラウンド実行&lt;/h3&gt;
&lt;p&gt;フォアグラウンド実行を行うときは次のように実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;$ clockwork clock.rb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;I, &lt;span style="color:#f92672"&gt;[&lt;/span&gt;2014-02-16T11:11:17.128897 &lt;span style="color:#75715e"&gt;#97926] INFO -- : Starting clock for 2 events: [ one_minute one_hour ]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;I, &lt;span style="color:#f92672"&gt;[&lt;/span&gt;2014-02-16T11:11:17.129034 &lt;span style="color:#75715e"&gt;#97926] INFO -- : Triggering &amp;#39;one_minute&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;minutely job&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;I, &lt;span style="color:#f92672"&gt;[&lt;/span&gt;2014-02-16T11:11:17.129107 &lt;span style="color:#75715e"&gt;#97926] INFO -- : Triggering &amp;#39;one_hour&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hourly job&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;I, &lt;span style="color:#f92672"&gt;[&lt;/span&gt;2014-02-16T11:12:17.182378 &lt;span style="color:#75715e"&gt;#97926] INFO -- : Triggering &amp;#39;one_minute&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;minutely job&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;I, &lt;span style="color:#f92672"&gt;[&lt;/span&gt;2014-02-16T11:13:17.231925 &lt;span style="color:#75715e"&gt;#97926] INFO -- : Triggering &amp;#39;one_minute&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;minutely job&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実行すると同時に1時間毎のジョブと1分ごとのジョブが実行され、それ以降は指定した間隔でジョブが動いていきます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;at&lt;/code&gt;オプションを使うことでcronのように◯時XX分に実行する、というような指定も可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;every(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hour, &lt;span style="color:#e6db74"&gt;&amp;#39;hourly&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:at&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;**:30&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="バックグラウンド実行デーモン"&gt;バックグラウンド実行（デーモン）&lt;/h3&gt;
&lt;p&gt;定期実行という機能の特性を考えるとバックグラウンドで実行したいケースがほとんどだと思います。そのためには&lt;code&gt;clockwork&lt;/code&gt;と一緒についてくる&lt;code&gt;clockworkd&lt;/code&gt;を使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ clockworkd -c clock.rb start --log
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;-c&lt;/code&gt;はコンフィグファイルを指定というようなニュアンスだと思われます。&lt;code&gt;clock.rb&lt;/code&gt;ファイルを指定して&lt;code&gt;start&lt;/code&gt;すればバックグラウンドで起動します。&lt;code&gt;--log&lt;/code&gt;オプションを付けることにより、フォアグラウンド実行のとき標準出力されていたログがファイルに出るようになります。&lt;/p&gt;
&lt;h2 id="railsと使う"&gt;Railsと使う&lt;/h2&gt;
&lt;p&gt;アプリケーションと一緒に使うことでより実用的になります。Railsの場合は&lt;code&gt;clockwork&lt;/code&gt;をrequireしたあとでRailsの環境をrequireすることでRailsのコードを使えるようになります。&lt;/p&gt;
&lt;p&gt;Railsの環境を読み込むには&lt;code&gt;config/boot&lt;/code&gt;と&lt;code&gt;config/environment&lt;/code&gt;をrequireします。requireする際のパスに注意して書く必要があるのですが、clockworkのコンフィグファイルが&lt;code&gt;boot&lt;/code&gt;などと同じく&lt;code&gt;config&lt;/code&gt;にある場合は、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;expand_path(&lt;span style="color:#e6db74"&gt;&amp;#39;../boot&amp;#39;&lt;/span&gt;, __FILE__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;expand_path(&lt;span style="color:#e6db74"&gt;&amp;#39;../environment&amp;#39;&lt;/span&gt;, __FILE__)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;などと書きます。&lt;/p&gt;
&lt;p&gt;これをやっておくことでRailsのモデルなどにアクセスできるようになって、より実用的な使い方をできるようになりますね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;clockwork&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;expand_path(&lt;span style="color:#e6db74"&gt;&amp;#39;../boot&amp;#39;&lt;/span&gt;, __FILE__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;expand_path(&lt;span style="color:#e6db74"&gt;&amp;#39;../environment&amp;#39;&lt;/span&gt;, __FILE__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;module&lt;/span&gt; Clockwork
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; handler &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;job&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; p &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;job&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;: user count =&amp;gt; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;User&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;count&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; every(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;minute, &lt;span style="color:#e6db74"&gt;&amp;#39;minute&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>RSSリーダーの記事更新のバックグラウンドジョブ概要</title><link>https://blog.piyo.tech/posts/2014-02-15-202607/</link><pubDate>Sat, 15 Feb 2014 20:25:07 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-15-202607/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/99f21986-8f73-4e57-a6dd-63d13b62208b/bf94f36ad9448fa25c477f5f9bcca1da/deep/0/imgres.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;RSSリーダーを作ったときのことをまとめておくシリーズ。&lt;/p&gt;
&lt;p&gt;これまでの記事はこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/category/RSS%E3%83%AA%E3%83%BC%E3%83%80%E3%83%BC"&gt;RSSリーダー - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;僕が知る限り全てのRSSリーダーは登録フィードをバックグラウンドで更新し記事を追加します。RSSリーダーのユーザー側、システム側から見てみます。&lt;/p&gt;
&lt;h2 id="ユーザー視点"&gt;ユーザー視点&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;RSSリーダーにブログやニュースサイトのフィードを購読&lt;/li&gt;
&lt;li&gt;これまでの記事を閲覧できるようになる&lt;/li&gt;
&lt;li&gt;サイトが更新されたら新しい記事を閲覧可能になる&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="rssリーダー視点"&gt;RSSリーダー視点&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;ユーザーがRSSフィードを購読する&lt;/li&gt;
&lt;li&gt;すでに誰かが購読済みのフィードかどうかを調べる
&lt;ul&gt;
&lt;li&gt;誰かが購読済み→フィードの購読者にこのユーザーを加える&lt;/li&gt;
&lt;li&gt;最初の購読者→フィードデータを作成し記事をクローリングする、また購読者にこのユーザーを加える&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;取得済みの記事をユーザーに見せる&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;フィード配信元に更新があるかどうか定期的にクローリング&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;更新があれば新たな記事を追加する&lt;/li&gt;
&lt;li&gt;（更新後に見たユーザーは新しい記事を読めるようになっている）&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="定期的なクローリング"&gt;定期的なクローリング&lt;/h2&gt;
&lt;p&gt;両者を比べてみるたときに一番違うのは、強調表示した**「フィード配信元に更新があるかどうか定期的にクローリング」**というところです。もっと言い換えれば、更新があるかどうか見に行くという行為をユーザーの代わりに行ってくれるのがRSSリーダーの価値であると言えます。&lt;/p&gt;
&lt;p&gt;そして、システムからすればもっとも負荷の高い部分のうちの1つとも言えます（もう一つはクロールした記事のデータ量。日に日に増えていくので、、、）。&lt;/p&gt;
&lt;p&gt;ではこのクローリングをどのように実施したかを紹介していきます。&lt;/p&gt;
&lt;h3 id="rails--resque"&gt;Rails &amp;amp; Resque&lt;/h3&gt;
&lt;p&gt;クローリングはユーザーの操作がないときでも定期的に動かす必要があります。したがってアプリケーションサーバーやWebサーバーは関係ありません。もっとも簡単に実行するには、定期的にスクリプトが動いてデータベースを更新するようなものでもできてしまいます。&lt;/p&gt;
&lt;p&gt;とはいえ、単なるジョブ用スクリプトを使うとアプリケーションと同じモデルを利用するのが困難でスクリプト自体が大変複雑になることは間違いないので、もうちょっとマシな方法を使います。&lt;/p&gt;
&lt;p&gt;RSSリーダーはRuby on Railsで作り、バックグラウンドジョブにはResqueを使用しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ruby on Rails&lt;/li&gt;
&lt;li&gt;Resque&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Resqueに関してはiQONを運営するVASILYさんの記事が詳しかったのでこちらを参考にいろいろ実装しました。超助かりました。&lt;/p&gt;
&lt;div class="intro-article-wrapper" style="width: 100%; overflow: auto;"&gt;&lt;a class="intro-article-img" href="http://tech.vasily.jp/2013/02/iqon_backend_resque/" target="_blank" style="float:left;" rel="nofollow"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://tech.vasily.jp/2013/02/iqon_backend_resque/" align="left" width="150" height="130" alt="iQONのバックエンドの非同期処理について(具体的な実装編) | VASILY DEVELOPERS BLOG"&gt;&lt;/a&gt;&lt;a class="intro-article-title" href="http://tech.vasily.jp/2013/02/iqon_backend_resque/" target="_blank" style="font-size:110%;" rel="nofollow"&gt;iQONのバックエンドの非同期処理について(具体的な実装編) | VASILY DEVELOPERS BLOG&lt;/a&gt; &lt;img src="https://b.hatena.ne.jp/entry/image/http://tech.vasily.jp/2013/02/iqon_backend_resque/" style="opacity:0.8;"&gt;&lt;span style="clear: both;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;Resqueのバックグラウンドジョブ用のワーカーは定期的にジョブキューを監視しつづけてくれます。暇なワーカーがいる限り、ジョブキューにジョブを放り投げるとすぐにジョブを実行してくれるようになっています。つまりワーカーを多数用意しておけば、がんがんジョブを回すことができますね。&lt;/p&gt;
&lt;p&gt;RSSフィードの定期チェックのためには「あるRSSフィードを見にいって、更新があれば記事を追加する」というジョブを全ての記事分ジョブキューに登録すればよい、ということになります。&lt;/p&gt;
&lt;h3 id="定期的にジョブを発行する"&gt;定期的にジョブを発行する&lt;/h3&gt;
&lt;p&gt;ジョブを処理する側はResqueを使って実装できました。ではジョブはどのように発行すればいいでしょうか？&lt;/p&gt;
&lt;p&gt;これには&lt;code&gt;cron&lt;/code&gt;のようにある時間毎に起動するプログラムを用いることにしました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/tomykaira/clockwork"&gt;tomykaira/clockwork&lt;/a&gt; [https://github.com/tomykaira/clockwork:image:large]&lt;/p&gt;
&lt;p&gt;この&lt;code&gt;clockwork&lt;/code&gt;というgemを使うと、「◯◯分毎に△△する」というようなデーモンをRubyで書くことができます。実際には次のような手段を取りました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;clockworkを使い1分ごとにRSSリーダーの特定のURL(例：/feed/update)にアクセス&lt;/li&gt;
&lt;li&gt;Rails側で上のURLに対応したコントローラのアクションを作っておく&lt;/li&gt;
&lt;li&gt;対応アクションで更新ジョブをジョブキューに登録する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これで定期的にジョブを発行するという流れができました。&lt;/p&gt;
&lt;p&gt;この方法だとジョブ発行アクションが1時間に60回呼ばれることになります。1回のアクション毎に1個のフィード更新ジョブを走らせていたのでは、ユーザーが期待するフィード更新頻度を保てません。&lt;/p&gt;
&lt;p&gt;ユーザー視点で考えると元サイトが更新されたらすぐにRSSリーダーに反映されて欲しいはずなので、せいぜい1時間に1回はすべてのフィードを更新するようにしておくべきです。&lt;/p&gt;
&lt;p&gt;これは単純計算すると、RSSリーダーのシステム内に存在するフィード数の60分の1を1分で更新しなければいけません。1分毎に呼ばれる更新アクションでは、フィードの更新時刻が古いものから60分の1個を取り出して、それを更新するジョブを作りジョブキューに投げるということを行います。&lt;/p&gt;
&lt;p&gt;Resqueワーカーの数が十分で、データベースがボトルネックにならないのであれば、これでユーザーが必要としているRSSリーダーの価値の部分を実装できたことになります。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;RSSリーダーはバックグラウンドのフィード更新処理が肝&lt;/li&gt;
&lt;li&gt;ジョブキューを監視するワーカーをたくさん動かしておく&lt;/li&gt;
&lt;li&gt;ユーザーが期待する頻度で更新ジョブをキューに登録する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;でも、さっきしれっと書いた十分な数のワーカーを動かしたりボトルネックにならないデータベースを用意するほうが大変だったりする。&lt;/p&gt;</description></item><item><title>Objective-CでBlockを遅延実行するコード</title><link>https://blog.piyo.tech/posts/2014-02-14-204407/</link><pubDate>Fri, 14 Feb 2014 20:43:07 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-14-204407/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/10029f8e-9de1-4286-a4fd-417edb59618d/9e2f0fe0580fc3aa7e3948abbcb74f21/deep/0/imgres-1.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;performSelector&lt;/code&gt;もいいんだけど、メソッドを定義するのが面倒ってことありますよね。そういうときはブロックを遅延実行させれば良いです。&lt;/p&gt;
&lt;p&gt;次のコードをカテゴリとして追加してあげて、&lt;/p&gt;
&lt;script src="https://gist.github.com/pi-chan/8955578.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/pi-chan/8955475.js"&gt;&lt;/script&gt;
&lt;p&gt;こんなふうに使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;hoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; [self performBlock:&lt;span style="color:#f92672"&gt;^&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// do something ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; } afterDelay:&lt;span style="color:#ae81ff"&gt;0.1f&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>iOSで上へ引っ張って更新させるライブラリ</title><link>https://blog.piyo.tech/posts/2014-02-13-202403/</link><pubDate>Thu, 13 Feb 2014 20:23:08 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-13-202403/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/8d1cc50d-6707-4ad1-830a-7d46d7d18fd7/862867500b26abac8f84430799defcd6/deep/0/IMG001.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Twitterのアプリなどが採用していた引っ張って更新するためのコントロールは、&lt;code&gt;UIRefreshControl&lt;/code&gt;としてiOS6からiOS SDKに正式採用されています。ところが、この&lt;code&gt;UIRefreshControl&lt;/code&gt;は&lt;strong&gt;下へ&lt;/strong&gt;引っ張って更新するのには対応していますが、&lt;strong&gt;上へ&lt;/strong&gt;引っ張って更新するのには対応していません。&lt;/p&gt;
&lt;p&gt;上へ引っ張って更新が欲しくなるのは、コンテンツが上から下に並んでいて、追加で読み込むコンテンツを一番下に追加したいような場合です。例えば2chビューワーなんかがそうですよね。&lt;/p&gt;
&lt;p&gt;上へ引っ張って更新する操作には標準の&lt;code&gt;UIRefreshControl&lt;/code&gt;が使えないので、自前で実装するかライブラリを使用するしか方法はありません。&lt;/p&gt;
&lt;h2 id="自前で実装する"&gt;自前で実装する&lt;/h2&gt;
&lt;p&gt;実はこれは試していません。先にライブラリ探しから始めてしまったので！&lt;/p&gt;
&lt;p&gt;ざっと調べたところでは、&lt;code&gt;UITableView&lt;/code&gt;の&lt;code&gt;footerView&lt;/code&gt;を使うとかなんとか、そんなような感じでした。スクロールを検知して追加コンテンツを読み込み「引っ張って更新」のViewの位置を再調整それば良さそうでした。&lt;/p&gt;
&lt;h2 id="ライブラリを使う"&gt;ライブラリを使う&lt;/h2&gt;
&lt;p&gt;デファクトスタンダードなライブラリがどれかわかりませんでした。もしそういうのがあったら教えて欲しいです。&lt;/p&gt;
&lt;p&gt;僕が使ったのはこれ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pilot34/MNMBottomPullToRefresh"&gt;pilot34/MNMBottomPullToRefresh&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="mnmbottompulltorefreshの導入"&gt;MNMBottomPullToRefreshの導入&lt;/h3&gt;
&lt;p&gt;READMEにはありませんが、CocoaPodsで導入可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Podfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;MNMBottomPullToRefresh&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ pod install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="使い方"&gt;使い方&lt;/h3&gt;
&lt;p&gt;UITableViewを置いたUIViewControllerを例に実装を紹介。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ViewController.h&lt;/code&gt;で&lt;code&gt;MNMBottomPullToRefreshManagerClient&lt;/code&gt;を継承します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;MNMBottomPullToRefreshManager.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ViewController&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;UIViewController&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;MNMBottomPullToRefreshManagerClient, UITableViewDelegate, UITableViewDataSource&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;IBOutlet&lt;/span&gt; UITableView &lt;span style="color:#f92672"&gt;*&lt;/span&gt;tableView;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;ViewController.m&lt;/code&gt;ではちょっとした実装と、&lt;code&gt;MNMBottomPullToRefreshManagerClient&lt;/code&gt;のメソッドの定義を行います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ViewController&lt;/code&gt;のプロパティに&lt;code&gt;MNMBottomPullToRefreshManager&lt;/code&gt;を持つ&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scrollViewDidScroll&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scrollViewDidEndDragging&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bottomPullToRefreshTriggered&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ViewController&lt;/span&gt; ()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;strong&lt;/span&gt;) MNMBottomPullToRefreshManager&lt;span style="color:#f92672"&gt;*&lt;/span&gt; refreshManager;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)viewDidLoad
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; [super viewDidLoad];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; self.tableView.delegate &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; self.tableView.dataSource &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ここ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; self.refreshManager &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[MNMBottomPullToRefreshManager alloc] initWithPullToRefreshViewHeight:&lt;span style="color:#ae81ff"&gt;60.0&lt;/span&gt; tableView:self.tableView withClient:self];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# pragma mark - MNMBottomPullToRefreshManager
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)scrollViewDidScroll:(UIScrollView &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)scrollView
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; [self.refreshManager tableViewScrolled];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)scrollViewDidEndDragging:(UIScrollView &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)scrollView willDecelerate:(&lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt;)decelerate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; [self.refreshManager tableViewReleased];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)bottomPullToRefreshTriggered:(MNMBottomPullToRefreshManager &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)manager {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; [self performSelector:&lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(refresh) withObject:nil afterDelay:&lt;span style="color:#ae81ff"&gt;0.3f&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最後の&lt;code&gt;bottomPullToRefreshTriggered&lt;/code&gt;で更新処理を実行します。ここでは&lt;code&gt;performSelector: withObject: afterDelay:&lt;/code&gt;を用いて非同期実行しています。確かActivityIndicatorと同じく、そうしておかないと動かなかったような…。&lt;/p&gt;
&lt;p&gt;そして更新メソッドの最後で&lt;code&gt;self.refreshManager&lt;/code&gt;に更新終了を通知します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;refresh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// データ更新
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 更新後に呼び出す
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; [self.refreshManager tableViewReloadFinished];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このライブラリにはもうひとつ注意があって、引っ張って更新するためのViewをTableの一番下に相当する位置に配置しているのですが、行が増えるたびに再配置し直さないとおかしな場所に配置されてしまうことになります。&lt;/p&gt;
&lt;p&gt;そこで&lt;code&gt;viewDidLayoutSubviews&lt;/code&gt;をオーバーライドします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewDidLayoutSubviews&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; [super viewDidLayoutSubviews];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; [self.refreshManager relocatePullToRefreshView];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また場合によっては&lt;code&gt;viewDidLayoutSubviews&lt;/code&gt;が呼ばれないケースがありました（どのようなケースで起こるのかはわかりっていません）。そういう場合はデータ更新後に&lt;code&gt;layoutIfNeeded&lt;/code&gt;を呼んであげることで再レイアウトさせることができるようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;refresh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// データ更新 ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 再レイアウト
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; [self.view layoutIfNeeded];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 更新後に呼び出す
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; [self.refreshManager tableViewReloadFinished];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Railsでデータベースのレプリケーションをしたいとき</title><link>https://blog.piyo.tech/posts/2014-02-11-195346/</link><pubDate>Tue, 11 Feb 2014 19:53:46 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-11-195346/</guid><description>&lt;p&gt;データベースの負荷分散の方法の1つレプリケーションという方法があります。マスターDBへの変更をスレーブDBに同期するようにしておいて、書き込みのクエリはマスターDBへ、読み取りのクエリはスレーブDBへと振り分けることで負荷を分散しようというやり方です。&lt;/p&gt;
&lt;p&gt;最初にこの方法を知った時は最強じゃんとか思ったんですが、そんな魔法のようなものではなくよく考えてうまく使う必要があります。例えばマスターの更新がスレーブに反映されるのにはタイムラグがあるので、マスターを更新した直後にスレーブを参照してデータがない、とか。まあとにかく色々工夫が必要です。&lt;/p&gt;
&lt;p&gt;と、ここまで書いておいてなんですが、今日の記事ではレプリケーションの実践について書くわけではありません。もっとライトな「Railsでデータベースの接続先を変えるためのgemを紹介する」という話です。&lt;/p&gt;
&lt;p&gt;いくつかのgemがありましたが、僕が選んだのはシンプルに使えそうだったpostamtというgemです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/sauspiel/postamt"&gt;sauspiel/postamt&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;有名なのはこっちかも？使った当時は導入に手間どってしまったのでパスしました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/tchandy/octopus"&gt;tchandy/octopus&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="postamtの導入"&gt;postamtの導入&lt;/h2&gt;
&lt;h3 id="インストール"&gt;インストール&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Gemfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;postamt&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ bundle install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="databaseymlの設定"&gt;database.ymlの設定&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;database.yml&lt;/code&gt;ファイルにスレーブの情報を追加します。スレーブは複数でもよいです。。データベースの名前やユーザー名などを一緒にしておけば&lt;code&gt;host&lt;/code&gt;を書き換えるだけでOKです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;development&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;adapter&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;mysql2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;host&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;db-master&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;database&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;hoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;user&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;hoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;password&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;hoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;pool&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;timeout&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;5000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;slave1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;host&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;db-slave1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;slave2&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;host&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;db-slave2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ローカルでの動作確認でレプリケーション構成を作るのが面倒なときは、参照するDBは同じにしたまま読み取り専用のユーザーを作っておくことでシミュレート可能です。&lt;/p&gt;
&lt;h2 id="postamtの使い方"&gt;postamtの使い方&lt;/h2&gt;
&lt;h3 id="アクション単位で分ける"&gt;アクション単位で分ける&lt;/h3&gt;
&lt;p&gt;READMEから転載ｗ&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UserController&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ApplicationController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; use_db_connection &lt;span style="color:#e6db74"&gt;:slave&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;User&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;only&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:search&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;search&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# SELECTs here are sent to slave&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# User#save and User.create would be sent to master anyways.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Everything in a transaction block too.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; @users &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;User&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(&lt;span style="color:#f92672"&gt;...&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# sent to slave&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; @something_else &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;SomethingElse&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;first &lt;span style="color:#75715e"&gt;# sent to master&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;create&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; @user &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;User&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(params&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:user&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; @user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;save! &lt;span style="color:#75715e"&gt;# sent to master&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;invoice&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; transaction &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; @user &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;User&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(&lt;span style="color:#f92672"&gt;...&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# sent to master&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; @invoices &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Invoice&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create(&lt;span style="color:#f92672"&gt;...&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# sent to master&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="モデルのデフォルトを指定する"&gt;モデルのデフォルトを指定する&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;User&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;default_connection &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;:slave1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;User&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(&lt;span style="color:#f92672"&gt;...&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# slave1が使われる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="dbを指定して実行する"&gt;DBを指定して実行する&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Postamt&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;on(&lt;span style="color:#e6db74"&gt;:master&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;User&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(&lt;span style="color:#f92672"&gt;...&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# masterが使われる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>iOS用のYouTubeの動画IDを渡すと再生してくれる便利なやつ</title><link>https://blog.piyo.tech/posts/2014-02-09-210119/</link><pubDate>Sun, 09 Feb 2014 21:01:19 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-09-210119/</guid><description>&lt;p&gt;YouTubeのAPIで取ってきた情報を何やら使うシリーズ。今日はIDを元に再生を行います。&lt;/p&gt;
&lt;p&gt;動画再生系はいくつかのブログポストでやり方を見かけるのですが、YouTubeを再生するとなるとembed用HTMLを埋め込んだWebViewを使うっていう方法ばかり見つかって少し困っていました。幸いこのような拡張を見つけました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/0xced/XCDYouTubeVideoPlayerViewController"&gt;0xced/XCDYouTubeVideoPlayerViewController&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;名前超長い。使い方は簡単です。&lt;code&gt;MPMoviePlayer&lt;/code&gt;と同じようにつかう感じですかね？&lt;/p&gt;
&lt;p&gt;サンプルコードを書くまでもなくて、これだけで再生できるようになります。超素敵です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;XCDYouTubeVideoPlayerViewController&lt;span style="color:#f92672"&gt;*&lt;/span&gt; videoPlayerViewController &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[XCDYouTubeVideoPlayerViewController alloc] initWithVideoIdentifier:&lt;span style="color:#e6db74"&gt;@&amp;#34;urRW3jx67AI&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;[self presentMoviePlayerViewControllerAnimated:videoPlayerViewController];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/ui0MeCWDD19xSAWOzW_X9L56eMEuhgZ2kyJuvnnwnuQjad4PQIi2GGXEFFLQi466oPxO3T1-p-5QiH3Nue7pJBiwYNRVdjh6-pl08iH-ZxK4cwuKAtt_HK2HOrm5xQMa347Ji2emmHV4piuqLCWvlhiCEVF4wdLlh5j_HpavFnO-8fuYuRQllIW1qQQ7nNXWG-Sw_QbdWlfCFTruBd7A6b8xXzgcnoSrWvXXj6pNEJIj6-6VcxFF03pD5-hWbqcvmUtnVDRueRxhDwFmG2bMRdlOPjoIccs536RRNz8HShfujB1odcW6EoIVMCP8xJ_8h0gNywoZWdr-F3HUKq2buVivu8QgXOoC5q2iCBG9MLphE0FvRYDWJSEiZAIYLXdAPl51VXetu1Z849A9x6begu0nbrhRWIYI8z6krj9RgGyqGfagrBLFCTqjI4sY4bjqG7dUGx6nL8g1BmQcoNXzfYffeufbSoAk1kVVa0ecsqPYa-WEDsDGPlTd8FhBOD4N79LvFq2yxMpc0JlI4LHLS7SnILPuLgoUKIJjsJgbE2KFY8tS0fRzDmgpLyktI8BNn6dB0kDqdGwhvZnGnkZZdMjElktdVP2yvj_drcdiGuy9zDoKmA2yUlMtc3LEIWT5dGXBSkwRc8jGm7KAaUidkaSU4xoomrldQg=w318-h500-no" alt=""&gt;&lt;/p&gt;</description></item><item><title>入れ子になったNSDictionaryのデータを取り出す</title><link>https://blog.piyo.tech/posts/2014-02-08-191912/</link><pubDate>Sat, 08 Feb 2014 19:19:12 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-08-191912/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/ffae429a-41a5-46e6-a23b-2311347c3191/e67a682a330bc344813d36dbb5ab70a6/deep/0/02.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;何重にも入れ子になったNSDictionaryのデータをチマチマ取り出すのは超絶めんどくさいです。&lt;code&gt;valueForKey&lt;/code&gt;で取り出したNSDictionaryにさらに&lt;code&gt;valueForKey&lt;/code&gt;して、さらに、、なんてやるともうやってられません。&lt;/p&gt;
&lt;p&gt;幸い&lt;code&gt;valueForKeyPath&lt;/code&gt;というメソッドで少し簡単にできるので、そちらを使ったほうがいいと思われます。&lt;/p&gt;
&lt;p&gt;例によってYoutubeAPIの戻り値をNSDictionaryにしたものを対象とします。((&lt;a href="https://blog.piyo.tech/posts/2014-01-24-212903"&gt;YouTubeAPI超入門 使い始めから検索まで - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[https://blog.piyo.tech/posts/2014-01-24-212903:image:large]))&lt;/p&gt;
&lt;p&gt;データはこれ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;youtube#searchListResponse&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;etag&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\&amp;#34;qQvmwbutd8GSt4eS4lhnzoWBZs0/TvUA3aT9bg7gzx72UgdpWtsjAD0\&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;nextPageToken&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;CAUQAA&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;pageInfo&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;totalResults&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000000&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;resultsPerPage&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;items&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;youtube#searchResult&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;etag&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\&amp;#34;qQvmwbutd8GSt4eS4lhnzoWBZs0/YNAKTLX6SbYCco99EQWCyVDIxCo\&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;youtube#video&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;videoId&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;lwYgdBQ0k3U&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;snippet&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;publishedAt&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;2013-10-04T05:16:29.000Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;channelId&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;UCZfWmiGEbwWNPMe2nr3WdDg&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;【WOWOW】U-12ジュニアサッカーワールドチャレンジ2013 FCバルセロナ ダイジェスト&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;U-12ジュニアサッカーワールドチャレンジ2013 FCバルセロナ ダイジェスト ☆U-12 Junior soccer world challenge 2013 FC Barcerona Infantil B digest 2013年8月27 ...&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;thumbnails&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://i.ytimg.com/vi/lwYgdBQ0k3U/default.jpg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;medium&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://i.ytimg.com/vi/lwYgdBQ0k3U/mqdefault.jpg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;high&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://i.ytimg.com/vi/lwYgdBQ0k3U/hqdefault.jpg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;channelTitle&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;WOWOWofficial&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;liveBroadcastContent&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;none&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このjsonがNSDictionaryに対応しているとします。データには動画情報が複数含まれているので次のコードのようにループで回しながら処理することを基本とします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;NSArray&lt;span style="color:#f92672"&gt;*&lt;/span&gt; items &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (NSArray&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)[dic valueForKey:&lt;span style="color:#e6db74"&gt;@&amp;#34;items&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (NSDictionary&lt;span style="color:#f92672"&gt;*&lt;/span&gt; item &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; items) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// process an item
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そして、各itemの標準サムネイルを取り出したいとします。階層で言うと、&lt;code&gt;snippet&lt;/code&gt;→&lt;code&gt;thumbnails&lt;/code&gt;→&lt;code&gt;default&lt;/code&gt;→&lt;code&gt;url&lt;/code&gt;です。&lt;/p&gt;
&lt;p&gt;これを馬鹿正直にやろうとすると、、、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;NSDictionary&lt;span style="color:#f92672"&gt;*&lt;/span&gt; snippet &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [item valueForKey:&lt;span style="color:#e6db74"&gt;@&amp;#34;snippet&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;NSDictionary&lt;span style="color:#f92672"&gt;*&lt;/span&gt; thumbnails &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [snippet valueForKey:&lt;span style="color:#e6db74"&gt;@&amp;#34;thumbnails&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;NSDictionary&lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [thumbails valueForKey:&lt;span style="color:#e6db74"&gt;@&amp;#34;default&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt; url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; valueForKey:&lt;span style="color:#e6db74"&gt;@&amp;#34;url&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;となります。まあアホらしいですね。&lt;/p&gt;
&lt;p&gt;ところが&lt;code&gt;valueForKeyPath&lt;/code&gt;を使うと、、、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt; url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [item valueForKeyPath:&lt;span style="color:#e6db74"&gt;@&amp;#34;snippet.thumbnails.default.url&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一行で書ける！&lt;/p&gt;
&lt;p&gt;これまでObjective-Cでこういった入れ子のデータを扱って来なかったので初めて知りました。きっと基本なんでしょうね。&lt;/p&gt;
&lt;h3 id="注意点"&gt;注意点&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://qiita.com/ninjinkun/items/74152f398fd94dcb1678"&gt;Objective-C - ネストしたJSONデータのプロパティアクセスにはvalueForKeyPath:が便利 - Qiita [キータ]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;こちらのリンク先でninjinkun氏がこのように述べていました。もっともだなあ。一応気をつけよう。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;この方法、便利ではありますが以下の理由で仕事ではあまり使わないようにしています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;コンパイラに頼れないので変更に弱い
&lt;ul&gt;
&lt;li&gt;テストがあればOKです&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;データ構造をそのまま引き回す羽目になるので見通しが悪い
&lt;ul&gt;
&lt;li&gt;きちんとモデルクラスを作ってプロパティを定義した方が他人が見てもわかりやすい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;多少面倒でもモデルを作った方が何かと良いというのが今のところの結論です。個人プロダクト及びCoreDataを使う場合には多用しています。&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>iOSで日時の相対表記</title><link>https://blog.piyo.tech/posts/2014-02-07-192803/</link><pubDate>Fri, 07 Feb 2014 19:28:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-07-192803/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/743c3447-691f-49db-a959-f0653c078c78/c59206f5046796a2c5d06f92a43e89c7/deep/0/imgres.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;1 week ago&lt;/code&gt;みたいな日付の相対表記をiOSでやりたいので探しました。そしたらCocoaPods対応のライブラリがありました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/kevinlawler/NSDate-TimeAgo"&gt;kevinlawler/NSDate-TimeAgo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これです。カテゴリでNSDateを拡張してくれてあります。&lt;/p&gt;
&lt;h2 id="インストール"&gt;インストール&lt;/h2&gt;
&lt;p&gt;普通のCocoaPods。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# in Podfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;NSDate+TimeAgo&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ pod install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="使う"&gt;使う&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;NSDate+TimeAgo.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;- (NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;relative:&lt;/span&gt;(NSDate&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)date
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [date timeAgo]; &lt;span style="color:#75715e"&gt;// ex. 2 days ago
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;できた。カテゴリなので呼び出しも自然な感じがして使いやすいです。&lt;/p&gt;
&lt;p&gt;個人的には1週間前とか2週間前でも&lt;code&gt;14 days ago&lt;/code&gt;とかにしたい気もするので、その辺は拡張してみてもいいかもしれない。&lt;/p&gt;</description></item><item><title>ISO8601拡張表記のNSStringをNSDateに変換する</title><link>https://blog.piyo.tech/posts/2014-02-06-203753/</link><pubDate>Thu, 06 Feb 2014 20:37:53 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-06-203753/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/90f19eb1-c407-440d-962c-41f5fada4cfc/5aa08b7057dadae38e95a98d8047b7a2/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-04-21-30.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;iOSアプリで日付文字列をNSDateに変換する話です。よく知られているように、NSDateFormatterを使って変換をするのが一般的です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;NSDateFormatter&lt;span style="color:#f92672"&gt;*&lt;/span&gt; formatter &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSDateFormatter new];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;formatter.dateFormat &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;yyyy/MM/dd HH:mm:ss&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;NSDate&lt;span style="color:#f92672"&gt;*&lt;/span&gt; date &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [formatter dateFromString:&lt;span style="color:#e6db74"&gt;@&amp;#34;2014/01/07 10:35:24&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;フォーマッタに変換したい文字列を解析するための書式を渡して変換するというわけです。ここまでが基本。&lt;/p&gt;
&lt;p&gt;さて、先日YoutubeのAPIに関する記事を書きました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-01-24-212903"&gt;YouTubeAPI超入門 使い始めから検索まで - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[https://blog.piyo.tech/posts/2014-01-24-212903:image:large]&lt;/p&gt;
&lt;p&gt;この記事では使い方のサンプルと戻ってくる文字列を載せましたが、その中に投稿日時&lt;code&gt;publishedAt&lt;/code&gt;というデータ項目があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;snippet&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;publishedAt&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;2013-10-04T05:16:29.000Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;channelId&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;UCZfWmiGEbwWNPMe2nr3WdDg&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;【WOWOW】U-12ジュニアサッカーワールドチャレンジ2013 FCバルセロナ ダイジェスト&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;U-12ジュニアサッカーワールドチャレンジ2013 FCバルセロナ ダイジェスト ☆U-12 Junior soccer world challenge 2013 FC Barcerona Infantil B digest 2013年8月27 ...&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;thumbnails&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ありますね、&lt;code&gt;&amp;quot;2013-10-04T05:16:29.000Z&amp;quot;&lt;/code&gt;とかいうのが。&lt;/p&gt;
&lt;p&gt;これをどうやってNSDateにするんだというのが今日の本題です。&lt;/p&gt;
&lt;h2 id="iso-8601-拡張表記"&gt;ISO 8601 拡張表記&lt;/h2&gt;
&lt;p&gt;そもそも、日時の表記は国際規格で決められています。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ja.wikipedia.org/wiki/ISO_8601"&gt;ISO 8601 - Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;YoutubeのAPIで取れるのはこのISO 8601の拡張表記というもので、&lt;code&gt;YYYY-MM-DDThh:mm:ss[.nnnnnn]Z&lt;/code&gt;のような形式を取ります。頭から、年、月、日、区切り文字&lt;code&gt;T&lt;/code&gt;、時、分、秒、[うるう秒]、タイムゾーンを意味します。&lt;/p&gt;
&lt;p&gt;詳しくは述べませんが角括弧の&lt;code&gt;nnnnnn&lt;/code&gt;はうるう秒で、Youtubeの投稿日時を扱うような場合には大した問題にはならず無視できるはずです。&lt;/p&gt;
&lt;p&gt;最後のタイムゾーンは、&lt;code&gt;Z&lt;/code&gt;とあればUTCです。東京のように時差がある場合は&lt;code&gt;+09:00&lt;/code&gt;のように表記します。Youtubeの表記はUTCですね。&lt;/p&gt;
&lt;p&gt;これで変換したい文字列のことがよくわかりました。&lt;/p&gt;
&lt;h2 id="実装"&gt;実装！&lt;/h2&gt;
&lt;p&gt;実装はこのようになりました。つまるところ&lt;code&gt;dateFormat&lt;/code&gt;を正しくしてあげればよいわけです。区切り文字の関係で少し癖のある書き方になっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;NSDateFormatter&lt;span style="color:#f92672"&gt;*&lt;/span&gt; formatter &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSDateFormatter new];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;formatter.dateFormat &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;yyyy-MM-dd&amp;#39;T&amp;#39;HH:mm:ss.SSS&amp;#39;Z&amp;#39;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;formatter.timeZone &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSTimeZone timeZoneWithName:&lt;span style="color:#e6db74"&gt;@&amp;#34;UTC&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;NSDate&lt;span style="color:#f92672"&gt;*&lt;/span&gt; date &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [formatter dateFromString:&lt;span style="color:#e6db74"&gt;@&amp;#34;2013-10-04T05:16:29.000Z&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>XcodeシミュレータなしでViewをプレビューする</title><link>https://blog.piyo.tech/posts/2014-02-05-201924/</link><pubDate>Wed, 05 Feb 2014 20:19:24 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-05-201924/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/2d342f01-367e-499a-a121-71af2dd91824/4701b9334fb41abf00a69d8aed78a7e2/deep/0/imgres-1.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Xcodeにはstoryboardを使って作り上げたViewをプレビューする機能があります。これを使うと、画面回転時、4インチと3.5インチの切替時、iOS7とそれ以前の切替時、それぞれのレイアウトを確かめることができます。&lt;/p&gt;
&lt;p&gt;AutoLayoutでConstraintを付けた結果がどうなるかは見てみないとわからないことが多いんですが、この機能を使えばいちいちシミュレータを立ち上げる必要はありません。&lt;/p&gt;
&lt;p&gt;というわけで、使い方。&lt;/p&gt;
&lt;p&gt;まずはストーリーボードを表示させ、アシスタントを有効に。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/f16c6831-caf8-4fa1-a76e-6676a92f8814/d340f0b1570602259e72b4fe8c1e485d/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-03-11-32.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;次にアシスタントが開くエティターを変えます。&lt;/p&gt;
&lt;p&gt;ここを押して、、、&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9734638c-d47c-48a2-bb78-5ec243820292/f6731a3fd918eb3f1cae31ab2e8567c4/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-03-11-33.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;プレビューを選択。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/d72ea258-2bda-4d5e-997e-0c020eb821df/c5b119067a5cce662dc4f9492b3d6f82/deep/0/%E5%85%A8%E7%94%BB%E9%9D%A2-2014-02-03-11-33.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;するとプレビューが表れます。画面下の方にこういったボタンがあり、そこでいろいろ切り替えることができます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/359c2768-29c6-4932-8dfd-f8321ef994da/18f0a1bf00e36d06a3dc17c615fbfd7f/deep/0/Tips.xcodeproj---Main.storyboard.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;↓Constraintをいくつか付けてレイアウトを変えてみた、の図です。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b79e1778-b75c-430f-b1c8-f4cf567c10ec/c95a14ba64516a34008fe73e2befab35/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-02-03-11-37.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>CocoaPods pod installが失敗する問題</title><link>https://blog.piyo.tech/posts/2014-02-04-171023/</link><pubDate>Tue, 04 Feb 2014 17:10:23 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-04-171023/</guid><description>&lt;p&gt;今日（2014/02/04）1週間ぶりにぐらいに&lt;code&gt;$ pod install&lt;/code&gt;したら妙なエラーが出てライブラリのインストールができなくなりました。&lt;/p&gt;
&lt;p&gt;エラーメッセージの最後はこんな感じでした。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Pull is not possible because you have unmerged files.
Please, fix them up in the work tree, and then use &amp;#39;git add/rm &amp;lt;file&amp;gt;&amp;#39;
as appropriate to mark resolution, or use &amp;#39;git commit -a&amp;#39;.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;調べてみるとCocoaPodsの公式ブログでもこのことについて言及されていました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.cocoapods.org/Repairing-Our-Broken-Specs-Repository/"&gt;Repairing Our Broken Specs Repository - CocoaPods Blog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この記事の「Why did this break?」のところを読んでみると、&lt;code&gt;libgit2&lt;/code&gt;にバグがあったせいでCocoaPodsのSpecリポジトリに&lt;code&gt;force push&lt;/code&gt;せざるを得なくなったということらしいです。&lt;code&gt;force push&lt;/code&gt;するということはそのリポジトリを参照していた全ての人のところで不都合が起きるわけですね。&lt;/p&gt;
&lt;p&gt;公式で発表されている対応方法は次の通りです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ pod repo remove master
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ pod setup
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで&lt;code&gt;$ pod install&lt;/code&gt;が効くようになりました！&lt;/p&gt;
&lt;p&gt;&lt;code&gt;force push&lt;/code&gt;怖い。&lt;/p&gt;</description></item><item><title>アイデアカードとかいうツールをrubygem化</title><link>https://blog.piyo.tech/posts/2014-02-03-214311/</link><pubDate>Mon, 03 Feb 2014 21:43:11 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-03-214311/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/3103251e-4496-4497-8c5f-648e919c26d9/0ea843ee5272db6594bdff695126ee61/deep/0/ruby.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;アイデアカードとかいうアイデア出しのサポートツールを見つけました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ideacard.jp/"&gt;アイデアカード公式サイト&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;目的、着眼点、どう変えるかという3種類のカードがあってカードを引くことでランダムなフレーズが完成するってやつです。昔そういう遊びをしたことはありませんか？誰が、どこで、なにを、どうした、っていう感じたくさんカードにしておいてランダムに引いてできた文章がおかしくて笑う、みたいな遊び。それに近いです。&lt;/p&gt;
&lt;p&gt;詳しく説明する気はあまりないので気になる人は上のURLを見てくれればおk。&lt;/p&gt;
&lt;p&gt;実物のカードが存在するみたいなんですが、iOS版なんかもあるようです。じゃあRubyのプログラムにしちゃえばいいじゃん？ってことでgem化してみました。完成物はrubygems.orgにアップロード済みです。1回そこまでやってみたかったんです。&lt;/p&gt;
&lt;p&gt;ソースはこちらです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/idea_card"&gt;pi-chan/idea_card&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="gemの作り方"&gt;gemの作り方&lt;/h2&gt;
&lt;p&gt;こちらのスライドを参照しました。超助かりました。&lt;/p&gt;
&lt;iframe src="https://www.slideshare.net/slideshow/embed_code/24925828" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px 1px 0; margin-bottom:5px; max-width: 100%;" allowfullscreen&gt; &lt;/iframe&gt; &lt;div style="margin-bottom:5px"&gt; &lt;strong&gt; &lt;a href="https://www.slideshare.net/shokai/ruby-24925828" title="Ruby中級入門" target="_blank"&gt;Ruby中級入門&lt;/a&gt; &lt;/strong&gt; from &lt;strong&gt;&lt;a href="http://www.slideshare.net/shokai" target="_blank"&gt;Sho Hashimoto&lt;/a&gt;&lt;/strong&gt; &lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;最終的に必要になるのでrubygems.orgでユーザー登録。&lt;a href="http://rubygems.org/"&gt;RubyGems.org | your community gem host&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$ bundle gem idea_card&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;idea_card.gemspec&lt;/code&gt;を編集、authorとかemailとかを埋める&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;実装する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$ rake install&lt;/code&gt; でローカルインストールして確認&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$ rake release&lt;/code&gt;する # 初回はrubygems.orgのIDとパスワードが設定されていないって怒られるので次の手順&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$ gem push&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;IDとパスワードを入れる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$ rake release&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="中身の説明"&gt;中身の説明&lt;/h2&gt;
&lt;h3 id="データファイル"&gt;データファイル&lt;/h3&gt;
&lt;p&gt;カードには目的、着眼点、変化の3種類があります。それぞれの文言をハードコーディングしてもよかったのですが一応外部ファイルに書いておくことにしました。&lt;/p&gt;
&lt;p&gt;一例ですが、目的を書いた&lt;code&gt;goals&lt;/code&gt;というテキストファイルがあります。このように一行がカード一枚に対応しています。&lt;/p&gt;
&lt;script src="https://gist.github.com/pi-chan/8768454.js"&gt;&lt;/script&gt;
&lt;h3 id="スクリプト本体"&gt;スクリプト本体&lt;/h3&gt;
&lt;p&gt;こういう風に使えるように作りました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;IdeaCard&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;draw
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;IdeaCard&lt;/code&gt;はモジュールで&lt;code&gt;draw&lt;/code&gt;はモジュールの特異メソッドです。&lt;/p&gt;
&lt;p&gt;で、実装はこれだけ。&lt;/p&gt;
&lt;script src="https://gist.github.com/pi-chan/8768522.js"&gt;&lt;/script&gt;
&lt;p&gt;ポイントは&lt;code&gt;IdeaCard.goal&lt;/code&gt;、&lt;code&gt;IdeaCard.point&lt;/code&gt;、&lt;code&gt;IdeaCard.change&lt;/code&gt;の3つのメソッド。必要性はさておき、動的にメソッドを定義しています。実装がかぶっていたからメタにやってみようという程度の理由です。メソッドに対応したファイルを読んで入力を全て取っておき、そのなかからランダムに1つだけ返すという実装です。&lt;/p&gt;
&lt;h3 id="微妙にはまる"&gt;微妙にはまる&lt;/h3&gt;
&lt;p&gt;これといって特に難しいことはありませんが、一箇所はまりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt; current_file_path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;dirname(__FILE__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; functions&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;m&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; eval &lt;span style="color:#e6db74"&gt;&amp;lt;&amp;lt;-EOC
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#75715e"&gt;#{m}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;expand_path &lt;span style="color:#e6db74"&gt;&amp;#34;./&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;m&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;s&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;current_file_path&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# &amp;lt;= この部分&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#75715e"&gt;#{m}s ||= load(path)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#75715e"&gt;#{m}s.sample&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;EOC&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このソースファイルと同じパスにデータファイルを置いてあるので、相対パスを使ってデータファイルを読みいくという作りにするつもりで、最初は&lt;code&gt;&amp;quot;#{current_file_path}&amp;quot;&lt;/code&gt;のところにそのまま&lt;code&gt;__FILE__&lt;/code&gt;としていました。ところが、&lt;code&gt;eval&lt;/code&gt;するタイミングでは&lt;code&gt;__FILE__&lt;/code&gt;はこのファイルを&lt;code&gt;require&lt;/code&gt;している人、つまり&lt;code&gt;lib/idea_card.rb&lt;/code&gt;（1つ上の階層のファイル）になってしまっていました。おかげでデータファイルが取れないため想定したとおりに動きませんでした。&lt;/p&gt;
&lt;p&gt;そういうわけで、evalの外で&lt;code&gt;__FILE__&lt;/code&gt;の値を取っておくという上のような実装に変えて事なきを得ました。これってメタプロの仕組みちゃんとわかってれば当たり前なんですかね。&lt;/p&gt;
&lt;p&gt;パーフェクトRubyとメタプログラミングRuby読みなおそうかなー。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4774158798/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/51K0jUf&amp;#43;iEL.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;パーフェクトRuby (PERFECT SERIES 6)&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4048687158/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/91fTiMcfC&amp;#43;L._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;メタプログラミングRuby&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>RubyMineエディターの水平分割・垂直分割</title><link>https://blog.piyo.tech/posts/2014-02-02-175310/</link><pubDate>Sun, 02 Feb 2014 17:53:10 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-02-175310/</guid><description>&lt;p&gt;RubyMineでエディターエリアを分割する方法。&lt;/p&gt;
&lt;p&gt;エディターのタブを右クリックして、&lt;code&gt;Split Horizontally&lt;/code&gt;または&lt;code&gt;Split Vertically&lt;/code&gt;です。たまに混乱して分割方向がわからなくなりますが、メニュー横にアイコンが付いているのでわかりやすいです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/87a15daa-ee91-4f18-a600-d3a30c0e3f05/96ad25bd1898e5bd73f95dae5b9923b1/deep/0/application.rb---scheduled-post------Documents-Dropbox-Documents-code-rails-env-scheduled-post-.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;デフォルトのキーマップではこの機能にキーが設定されていません。よく使う人は要設定。&lt;/p&gt;</description></item><item><title>OmniGraphSketcherがオープンソース化して無料に！</title><link>https://blog.piyo.tech/posts/2014-02-01-192133/</link><pubDate>Sat, 01 Feb 2014 19:21:33 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-02-01-192133/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/4b34e21f-524b-48c9-b2fc-9bc369304c88/1488a0e4c95a00fa9b23444432d5f05b/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-28-19-44.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;あのOmniFocusを作っているOmniグループのグラフ作成アプリ「OmniGraphSketcher」、これまでは3000円程度で販売されていたのですが2014年1月からオープンソース化し、無償で使用できるようになったようです。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In January 2014, we released OmniGraphSketcher source code as the open source project GraphSketcher. You can download a build of the new Mac app from GitHub. We hope that the iPad app will make it back to the iTunes store soon.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/graphsketcher/GraphSketcher"&gt;graphsketcher/GraphSketcher&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;オープンソースなので自分でビルドすることもできますし、バイナリをダウンロードして使うこともできます。有料ということも試したこともなかったのですが、Omni系はクオリティ高いことがおおいので触ってみようかなーと思っています。&lt;/p&gt;
&lt;h2 id="試しに使ってみる"&gt;試しに使ってみる&lt;/h2&gt;
&lt;p&gt;バイナリをダウンロードしてきて起動してみました。使い方わからないけどポチポチと点を打ってみたの図。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/75042711-f0b6-4310-b1bb-66fae1d8b1e2/3fea90e30dfec52a3a7f62842674b7b4/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-28-17-45.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="xcodeでプロジェクトを開くとこんな感じ"&gt;Xcodeでプロジェクトを開くとこんな感じ&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/aeaff84b-1c6e-4ed0-9e31-3275c943ce4e/76962801bf4139cd2e5f83fe09b79276/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-28-17-51.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="ipad版もビルドできるよ"&gt;iPad版もビルドできるよ&lt;/h2&gt;
&lt;p&gt;ほらこの通り！iOSの開発ライセンスを持っているならビルドしてデバイスに入れることもできますね。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/24536385-5a2a-479d-a9ec-d099019b6b0e/2115b1f77e9cb3b0e552ab7342bc5925/deep/0/screenshot_311.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;せっかくなので今度はソースコードを眺めてみようと思います。&lt;/p&gt;</description></item><item><title>RubyMinerbenvのRubyを切り替える</title><link>https://blog.piyo.tech/posts/2014-01-30-173334/</link><pubDate>Thu, 30 Jan 2014 17:33:34 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-30-173334/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/d38843ab-8d5d-4946-b217-5f7d6326de41/182c889dfa648a6cc9730be76ff7bb53/deep/0/%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;RubyMine入れてみました。少しずつ慣れていきたいです。&lt;/p&gt;
&lt;p&gt;起動時はコマンドラインで使っていたrbenvのバージョンと異なるバージョンのRubyを使おうとして何やら怒られたました。明示的にバージョンを切り替える必要があるようです。&lt;/p&gt;
&lt;h2 id="やりかた"&gt;やりかた&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;コマンドキー+, &lt;/code&gt;でPreferencesを開く&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ruby SDK and Gems&lt;/code&gt;を探す&lt;/li&gt;
&lt;li&gt;リストから選んで&lt;code&gt;Apply&lt;/code&gt;（または&lt;code&gt;OK&lt;/code&gt;）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/bd04ae81-4923-46c1-8aa3-489ea31d40d2/180fd7f5a86b7cad32ab7d1e0323bb4c/deep/0/Preferences.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>悩んだらどうする？成功した起業家に学ぶ選択のしかた</title><link>https://blog.piyo.tech/posts/2014-01-29-205230/</link><pubDate>Wed, 29 Jan 2014 20:52:30 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-29-205230/</guid><description>&lt;p&gt;大きな選択をするときに迷いは生じるものです。悩みすぎて無駄な時間を過ごしたり誤った選択をしてしまったりする可能性を減らすためにも、「悩んだとき自分はこう選ぶ」という方針を決めておくと良さそうです。半分は自分に言っています。&lt;/p&gt;
&lt;h2 id="ポールグレアム"&gt;ポール・グレアム&lt;/h2&gt;
&lt;p&gt;起業家として、またY Combinatorで投資家として有名なあの人が「ハッカーと画家」の中でこう述べています。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;これは人生においても一般的に良い方法だ。2つの選択肢がある場合、難しいほうを選べ。ジョギングに行くか、座ってテレビを見るか迷ったら、ジョギングに行け。このルールがとてもうまくいくのは、おそらく、選択肢があって一方が難しいという場合、たぶんあなたの怠惰さがもう一方の選択肢を持ちだしたに違いないからだ。心の底では、何をすべきか知っているんだ。このルールに従えば、それを自分で認めることになる。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;2つの選択肢がある場合、難しい方を選べ&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="ジェフベゾス"&gt;ジェフ・ベゾス&lt;/h2&gt;
&lt;p&gt;アマゾンの創業者でありCEOであるジェフ・ベゾス。アマゾンのアイデアを当時在籍していた会社の新事業として立ち上げるのか、起業して自分のビジネスとして立ち上げるのかを悩んだときに、次のように考えて決断したそうです。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;「いろいろ悩みに悩んでいると、細かな部分にとらわれてわけがわからなくなったりします。でもたとえば、80歳になったとき、１９９４年の半ばという最悪のタイミングでウォールストリートの会社を辞め、ボーナスをもらいそこねたなぁと思いだすことはありえません。そんなの、80歳にもなってくよくよすることではありませんからね。逆に、このインターネットというもの、世界を変える原動力になると思ったものに身を投じなかった場合、あのときやっておけばよかったと心から後悔する可能性があると思いました。こう考えると……決断は簡単でした」&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;この考え方は書籍で「後悔最小化理論なるもの」表現されています。&lt;/p&gt;
&lt;h2 id="結論"&gt;結論&lt;/h2&gt;
&lt;p&gt;後悔が小さくなるような難しいほうを選べばおk。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4274065979/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/81hFpVptJpL._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;ハッカーと画家 コンピュータ時代の創造者たち&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/4822249816/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/714KYH2ULpL._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;ジェフ・ベゾス 果てなき野望&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;</description></item><item><title>tmuxやscreenでも使えるpopd、pushdの強化版</title><link>https://blog.piyo.tech/posts/2014-01-28-232914/</link><pubDate>Tue, 28 Jan 2014 23:29:14 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-28-232914/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7466c0c6-0d9f-4eab-a98b-602cc346dba4/c9c22109577c7b5b71595fcd77c42d58/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-25-22-04.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ターミナルでのディレクトリ移動は毎回タイプして頑張ってたんですがいよいよそれも面倒に思えて来ました。最終的に便利なものに出会ったのでそれを紹介します。&lt;/p&gt;
&lt;h2 id="pushdpopd"&gt;pushd、popd&lt;/h2&gt;
&lt;p&gt;まず、僕が知っていた方法である、シェルの組み込みのコマンドの&lt;code&gt;pushd&lt;/code&gt; &lt;code&gt;popd&lt;/code&gt;を考えてみました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pushd → 引数に渡したディレクトリをディレクトリスタック（履歴のようなもの）に入れる&lt;/li&gt;
&lt;li&gt;popd → ディレクトリスタックに最後に追加したディレクトに移動する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;さっきまで作業していたディレクトリに戻るなどの一部のケースではこのコマンドでも十分やっていけるなーと思っていたものの使ってはいなかったので、これで行ってみよう！と思ったんですが、この&lt;code&gt;pushd&lt;/code&gt; &lt;code&gt;popd&lt;/code&gt;だと問題があることがわかりました。&lt;/p&gt;
&lt;p&gt;普段ターミナルを使うときはtmuxを使って複数セッション？っていうんですかね、複数の窓を立ちあげて使っています。pushdやpopdは各ウィンドウごとに独立しているみたいで、別のウィンドウで&lt;code&gt;pushd&lt;/code&gt;したディレクトリには&lt;code&gt;popd&lt;/code&gt;できないようです。&lt;/p&gt;
&lt;p&gt;ナンテコッタイ／(^o^)＼&lt;/p&gt;
&lt;h2 id="ググったらあったよ"&gt;ググったらあったよ！&lt;/h2&gt;
&lt;p&gt;もっといいのがありました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/rcmdnk/sd_cl"&gt;rcmdnk/sd_cl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GitHubで公開している方がいたのでそのまま利用させてもらいました。&lt;/p&gt;
&lt;h3 id="元記事"&gt;元記事&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://rcmdnk.github.io/blog/2013/12/27/computer-bash-zsh-sd-cl/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://rcmdnk.github.io/blog/2013/12/27/computer-bash-zsh-sd-cl/" alt="ターミナルでのディレクトリ移動を保存、取り出しする #screen - rcmdnk's blog" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://rcmdnk.github.io/blog/2013/12/27/computer-bash-zsh-sd-cl/"&gt;ターミナルでのディレクトリ移動を保存、取り出しする #screen - rcmdnk&amp;rsquo;s blog&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://rcmdnk.github.io/blog/2013/12/27/computer-bash-zsh-sd-cl/" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://rcmdnk.github.io/blog/2013/12/27/computer-bash-zsh-sd-cl/" alt="はてなブックマーク - ターミナルでのディレクトリ移動を保存、取り出しする #screen - rcmdnk's blog" title="はてなブックマーク - ターミナルでのディレクトリ移動を保存、取り出しする #screen - rcmdnk's blog" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;h3 id="インストールと設定"&gt;インストールと設定&lt;/h3&gt;
&lt;p&gt;インストールにはHomebrewが使えます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ brew tap rcmdnk/rcmdnkpac
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ brew install sd_cl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;.bashrc&lt;/code&gt; に追記が必要です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;source /usr/local/etc/sd_cl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="使い方"&gt;使い方&lt;/h3&gt;
&lt;p&gt;保存して置いたディレクトリを選ぶのにいくつか方法があります。個人的には&lt;code&gt;$ cl -c&lt;/code&gt;で一覧表示したディレクトリ一覧からvi風の&lt;code&gt;j&lt;/code&gt;、&lt;code&gt;k&lt;/code&gt;で選択して移動というのが超いけてます。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ディレクトリを保存する&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ sd &lt;span style="color:#75715e"&gt;# カレントディレクトリを保存&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;最後に保存したディレクトリに移動&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ cl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;最後からN番目のディレクトリに移動&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ cl -n N
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;保存ディレクトリ一覧表示&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ cl -l
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;一覧から選択して移動&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-placeholder" data-lang="placeholder"&gt;$ cl -c
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;クリア&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ cl -C
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Xcode5でのiOSアプリの起動イメージ設定方法と注意点</title><link>https://blog.piyo.tech/posts/2014-01-27-222501/</link><pubDate>Mon, 27 Jan 2014 22:25:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-27-222501/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/2d342f01-367e-499a-a121-71af2dd91824/4701b9334fb41abf00a69d8aed78a7e2/deep/0/imgres-1.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;最近のiOS開発者の方にとっては当たり前の話かもしれませんが、起動画面の画像が変わっていない現象に出くわしたので残しておきます。&lt;/p&gt;
&lt;h2 id="そもそもどうやって設定するのか"&gt;そもそもどうやって設定するのか？&lt;/h2&gt;
&lt;p&gt;まず起動用画像用意します。今回は3.5インチ、4インチのRetina用を用意。特にXcodeプロジェクトに含める必要はありません。&lt;/p&gt;
&lt;p&gt;そしてターゲットの設定画面から&lt;code&gt;Launch Images&lt;/code&gt;のところにある矢印を押します。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/908b886a-f4d5-4c68-b49d-1e1b333d68ef/d97a6fd577babbd6b28163a5eff0bdff/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-24-20-38.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;するとこんな画面に。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/685ae478-272d-478e-8b7f-fd0136e6ca75/f69ae45e798374d7fa80018ef2929453/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-24-20-42.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;2x&lt;/code&gt; という枠と&lt;code&gt;R4&lt;/code&gt;という枠があるのでここに用意しておいた画像をドロップします。ファイル名は何でもよさそうですが画像のサイズは規定通りでないといけません。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;2x&lt;/code&gt; =&amp;gt; 640x960&lt;/li&gt;
&lt;li&gt;&lt;code&gt;R4&lt;/code&gt; =&amp;gt; 640x1136&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="以前との変更点"&gt;以前との変更点&lt;/h2&gt;
&lt;p&gt;以前はプロジェクトに&lt;code&gt;Default@2x.png&lt;/code&gt;などという名前でファイルを置いておけばよかったと思いますが、Xcode5から（？）は明示的に&lt;code&gt;Launch Images&lt;/code&gt;のところに設定してあげないといけないようです。その代わりに画像の扱いがシンプルになったり複数の画像セットを切り替えたりできるようになりました。&lt;/p&gt;
&lt;p&gt;最近うっかりやってしまったのは起動用画像ファイルを更新するにはファイルの上書きをするだけでOKと思い込んでいて実際には反映されていない、というやつです。改めて新しいファイルをアセット画面にドロップして反映できました。&lt;/p&gt;</description></item><item><title>mp4などをGIFに変換するシェルスクリプト改変版</title><link>https://blog.piyo.tech/posts/2014-01-26-184605/</link><pubDate>Sun, 26 Jan 2014 18:45:27 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-26-184605/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/721f3ae4-cbdc-4ee8-8f37-38adc390eac0/202d620df682dbd87f9daa428f4d61e7/deep/0/ffmpeg-logo.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;キャプチャ動画をブログに貼るときはGIFに変換して貼るのですが、Photoshopを使ってGIF書き出しをやっていてすごく手間だなぁと思っていたときにちょうど見かけたid:shu223さんのこちらの記事。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://d.hatena.ne.jp/shu223/20140108/1389145175"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://d.hatena.ne.jp/shu223/20140108/1389145175" alt="シェルスクリプトでmp4からアニメーションgifを生成する - Over&amp;Out その後" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://d.hatena.ne.jp/shu223/20140108/1389145175"&gt;シェルスクリプトでmp4からアニメーションgifを生成する - Over&amp;amp;Out その後&lt;/a&gt;&lt;a href="http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/shu223/20140108/1389145175" target="_blank" rel="nofollow"&gt;&lt;img src="https://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/shu223/20140108/1389145175" alt="はてなブックマーク - シェルスクリプトでmp4からアニメーションgifを生成する - Over&amp;Out その後" title="はてなブックマーク - シェルスクリプトでmp4からアニメーションgifを生成する - Over&amp;Out その後" style="border:none" /&gt;&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;ここで紹介されていたスクリプトを少し改変してもう少し自由度を高くしてみました。&lt;/p&gt;
&lt;h2 id="必要なコマンドのインストール"&gt;必要なコマンドのインストール&lt;/h2&gt;
&lt;p&gt;詳しい手順は引用記事にお任せして、箇条書きで書いておきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$ brew install ffmpeg&lt;/code&gt; でffmpegをインストール&lt;/li&gt;
&lt;li&gt;&lt;a href="https://xquartz.macosforge.org/"&gt;https://xquartz.macosforge.org/&lt;/a&gt; から XQuartzをインストール&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ brew install gifsicle&lt;/code&gt; でgifsicleをインストール&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="gifmakershを作成"&gt;gifmaker.shを作成&lt;/h2&gt;
&lt;p&gt;パスが通っている場所にスクリプトを置きます。&lt;/p&gt;
&lt;script src="https://gist.github.com/pi-chan/8557946.js"&gt;&lt;/script&gt;
&lt;p&gt;元記事と異なるのは、変換後の動画サイズを固定ではなく可変（元動画を拡大、縮小する形）にしたところです。&lt;/p&gt;
&lt;p&gt;こんなふうに使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ gifmaker.sh &lt;span style="color:#f92672"&gt;[&lt;/span&gt;対象ファイル&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;拡大/縮小率（パーセント）&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;$ gifmaker.sh capture.mov &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;少しわかりづらいところはこの部分かな。元動画のサイズを調べたあと引数のパーセンテージを掛けて変換後のサイズを算出しています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ffmpeg -i [動画ファイル] とやるとファイルの情報が標準エラーに出るのでそのテキストを解析して幅と高さを得る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;WIDTH&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;ffmpeg -i &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$SRC&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; 2&amp;gt;&amp;amp;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &amp;gt; /dev/null | grep Stream | grep -o &lt;span style="color:#e6db74"&gt;&amp;#34;[1-9][0-9]\+x[1-9][0-9]\+&amp;#34;&lt;/span&gt; | cut -d x -f1&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;HEIGHT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;ffmpeg -i &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$SRC&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; 2&amp;gt;&amp;amp;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &amp;gt; /dev/null | grep Stream | grep -o &lt;span style="color:#e6db74"&gt;&amp;#34;[1-9][0-9]\+x[1-9][0-9]\+&amp;#34;&lt;/span&gt; | cut -d x -f2&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 引数の拡大/縮小率を掛けあわせて変換後のサイズを得る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;WIDTH&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;expr $WIDTH &lt;span style="color:#ae81ff"&gt;\*&lt;/span&gt; $RATIO / 100&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;HEIGHT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;expr $HEIGHT &lt;span style="color:#ae81ff"&gt;\*&lt;/span&gt; $RATIO / 100&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 計算したサイズを使って変換！&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;ffmpeg -loglevel panic -ss &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; -i &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$SRC&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; -r &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt; -an -f image2 -s &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$WIDTH&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;x&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$HEIGHT&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;./temp/%03d.gif&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここまでやっておけば、キャプチャしたmovなどの動画を縮小しつつGIFアニメにできますね。我ながら便利。&lt;/p&gt;</description></item><item><title>iPhone用タブ付ページめくりコントロール</title><link>https://blog.piyo.tech/posts/2014-01-25-204607/</link><pubDate>Sat, 25 Jan 2014 20:45:35 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-25-204607/</guid><description>&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/0QFvXgBR9PJ25y0QhsWeZKaqacaLdICOIpsRgJJQxuL7O4-kNRQ1yEdhihrvFjAgsxJTdUvwKcYWXVEtLnaAtaz-GwQ2eFSSFcRK_Xu_W8-5sPmwOqNlhh_no951lfACzYWefQsZw7moPliArxkJ5gSsGYZhAl2hlBjVL6H2bsYY1JT1apSFtvvGN5-7LW-Us7VCT1XejWc_xMghC1-_2FD9ozHxe3T88HHSsbpCcbygGOwB_Im4_cNmc6urEiwXoN-ABpWuWjWKo4c0Je-gi3fDGIuuB4qzgdESWo1XbxvMtMogHbGeYOEbYOCj3g7xUamtRFPa6VpmTFrQsS8rPZdCbK5D8A6p_gFqTCGYIsHZbV9ZvC82J_GjBAaT1Lr-VHn5dSFaQF00djPOM7iKaZ2tsDoul4MDihWUJaUlOi5eDjFU6d1D5X6l2R43oK4Wbmtnzmm1qUAT8ESv_dT8_2TyqRE8SDQ11CrRbCjWO6_DHMs_te20r0nbZffIIqUiJJ4F4p4EGdlJqHg-Pw6S2CHOStCRLXopOUd_zbV5oLWep2V4EDpAG5KxdrBE-_zlSNbS5gQafVQOaklp6gDSd_gpvI7Oq5P4h_MiVljcBYOWjvs-MWIJ-ekLjOafF53MEwROcxFUYfL-SfcrmaTWMVF-5vKnwWClMA=w304-h540-no" alt=""&gt;&lt;/p&gt;
&lt;p&gt;iOSには標準でページめくり用のコンポーネントが用意されています。iPhoneのホーム画面のようにページコントロールがあって、左右スワイプでページめくりができるアレです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7d670b62-b498-41ca-a430-bb1e11973bef/c223c796643724013e31f01b60a0fb12/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-22-12-35.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;この機能を実装するためには&lt;code&gt;UIPageViewController&lt;/code&gt;などを使います。ところが実装がめちゃくちゃ面倒くさいんですよ。以前作ったときはいろいろ調べてみつけた英語の記事を参考に実装したんだけど、もう全然覚えていません。リンクだけは残してあったりして。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.appcoda.com/uipageviewcontroller-storyboard-tutorial/"&gt;&lt;img src="https://capture.heartrails.com/150x130/shadow?http://www.appcoda.com/uipageviewcontroller-storyboard-tutorial/" alt="How To Create UIPageViewController in Storyboard | iOS Programming" style="border:none;float:left;margin:0 .5em .5em 0;" /&gt;&lt;/a&gt;&lt;a href="http://www.appcoda.com/uipageviewcontroller-storyboard-tutorial/"&gt;How To Create UIPageViewController in Storyboard | iOS Programming&lt;/a&gt;&lt;br style="clear:left;"&gt;&lt;/p&gt;
&lt;p&gt;で、嫌気がさしてCocoaControlsを漁っていたらページコントロール系のPodを見つけたので試してみました。実装方法は標準のUIPageViewControllerに近いところもあるのですが、わりといい感じかもしれないのでレポります。&lt;/p&gt;
&lt;h2 id="icviewpager"&gt;ICViewPager&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/monsieurje/ICViewPager"&gt;monsieurje/ICViewPager&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;サンプルプロジェクトをSingle View Applicationとして作成しICViewPagerを使ってみます。最初にSingle View Applicationを作っておきます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0d7361d1-dd9b-4eb2-8981-6096a4eb58ba/84799cc5aad3df562a4ad71a30ca3f16/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-22-12-52.png" alt=""&gt;&lt;/p&gt;
&lt;h3 id="インストール"&gt;インストール&lt;/h3&gt;
&lt;p&gt;CocoaPodsでインストールし、xcworkspaceを開きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ vi Podfile
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;ICViewPager&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;$ pod install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="controllerクラスを追加"&gt;Controllerクラスを追加&lt;/h3&gt;
&lt;p&gt;ページ全体を管理するPageControllerクラスと、各ページのViewを担当するContentViewControllerを用意します。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/906e060c-6a4d-4ac2-84aa-d3d643432379/5448c25bea38a7ec2c07c1fb98cfac7f/deep/0/icviewpager.xcworkspace---ContentViewController.m.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PageController&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PageControllerはICViewPagerの&lt;code&gt;ViewPagerController&lt;/code&gt;のサブクラスにし、デリゲートとデータソースを実装するようにプロトコルを継承しておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;#34;ViewPagerController.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PageController&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;ViewPagerController&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;ViewPagerDataSource,ViewPagerDelegate]]&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;ContentViewController&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;こいつは普通のViewControllerで良いです。&lt;/p&gt;
&lt;h3 id="storyboardでやること"&gt;storyboardでやること&lt;/h3&gt;
&lt;p&gt;最初からあるViewControllerのカスタムクラスを&lt;code&gt;PageController&lt;/code&gt;に、新しく追加したUIViewControllerのカスタムクラスを&lt;code&gt;ContentViewController&lt;/code&gt;にします。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/6f1df41f-bbe9-4ef5-b2c3-c20c562eb06d/6077bbeb8a76692d601724b730b304e7/deep/0/icviewpager.xcworkspace---Main.storyboard.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;また、後でコードから呼び出すためにContentViewControllerのほうは&lt;code&gt;Storyboard ID&lt;/code&gt;にも同じ名前を付けておきます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/febad66c-3491-40ab-b715-4432c1851eff/3c0ad77943e246cfd7843a5a23b30a1e/deep/0/icviewpager.xcworkspace---Main.storyboard.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ページめくりを確認するために申し訳程度にラベルを置いておきました。このラベルをソースから変更できるようにIBOutletとして&lt;code&gt;ContentViewController&lt;/code&gt;と紐付けておきます。また、ラベルに描画するテキストを一時的に置いておくための&lt;code&gt;NSString&lt;/code&gt;のプロパティも1つ用意しておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;UIKit/UIKit.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ContentViewController&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;UIViewController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;IBOutlet&lt;/span&gt; UILabel &lt;span style="color:#f92672"&gt;*&lt;/span&gt;label;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt; labelText;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="あとはコードで"&gt;あとはコードで&lt;/h3&gt;
&lt;p&gt;データソース、デリゲートに自分自身を設定します。必須なのはデータソースのメソッドのみですのでそれを実装します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// PageController.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; [super viewDidLoad];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Do any additional setup after loading the view.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; self.dataSource &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; self.delegate &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;- (NSUInteger)&lt;span style="color:#a6e22e"&gt;numberOfTabsForViewPager:&lt;/span&gt;(ViewPagerController &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)viewPager
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// タブの数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;- (UIView &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewPager:&lt;/span&gt;(ViewPagerController &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)viewPager &lt;span style="color:#a6e22e"&gt;viewForTabAtIndex:&lt;/span&gt;(NSUInteger)index
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// タブに表示するView、今回はUILabelを使用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; UILabel&lt;span style="color:#f92672"&gt;*&lt;/span&gt; label &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [UILabel new];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; label.text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSString stringWithFormat:&lt;span style="color:#e6db74"&gt;@&amp;#34;Tab #%i&amp;#34;&lt;/span&gt;, index];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; [label sizeToFit];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; label;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;- (UIViewController &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewPager:&lt;/span&gt;(ViewPagerController &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)viewPager &lt;span style="color:#a6e22e"&gt;contentViewControllerForTabAtIndex:&lt;/span&gt;(NSUInteger)index
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// タブ番号に対応するUIViewControllerを返す
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; ContentViewController&lt;span style="color:#f92672"&gt;*&lt;/span&gt; contentViewController &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [self.storyboard instantiateViewControllerWithIdentifier:&lt;span style="color:#e6db74"&gt;@&amp;#34;ContentViewController&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; contentViewController.labelText &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSString stringWithFormat:&lt;span style="color:#e6db74"&gt;@&amp;#34;Tab #%i&amp;#34;&lt;/span&gt;, index];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; contentViewController;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最後に &lt;code&gt;ContentViewController&lt;/code&gt;の&lt;code&gt;viewDidLoad&lt;/code&gt;でラベルのテキストを更新してあげれば完了です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; [super viewDidLoad];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Do any additional setup after loading the view.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; self.label.text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self.labelText;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最初に紹介したアニメーション画像が完成したサンプルにあたります。&lt;/p&gt;
&lt;p&gt;ソースコードはここ→&lt;a href="https://github.com/pi-chan/icviewpager-sample"&gt;pi-chan/icviewpager-sample&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="その他にできること"&gt;その他にできること&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;タブを画面下に&lt;/li&gt;
&lt;li&gt;選択中のタブの色&lt;/li&gt;
&lt;li&gt;タブの背景色&lt;/li&gt;
&lt;li&gt;タブの大きさ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などなど、いくつかカスタマイズも可能です。&lt;/p&gt;</description></item><item><title>YouTubeAPI超入門 使い始めから検索まで</title><link>https://blog.piyo.tech/posts/2014-01-24-212903/</link><pubDate>Fri, 24 Jan 2014 21:28:27 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-24-212903/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/f77c3994-3213-4d1e-82f7-dc265c4c49b8/65746f3137dee5dfbca9c8b01e6458e1/deep/0/imgres.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;YouTubeのAPIを使えるようになるまでがめちゃくちゃわかりづらかったので、メモに残しておかないとやばいと思いました。&lt;/p&gt;
&lt;p&gt;今回はPublicなデータにアクセスするための手順について書きます。OAuthについては触れません。&lt;/p&gt;
&lt;h2 id="キーを取得しよう"&gt;キーを取得しよう&lt;/h2&gt;
&lt;p&gt;まず、&lt;a href="https://cloud.google.com/console/project"&gt;Google Developers Console&lt;/a&gt;へ行ってアプリケーションを作ってキーを取得する必要があります。&lt;/p&gt;
&lt;p&gt;コンソールの&lt;code&gt;CREATE PROJECT&lt;/code&gt;ボタンを押して、名前を決めてプロジェクトを作ります。1回目は規約に同意するかどうかのチェックボックスがありますが、2回目いこうは省略されます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/19aa1c41-32a4-43f9-8396-bd3df4cd5482/54948441e799b080df5ce5ddbafce141/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-21-10-14.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/da8bd47d-2ea7-4cfd-9386-f1b7a60fa845/3e11bb5f14c6fa80820d2983017b553a/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-21-10-15.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;そして、&lt;code&gt;YouTube Data API v3&lt;/code&gt;をONにします。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/a4b153b0-8566-416c-acff-259fd177ffb9/ad7e79097e9f24357e0e15e755ebec47/deep/0/Google-Developers-Console.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;次にAPIアクセスようのキーを発行します。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/ddf7da96-06a4-4eba-99c4-ec9f6b570903/8d6688a135423e5bd67cdbf76666cdc5/deep/0/Google-Developers-Console.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;クライアント毎にアプリケーションキーを分けることができるようです。次の種類から選ぶことができます。ここではiOSを選んでみます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Server key&lt;/li&gt;
&lt;li&gt;Browser key&lt;/li&gt;
&lt;li&gt;Android key&lt;/li&gt;
&lt;li&gt;iOS key&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/eb5ec69b-63ae-4700-9b73-902d2375ff6c/fb49c94bd6c18f260c6b24a867b5fbc3/deep/0/Google-Developers-Console.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;こんな風にキーが発行されました。&lt;code&gt;API key&lt;/code&gt;という欄に書かれている文字列がキーです。APIで問い合わせる際にこのキーを使用します。&lt;/p&gt;
&lt;h2 id="ビデオを取得する"&gt;ビデオを取得する&lt;/h2&gt;
&lt;p&gt;ビデオ取得のやりかたをいくつかのパターンで試してみます。&lt;/p&gt;
&lt;p&gt;リファレンスはこれ。&lt;a href="https://developers.google.com/youtube/v3/docs/videos/list"&gt;Videos: list - YouTube — Google Developers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;APIキーと検索キーワードを使って動画の検索ができます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https://www.googleapis.com/youtube/v3/search?key={YOUR_API_KEY}&amp;amp;q={SEARCH_TERM}&amp;amp;part=id&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;例えばサッカーと検索したい場合は&lt;code&gt;q=サッカー&lt;/code&gt;としてリクエストを投げます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// https://www.googleapis.com/youtube/v3/search?key={YOUR_API_KEY}&amp;amp;q=サッカー&amp;amp;part=id
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// jsonレスポンス
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;youtube#searchListResponse&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;etag&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\&amp;#34;qQvmwbutd8GSt4eS4lhnzoWBZs0/lGGCM9oSIhJS2gnOaQu1RjEiDx8\&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;nextPageToken&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;CAUQAA&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;pageInfo&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;totalResults&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000000&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;resultsPerPage&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;items&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;youtube#searchResult&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;etag&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\&amp;#34;qQvmwbutd8GSt4eS4lhnzoWBZs0/RGl-lf1mZjCqGo-FbFwvgjAY6B0\&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;youtube#video&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;videoId&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;lwYgdBQ0k3U&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="nextpagetoken"&gt;nextPageToken&lt;/h3&gt;
&lt;p&gt;デフォルトでは1ページあたり5件の結果が返ってきます。続きの結果を得たい場合には最初のレスポンスにあった&lt;code&gt;nextPageToken&lt;/code&gt;を使って次のようなリクエストをします。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https://www.googleapis.com/youtube/v3/search?key={YOUR_API_KEY}&amp;amp;q=サッカー&amp;amp;part=id&amp;amp;pageToken=CAUQAA&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;こうすると2ページ目の結果が得られた上、新たな&lt;code&gt;nextPageToken&lt;/code&gt;や前のページのための&lt;code&gt;prevPageToken&lt;/code&gt;が得られるようになります。結果を次々に取ってきたい場合はこのtokenを使って繰り返しリクエストしていけばOK。&lt;/p&gt;
&lt;h3 id="maxresults"&gt;maxResults&lt;/h3&gt;
&lt;p&gt;1回のリクエストあたり5件だとまどろっこしい、100件ぐらい持ってこいと思った場合は&lt;code&gt;maxResults&lt;/code&gt;パラメータを使います。&lt;/p&gt;
&lt;p&gt;URLの最後に&lt;code&gt;&amp;amp;maxResults=100&lt;/code&gt;に問い合わせてみると、、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;errors&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;domain&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;global&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;reason&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;invalidParameter&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Invalid value &amp;#39;100&amp;#39;. Values must be within the range: [0, 50]&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;locationType&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;parameter&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;location&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;maxResults&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;code&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;400&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Invalid value &amp;#39;100&amp;#39;. Values must be within the range: [0, 50]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;怒られた…。最大50件まででした。&lt;/p&gt;
&lt;h3 id="part"&gt;part&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;part=id&lt;/code&gt;となっているところを変えるとレスポンスで返ってくるパラメータを変えることができます。カンマ区切りで複数指定できます。&lt;/p&gt;
&lt;p&gt;例えば&lt;code&gt;part=id,snippet&lt;/code&gt;としてみると、、、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// https://www.googleapis.com/youtube/v3/search?key={YOUR_API_KEY}&amp;amp;q=サッカー&amp;amp;part=id,snippet
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// レスポンス
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;youtube#searchListResponse&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;etag&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\&amp;#34;qQvmwbutd8GSt4eS4lhnzoWBZs0/TvUA3aT9bg7gzx72UgdpWtsjAD0\&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;nextPageToken&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;CAUQAA&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;pageInfo&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;totalResults&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000000&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;resultsPerPage&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;items&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;youtube#searchResult&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;etag&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\&amp;#34;qQvmwbutd8GSt4eS4lhnzoWBZs0/YNAKTLX6SbYCco99EQWCyVDIxCo\&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;youtube#video&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;videoId&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;lwYgdBQ0k3U&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;snippet&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;publishedAt&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;2013-10-04T05:16:29.000Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;channelId&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;UCZfWmiGEbwWNPMe2nr3WdDg&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;【WOWOW】U-12ジュニアサッカーワールドチャレンジ2013 FCバルセロナ ダイジェスト&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;U-12ジュニアサッカーワールドチャレンジ2013 FCバルセロナ ダイジェスト ☆U-12 Junior soccer world challenge 2013 FC Barcerona Infantil B digest 2013年8月27 ...&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;thumbnails&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://i.ytimg.com/vi/lwYgdBQ0k3U/default.jpg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;medium&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://i.ytimg.com/vi/lwYgdBQ0k3U/mqdefault.jpg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;high&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://i.ytimg.com/vi/lwYgdBQ0k3U/hqdefault.jpg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;channelTitle&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;WOWOWofficial&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;liveBroadcastContent&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;none&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;42&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;43&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;44&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;45&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;動画のタイトルやサムネイルのURLなど、詳細な情報を得られるようになりました。&lt;/p&gt;
&lt;p&gt;もっといろいろな使い方ができるのですがここまでわかればあとはリファレンスを見てなんとかできるのでは。&lt;/p&gt;</description></item><item><title>RubyでGrowlに通知を出してみる</title><link>https://blog.piyo.tech/posts/2014-01-23-205003/</link><pubDate>Thu, 23 Jan 2014 20:49:27 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-23-205003/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/59094b16-88db-4f6c-a308-ca190242f67a/0c4a0c97d3d385e993d32477518f19e2/deep/0/images.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Growl、有料になっちゃったけど使ってます。guardで監視してrspec動かしたり、重いコマンドが終わったら通知させたり。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://cflat-inc.hatenablog.com/entry/20130610/1370821289"&gt;実行時間の長いコマンドの終了をGrowlやメール通知するRubyスクリプト - 株式会社CFlatの明後日スタイルのブログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;とある用途で、いくつかの候補からランダムで選択した文字列を定期的に出したいなーと思ったのでRubyで書いてみました。&lt;/p&gt;
&lt;p&gt;Growlが入っていることが前提です。また、定期的にスクリプトを起動するのは&lt;code&gt;launchctl&lt;/code&gt;を使うのが定番らしいのでそれでやりますが、ここでは割愛。&lt;/p&gt;
&lt;h2 id="growlnotifyを使う場合"&gt;growlnotifyを使う場合&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://growl.info/downloads"&gt;Growl - Downloads&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;コマンドラインからGrowlに通知を投げるコマンドで、上のURLからダウンロードできます。コマンド終了通知にはこれを使ってます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b7a39bf9-9e17-4b91-b827-c63a403dbb85/f71956aa340d383bc568df306ed8ebaf/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-17-22-29.png" alt=""&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ growlnotify -n &lt;span style="color:#e6db74"&gt;&amp;#39;Terminal&amp;#39;&lt;/span&gt; -t &lt;span style="color:#e6db74"&gt;&amp;#39;bash&amp;#39;&lt;/span&gt; -m &lt;span style="color:#e6db74"&gt;&amp;#39;hogehoge&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# -n アプリケーション名&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# -t タイトル&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# -m 表示メッセージ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これを利用すれば簡単に実現できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;texts &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hogehogehogehoge&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fugafugafugafuga&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;piyopiyopiyopiyo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;system &lt;span style="color:#e6db74"&gt;&amp;#34;growlnotify -n &amp;#39;MyApp&amp;#39; -t &amp;#39;Notification&amp;#39; -m &amp;#39;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;texts&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sample&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="gemを使う場合"&gt;gemを使う場合&lt;/h2&gt;
&lt;p&gt;Growl連携用のgemがあります。それは&lt;code&gt;ruby-growl&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;growlnotify&lt;/code&gt; コマンドと同じぐらいシンプルに使えます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;ruby-growl&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;texts &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hogehogehogehoge&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fugafugafugafuga&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;piyopiyopiyopiyo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;growl &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Growl&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new &lt;span style="color:#e6db74"&gt;&amp;#34;localhost&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;MyApp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;growl&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_notification(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;notification_name&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;hoghoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;growl&lt;span style="color:#f92672"&gt;.&lt;/span&gt;notify &lt;span style="color:#e6db74"&gt;&amp;#34;notification_name&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Notification&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;texts&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sample&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/8f744594-97a5-4cf3-b238-277c4488e440/423203a09c56e1e854f2234cd2095293/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-17-22-46.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>Feedzirraのupdateメソッドを読み解く</title><link>https://blog.piyo.tech/posts/2014-01-22-211107/</link><pubDate>Wed, 22 Jan 2014 21:10:32 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-22-211107/</guid><description>&lt;p&gt;少し前にRSSフィードをパースするgem、Feedzirraの紹介記事で次のようなことを書きました。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;そうすると&lt;code&gt;update&lt;/code&gt;メソッドが使えるようになります。このような流れで更新された記事だけを取り出すことができるようになりました。&lt;/p&gt;
&lt;p&gt;なお、&lt;code&gt;Feedzirra::Parser::RSS&lt;/code&gt;以外にも&lt;code&gt;Feedzirra::Parser::Atom&lt;/code&gt;などのパーサーがあるのですが、違うフォーマットでもいい感じにやってくれるから大丈夫！という旨がこちらのコメントで確認できます。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/a/2487826/2289849"&gt;rss - Ruby - Feedzirra and updates - Stack Overflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ソース読めばわかるんでしょうがまだ読んでいないという。今度読みます。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;なので、早速ソースコードを読んでみました。&lt;/p&gt;
&lt;h2 id="何を調べるのか"&gt;何を調べるのか？&lt;/h2&gt;
&lt;p&gt;整理すると、フィードの更新の際に用意するパーサーオブジェクトが&lt;code&gt;Feedzirra::Parser::RSS&lt;/code&gt;であろうが&lt;code&gt;Feedzirra::Parser::Atom&lt;/code&gt;だろうが、どんなフォーマットのフィードでも更新できるらしいが、それはなぜかというところです。&lt;/p&gt;
&lt;h2 id="そもそも新規の取得時は"&gt;そもそも新規の取得時は？&lt;/h2&gt;
&lt;p&gt;新規取得のときはこのような使い方をします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;feed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Feedzirra&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Feed&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fetch_and_parse(feed_urls&lt;span style="color:#f92672"&gt;.&lt;/span&gt;first)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この&lt;code&gt;fetch_and_parse&lt;/code&gt;が何をしているのかを追ってみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# feed.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;fetch_and_parse&lt;/span&gt;(urls, options &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; url_queue&lt;span style="color:#f92672"&gt;.&lt;/span&gt;slice!(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;url&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; add_url_to_multi(multi, url, url_queue, responses, options)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ... &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;add_url_to_multi&lt;/span&gt;(multi, url, url_queue, responses, options)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ... &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; klass &lt;span style="color:#f92672"&gt;=&lt;/span&gt; determine_feed_parser_for_xml(xml)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ... &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;determine_feed_parser_for_xml&lt;/span&gt;(xml)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; start_of_doc &lt;span style="color:#f92672"&gt;=&lt;/span&gt; xml&lt;span style="color:#f92672"&gt;.&lt;/span&gt;slice(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2000&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; feed_classes&lt;span style="color:#f92672"&gt;.&lt;/span&gt;detect {&lt;span style="color:#f92672"&gt;|&lt;/span&gt;klass&lt;span style="color:#f92672"&gt;|&lt;/span&gt; klass&lt;span style="color:#f92672"&gt;.&lt;/span&gt;able_to_parse?(start_of_doc)}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;お！どのパーサー使うか、というような話がでてきました。&lt;code&gt;fetch_and_parse&lt;/code&gt;の奥でパース直前にフィードのXMLからパーサーを特定するようなロジックが入っていました。この&lt;code&gt;determine_feed_parser_for_xml&lt;/code&gt;でRSSフィードのフォーマットに応じて&lt;code&gt;Feedzirra::Parser::RSS&lt;/code&gt;や&lt;code&gt;Feedzirra::Parser::Atom&lt;/code&gt;などが返ってくるようです。&lt;/p&gt;
&lt;h2 id="更新のとき"&gt;更新のとき&lt;/h2&gt;
&lt;p&gt;更新のときはこう使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;feed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Feedzirra&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Parser&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;RSS&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ... &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Feedzirra&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Feed&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;update(feed)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この&lt;code&gt;update&lt;/code&gt;を追ってみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;update&lt;/span&gt;(feeds, options &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; feed_queue&lt;span style="color:#f92672"&gt;.&lt;/span&gt;slice!(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;feed&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; add_feed_to_multi(multi, feed, feed_queue, responses, options)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;add_feed_to_multi&lt;/span&gt;(multi, feed, feed_queue, responses, options)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; updated_feed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Feed&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;parse(c&lt;span style="color:#f92672"&gt;.&lt;/span&gt;body_str)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;parse&lt;/span&gt;(xml)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; parser &lt;span style="color:#f92672"&gt;=&lt;/span&gt; determine_feed_parser_for_xml(xml)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; parser&lt;span style="color:#f92672"&gt;.&lt;/span&gt;parse(xml)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;raise&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NoParserAvailable&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#e6db74"&gt;&amp;#34;No valid parser for XML.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここでもまた&lt;code&gt;determin_feed_parser_for_xml&lt;/code&gt;が呼ばれてた！&lt;/p&gt;
&lt;p&gt;そういうわけで、どのクラスを渡しても実際のパース前に適切なロジックが選択されることに間違いないということがわかりました。&lt;/p&gt;
&lt;p&gt;よかった。すっきりしました。&lt;/p&gt;</description></item><item><title>DashとXcodeで一発リファレンス検索</title><link>https://blog.piyo.tech/posts/2014-01-21-225446/</link><pubDate>Tue, 21 Jan 2014 22:54:46 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-21-225446/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/37744abc-968f-49a8-95cc-4ae7c1f3e027/2be092167e0a900c102e1fbfa599bdc4/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-17-11-18.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;先日AlfredとDashで一瞬でリファレンス検索する方法について書きました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-01-03-203206"&gt;Alfred+Dashで秒速リファレンス検索 - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今度はXcodeから一発検索する方法を紹介します。&lt;/p&gt;
&lt;h2 id="dash-plugin-for-xcode"&gt;Dash Plugin for Xcode&lt;/h2&gt;
&lt;p&gt;このプラグインを導入します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/omz/Dash-Plugin-for-Xcode"&gt;omz/Dash-Plugin-for-Xcode&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;インストールは簡単で、GitHubからプロジェクトをダウンロードしてXcodeで開いてビルド、そしてXcodeを再起動するたけです。&lt;/p&gt;
&lt;p&gt;これだけですぐに使えるようになります。&lt;/p&gt;
&lt;p&gt;調べたいメソッドなどを&lt;code&gt;オプションキー+クリック&lt;/code&gt;するとDashで検索してくれます。タイプする時間がかからない分Alfredとの連携よりも早そうです。&lt;/p&gt;
&lt;p&gt;また、キーボードショートカットも使えます。&lt;/p&gt;
&lt;p&gt;僕の環境では&lt;code&gt;Ctrl+Command+?&lt;/code&gt;でした（てことは&lt;code&gt;Ctrl+Command+Shift+/&lt;/code&gt;なんだよね）。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9130f852-4102-42c6-b70c-faaf78acc62a/2c73f2e4e4c319228f26d7a535d42eda/deep/0/Key-Bindings.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;設定からお好みの物に変えればコードを書きながらの流れで検索できてめっちゃよさそう。&lt;/p&gt;</description></item><item><title>RubyでRSSフィードをパースするgem、Feedzirra</title><link>https://blog.piyo.tech/posts/2014-01-20-201703/</link><pubDate>Mon, 20 Jan 2014 20:16:31 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-20-201703/</guid><description>&lt;p&gt;RailsでRSSリーダーを作ったときに得たノウハウ第2弾、RSSフィードのパースのところを書いてみようと思います。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/99f21986-8f73-4e57-a6dd-63d13b62208b/bf94f36ad9448fa25c477f5f9bcca1da/deep/0/imgres.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;第1弾としてこんなん書きました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2014-01-07-203404"&gt;個別ページのURLからRSSフィードURLを取得するfeedbag - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;サイトURLを渡すとHTMLを解析してRSSフィードのURL候補を返してくれるというgemの紹介でした。今回は得られたRSSフィードのURLに情報を取りに行ってパースしてくれるgemを紹介してみようかと思います。&lt;/p&gt;
&lt;h2 id="feedzirra"&gt;Feedzirra&lt;/h2&gt;
&lt;p&gt;これを使います。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pauldix/feedzirra"&gt;pauldix/feedzirra&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;いくつか候補がありました（全部忘れました）が、最も新しくてその上現在進行形で開発が進んでいる風だったこともあってこちらを使用していました。&lt;/p&gt;
&lt;h3 id="初回のフィード取得"&gt;初回のフィード取得&lt;/h3&gt;
&lt;p&gt;GitHubのREADMEにある通りですんなりいけます。折角なのでfeedbagを絡めてみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;feedbag&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;feedzirra&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;feed_urls &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Feedbag&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.piyo.tech/&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# このブログ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;p feed_urls&lt;span style="color:#f92672"&gt;.&lt;/span&gt;first &lt;span style="color:#75715e"&gt;# =&amp;gt; &amp;#34;https://blog.piyo.tech/feed&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;feed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Feedzirra&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Feed&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fetch_and_parse(feed_urls&lt;span style="color:#f92672"&gt;.&lt;/span&gt;first)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;p feed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;title &lt;span style="color:#75715e"&gt;# =&amp;gt; &amp;#34;ぴよログ&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;p feed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;url &lt;span style="color:#75715e"&gt;# =&amp;gt; &amp;#34;https://blog.piyo.tech/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;p feed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;feed_url &lt;span style="color:#75715e"&gt;# =&amp;gt; &amp;#34;https://blog.piyo.tech/feed&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;p feed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;etag &lt;span style="color:#75715e"&gt;# =&amp;gt; &amp;#34;f6ce826cbbd07e222b6cee445fc981f730ad0693&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;p feed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;last_modified &lt;span style="color:#75715e"&gt;# =&amp;gt; 2014-01-15 11:47:34 UTC&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;p feed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;entries&lt;span style="color:#f92672"&gt;.&lt;/span&gt;count &lt;span style="color:#75715e"&gt;# =&amp;gt; 7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こんな風に結構簡単にRSSフィードの解析が終わりました。このブログを対象としてみましたが、7記事分の情報が取れるようですね。それ以前の記事はフィードされていないということになります。&lt;/p&gt;
&lt;h3 id="更新の確認"&gt;更新の確認&lt;/h3&gt;
&lt;p&gt;RSSリーダーというものは、RSSの仕組みのせいでリーダー側からRSS配信元を見に行かなくてはならない、いわゆるプル型のサービスです。そのため、更新されているかどうかもわからないのにRSSフィードを見に行かなくてはなりません。そして更新があれば新しい記事の分だけをサービスに保存する、というようなことを行うことになります。&lt;/p&gt;
&lt;p&gt;この辺りの設計について話しだすと長くなるので、後日書くかもしれません。&lt;/p&gt;
&lt;p&gt;話をFeedzirraに戻します。&lt;/p&gt;
&lt;p&gt;先ほどの例でもわかるように、はてなブログのRSSフィードでは7記事分配信されるようです。ここではあるはてなブログを例に解説を進めます。&lt;/p&gt;
&lt;p&gt;例えば初回取得時と2回目の取得時（つまり更新時）の間に対象のはてなブログに新たに2記事追加されたとします。&lt;/p&gt;
&lt;p&gt;図でいうとこんな感じ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0a012911-f152-4c68-848c-3388686b28fd/ac0928940a5647908af0745994ddc9b1/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-15-21-32.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;先ほど使ったメソッド、&lt;code&gt;fetch_and_parse&lt;/code&gt;を使うと現在のRSSフィードの内容をパースしてそこに載っている記事を全て取得してくることになるので、そのままデータベース等に保存しようとすると記事3〜記事7はダブってしまうことになります。&lt;/p&gt;
&lt;p&gt;普通はそんなの困るのですでに取得済みの記事は除外して新しいものだけを新たに保存したいですよね。自前でやる場合はタイムスタンプ等で判別しなければいけません。&lt;/p&gt;
&lt;p&gt;当然Feedzirraにはそのような方法が用意されています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;feedbag&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#34;feedzirra&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 最初は一緒&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;feed_urls &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Feedbag&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.piyo.tech/&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# このブログ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;p feed_urls&lt;span style="color:#f92672"&gt;.&lt;/span&gt;first &lt;span style="color:#75715e"&gt;# =&amp;gt; &amp;#34;https://blog.piyo.tech/feed&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;feed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Feedzirra&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Feed&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fetch_and_parse(feed_urls&lt;span style="color:#f92672"&gt;.&lt;/span&gt;first)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;p feed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;entries&lt;span style="color:#f92672"&gt;.&lt;/span&gt;count &lt;span style="color:#75715e"&gt;# =&amp;gt; 7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# この瞬間に2記事分更新されたとする（そんなことあり得ないけど）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;updated_feed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Feedzirra&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Feed&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;update(feed)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;updated_feed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;updated? &lt;span style="color:#75715e"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;updated_feed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new_entries&lt;span style="color:#f92672"&gt;.&lt;/span&gt;count &lt;span style="color:#75715e"&gt;# =&amp;gt; 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで更新のときに必要な記事だけ取り出せますね、、と言いたいところですがそうはいきません。&lt;/p&gt;
&lt;h3 id="何がだめ"&gt;何がだめ？&lt;/h3&gt;
&lt;p&gt;先ほどの更新の例では、最初に&lt;code&gt;fetch_and_parse&lt;/code&gt;したときに帰ってきた&lt;code&gt;feed&lt;/code&gt;というオブジェクトが生き残っていて、そのオブジェクトに対して&lt;code&gt;update&lt;/code&gt;メソッドを呼ぶことで更新を確認しています。&lt;/p&gt;
&lt;p&gt;普通に考えて初回取得時に存在していたオブジェクトが、それ以降も存在しているわけはありません。初回のRSSフィード取得が終わったしばらくあと（数時間後とか）にスケジュールされたジョブとして2回目のフィード取得が走るのが普通だからです。&lt;/p&gt;
&lt;p&gt;つまり、&lt;code&gt;feed&lt;/code&gt;に相当するオブジェクトを自分で生成した上で&lt;code&gt;update&lt;/code&gt;を呼んであげる必要があるわけです。取得済みの記事だとかフィードの最終更新などの情報はデータベースなどに入れてあるはずなので、それらの情報から&lt;code&gt;feed&lt;/code&gt;を再作成します。こんな感じで。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;feed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Feedzirra&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Parser&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;RSS&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;feed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;feed_url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.piyo.tech/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;feed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;etag &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;f6ce826cbbd07e222b6cee445fc981f730ad0693&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# いらないかも&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;feed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;last_modified &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;DateTime&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;parse(&lt;span style="color:#e6db74"&gt;&amp;#34;2014-01-15 11:47:34 UTC&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;last_entry &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Feedzirra&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Parser&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;RSSEntry&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;last_entry&lt;span style="color:#f92672"&gt;.&lt;/span&gt;url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;取得済みの記事の中で最も新しいのURLを入れておく&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;feed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;entries &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;last_entry&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Feedzirra&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Feed&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;update(feed)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そうすると&lt;code&gt;update&lt;/code&gt;メソッドが使えるようになります。このような流れで更新された記事だけを取り出すことができるようになりました。&lt;/p&gt;
&lt;p&gt;なお、&lt;code&gt;Feedzirra::Parser::RSS&lt;/code&gt;以外にも&lt;code&gt;Feedzirra::Parser::Atom&lt;/code&gt;などのパーサーがあるのですが、違うフォーマットでもいい感じにやってくれるから大丈夫！という旨がこちらのコメントで確認できます。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/a/2487826/2289849"&gt;rss - Ruby - Feedzirra and updates - Stack Overflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ソース読めばわかるんでしょうがまだ読んでいないという。今度読みます。&lt;/p&gt;</description></item><item><title>笑顔やまばたきも！iPhoneカメラでカンタン顔認識</title><link>https://blog.piyo.tech/posts/2014-01-19-210806/</link><pubDate>Sun, 19 Jan 2014 21:07:33 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-19-210806/</guid><description>&lt;p&gt;iOS5から使えるようになった&lt;code&gt;CIDetector&lt;/code&gt;がiOS7で更に進化し、笑顔やまばたき（目をつぶっているかどうか）を検出可能となりました。&lt;/p&gt;
&lt;p&gt;すごく簡単に実装できる上に処理も遅くないのでいろいろな使い道があると思います。&lt;/p&gt;
&lt;h2 id="下準備"&gt;下準備&lt;/h2&gt;
&lt;p&gt;まずCoreImageフレームワークをプロジェクトに追加しておきます。&lt;/p&gt;
&lt;h2 id="検出"&gt;検出&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;CIDetector &lt;span style="color:#f92672"&gt;*&lt;/span&gt;detector &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [CIDetector detectorOfType:CIDetectorTypeFace
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; context:nil
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; options:&lt;span style="color:#ae81ff"&gt;@{&lt;/span&gt;CIDetectorAccuracy: CIDetectorAccuracyLow&lt;span style="color:#ae81ff"&gt;}&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;CIImage&lt;span style="color:#f92672"&gt;*&lt;/span&gt; image &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [CIImage imageWithCGImage:uiimage.CGImage];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;NSArray &lt;span style="color:#f92672"&gt;*&lt;/span&gt;features &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [detector featuresInImage:image
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; options:&lt;span style="color:#ae81ff"&gt;@{&lt;/span&gt; CIDetectorSmile:&lt;span style="color:#ae81ff"&gt;@YES&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; CIDetectorEyeBlink:&lt;span style="color:#ae81ff"&gt;@YES&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; CIDetectorImageOrientation:[NSNumber numberWithInt:[self exifOrientation:uiimage]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; ];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;(CIFaceFeature&lt;span style="color:#f92672"&gt;*&lt;/span&gt; face &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; features){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// faceを使って何かする（矩形を描画する、など）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="画像の向きについて"&gt;画像の向きについて&lt;/h3&gt;
&lt;p&gt;iOSデバイスのカメラで撮影した画像の場合、撮影時のデバイスの向きに応じて内部的に方向を持っています。その方向というのを&lt;code&gt;CIDetector&lt;/code&gt;の&lt;code&gt;featuresInImage&lt;/code&gt;に渡してあげないと正しく検出されません。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;uiimage.imageOrientation&lt;/code&gt; によって渡すべき値がことなるので、次のようなメソッドを定義して使いました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (NSUInteger)&lt;span style="color:#a6e22e"&gt;exifOrientation:&lt;/span&gt;(UIImage&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)image
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; NSUInteger orientation &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (image.imageOrientation) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; UIImageOrientationUp:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; orientation &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; UIImageOrientationDown:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; orientation &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; UIImageOrientationLeft:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; orientation &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; UIImageOrientationRight:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; orientation &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; UIImageOrientationUpMirrored:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; orientation &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; UIImageOrientationDownMirrored:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; orientation &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; UIImageOrientationLeftMirrored:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; orientation &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; UIImageOrientationRightMirrored:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; orientation &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; orientation;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="笑顔まばたきの検出"&gt;笑顔・まばたきの検出&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;featuresInImage&lt;/code&gt;に渡すオプションに笑顔を検出するかどうか、まばたきを検出するかどうかというオプションを追加しておくと、帰ってくる&lt;code&gt;CIFaceFeature&lt;/code&gt;にそれらの情報が入ってくるようになります。&lt;/p&gt;
&lt;p&gt;今回は両方ともYESとしておきました。&lt;/p&gt;
&lt;h2 id="cifacefeature"&gt;CIFaceFeature&lt;/h2&gt;
&lt;p&gt;次のようなプロパティを持ちます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;bounds&lt;/li&gt;
&lt;li&gt;leftEyePosition&lt;/li&gt;
&lt;li&gt;rightEyePosition&lt;/li&gt;
&lt;li&gt;mouthPosition&lt;/li&gt;
&lt;li&gt;hasSmile&lt;/li&gt;
&lt;li&gt;leftEyeClosed&lt;/li&gt;
&lt;li&gt;rightEyeClosed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;hasSmile&lt;/code&gt;や&lt;code&gt;leftEyeClosed&lt;/code&gt;などで笑顔やまばたきがわかりますね。&lt;/p&gt;
&lt;h2 id="フリー写真を使って試してみた"&gt;フリー写真を使って試してみた&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/96946bf3-64ec-4d8e-ad00-0959d236e3c9/fe5a26744a92398d83e1c242231e3441/deep/0/IMG_1252.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;こんな感じです。
ちゃんと笑顔フラグも取れました。&lt;/p&gt;</description></item><item><title>iOSシミュレータのアプリディレクトリ探しから開放される</title><link>https://blog.piyo.tech/posts/2014-01-18-210504/</link><pubDate>Sat, 18 Jan 2014 21:04:33 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-18-210504/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/3f7afcf1-034a-4396-b202-1a9a437f0005/9fbda02d3eaf22b1b3260e32f9a9dd27/deep/0/screenshot_309.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;iOSアプリでアプリケーションティレクトリを使うようなアプリだと、開発中やデバッグ中にそのディレクトリの中を確認したくなることってたくさんありますよね。&lt;/p&gt;
&lt;p&gt;ですが、そのときに必要な行動は実機でもシミュレータでもとても面倒です。実機はコネクタで繋がなければいけないし、シミュレータの場合はアプリの置き場所が深い位置にあるので探すのが大変。とてもストレスがたまります。&lt;/p&gt;
&lt;p&gt;今回はシミュレータのケースに限定してアプリケーションディレクトリにアクセスするための方法をいくつか紹介します。&lt;/p&gt;
&lt;h2 id="コードで出力する"&gt;コードで出力する&lt;/h2&gt;
&lt;p&gt;以下のコードでログに出したりすれば、あとはコピペで使えますね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;%@&amp;#34;&lt;/span&gt;,[[NSBundle mainBundle] bundlePath]);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;アプリケーションディレクトリはめったに使わないけど一時的にパスを知りたい、というときはこれでもいいかもしれません。&lt;/p&gt;
&lt;h2 id="アプリを頼る"&gt;アプリを頼る&lt;/h2&gt;
&lt;p&gt;常駐型のアプリでアプリケーションディレクトリを一覧にし、選んだものをFinderで開いてくれるものが2つありました。これらを使えばすごく楽です。&lt;/p&gt;
&lt;h3 id="simulator-folders"&gt;Simulator Folders&lt;/h3&gt;
&lt;p&gt;[http://nimbleworks.co.uk/blog/simulator-folders/:image:large]&lt;br&gt;
&lt;a href="http://nimbleworks.co.uk/blog/simulator-folders/"&gt;Simulator Folders&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;起動するとツールバーに常駐するので、そこのアイコンから使用します。こんな風にドロップダウンからアプリを選択して、、、&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/be14532f-401e-4a9d-9225-3a881caaf4ce/cc3f622a7a3736e2214dc7460ad54fa8/deep/0/OtherViews.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;GOとすればFinderが開きます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7c8fcaad-4135-49a8-943c-27d7620637fb/d82120de83c7ca5ab9df3d1ea2e66e47/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-14-21-53.png" alt=""&gt;&lt;/p&gt;
&lt;h3 id="simpholders"&gt;SimPholders&lt;/h3&gt;
&lt;p&gt;[http://simpholders.com/:image:large]&lt;/p&gt;
&lt;p&gt;&lt;a href="http://simpholders.com/"&gt;SimPholders 1.5&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;はっきり言ってSimulator Folderよりこちらのほうが使い勝手、見た目ともに良いのでこっちを使いましょう。&lt;/p&gt;
&lt;p&gt;こちらもインストール後に常駐アイコンが現れるのでツールバーから使います。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9a09aceb-7fba-4477-a06f-d604711f1f43/85854cc8582fa6d864abd54c6dc31f58/deep/0/7.0.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;SimPholdersは最近使ったアプリという項目があるほか、ビルドされたSDKのバージョン毎に個別のサブメニューに分類してくれています。目的のアプリを選べばアプリケーションディレクトリがFinderで開くというわけです。&lt;/p&gt;
&lt;p&gt;最初に紹介したアプリの場合はSDKのバージョンに関係なくすべての候補を並べてしまうので非常に見づらいというのが少々問題がありそうだったのに対し、こちらは比較的すっきり閲覧できます。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ&lt;/h2&gt;
&lt;p&gt;SimPholders入れましょう。&lt;/p&gt;</description></item><item><title>webmockでHTTPリクエストをstubしてファイルの中身を返す</title><link>https://blog.piyo.tech/posts/2014-01-17-210605/</link><pubDate>Fri, 17 Jan 2014 21:05:34 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-17-210605/</guid><description>&lt;p&gt;ユニットテストのときのAPIリクエストは本当にAPIをたたくのではなくstubしておくことで、決まったレスポンスを受け取ってテストしやすくするという話です。よくある話ですね。&lt;/p&gt;
&lt;p&gt;RubyでRSpecを使っている場合です。&lt;/p&gt;
&lt;p&gt;RSpecを含めいろいろなテストフレームワークに対応しているHTTPリクエストをstubするライブラリ、&lt;a href="https://github.com/bblimke/webmock/"&gt;bblimke/webmock&lt;/a&gt;がいい感じです。他のを知っているわけではないですが、そこそこ使われている感じだったので全然問題ないと思います。&lt;/p&gt;
&lt;h2 id="返したい内容を書いたファイルを用意しておく"&gt;返したい内容を書いたファイルを用意しておく&lt;/h2&gt;
&lt;p&gt;想定しているリクエストに応じて必要なファイルを用意します。あ、その前に想定しているディレクトリ階層はこんな感じ。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;.
└── spec
├── fixtures
│ ├── file1.html
│ ├── file2.xml
│ └── file3.json
└── spec_helper.rb ☄
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;fixtures&lt;/code&gt; ディレクトリにレスポンス用ファイルを置いておくことにしています。&lt;/p&gt;
&lt;h2 id="webmockでファイルを指定する"&gt;webmockでファイルを指定する&lt;/h2&gt;
&lt;p&gt;tubするときにRubyのファイルクラスを用いてファイルを指定するとそのファイルの内容をHTTPのレスポンスとして返すことができるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;stub_request(&lt;span style="color:#e6db74"&gt;:get&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;http://example.com/&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_return(&lt;span style="color:#e6db74"&gt;body&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#e6db74"&gt;&amp;#34;path_to_file.html&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これ以降&lt;code&gt;http://example.com/&lt;/code&gt;へのgetリクエストは&lt;code&gt;path_to_file.html&lt;/code&gt;を結果として返すようになります。パラメータをつけたりいろいろできるのですが、そのあたりはREADMEを見た方が早いです(´・ω・｀)&lt;/p&gt;
&lt;p&gt;これでAPIリクエストの結果に相当するようなjsonファイルを書いておいてテストに使うことができますね。これはめでたい。&lt;/p&gt;
&lt;h2 id="ファイル名で簡単に指定できるようにしておくと便利"&gt;ファイル名で簡単に指定できるようにしておくと便利&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;fixtures&lt;/code&gt;ディレクトリ内のファイル名だけでレスポンスを指定できるように&lt;code&gt;spec_helper.rb&lt;/code&gt;にメソッドを定義しておくと楽です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fixture_path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;expand_path(&lt;span style="color:#e6db74"&gt;&amp;#34;../fixtures&amp;#34;&lt;/span&gt;, __FILE__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fixture&lt;/span&gt;(file)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(fixture_path, file))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>期間を表すRangeオブジェクトが便利</title><link>https://blog.piyo.tech/posts/2014-01-16-205005/</link><pubDate>Thu, 16 Jan 2014 20:49:36 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-16-205005/</guid><description>&lt;p&gt;Rubyで日付・日時を扱うときはDateTimeなどのクラスを使いますよね。これらのインスタンスは不等号で大小を比較できるようになっています。&lt;/p&gt;
&lt;p&gt;あるDateTimeインスタンスが指定した期間に含まれるか、というようなことを調べたいときはRubyのRangeクラスが使えます。というか、Rangeクラスにしておくと便利です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;s &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;DateTime&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#ae81ff"&gt;2014&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;e &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;DateTime&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;now
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;range &lt;span style="color:#f92672"&gt;=&lt;/span&gt; s&lt;span style="color:#f92672"&gt;..&lt;/span&gt;e
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;range&lt;span style="color:#f92672"&gt;.&lt;/span&gt;class &lt;span style="color:#75715e"&gt;# =&amp;gt; Range&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;date &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;DateTime&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#ae81ff"&gt;2014&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;range&lt;span style="color:#f92672"&gt;.&lt;/span&gt;cover?(date) &lt;span style="color:#75715e"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;range&lt;span style="color:#f92672"&gt;.&lt;/span&gt;include?(date) &lt;span style="color:#75715e"&gt;# =&amp;gt; TypeError&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;range&lt;span style="color:#f92672"&gt;.&lt;/span&gt;cover?(&lt;span style="color:#66d9ef"&gt;DateTime&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#ae81ff"&gt;2013&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;# =&amp;gt; false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;range.include?(date)&lt;/code&gt;とすると例外が発生するようです。日付のRangeに対してinclude?は使えません。そのかわりに&lt;code&gt;cover?&lt;/code&gt;が使えます。用途としてはこちらで問題なし。&lt;/p&gt;
&lt;h2 id="includeとcoverの違い"&gt;&lt;code&gt;include?&lt;/code&gt;と&lt;code&gt;cover?&lt;/code&gt;の違い&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;include?&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;引数となった値がRange内の要素と一致する場合にtrueとなります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;range &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;..&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;c&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;range&lt;span style="color:#f92672"&gt;.&lt;/span&gt;include?(&lt;span style="color:#e6db74"&gt;&amp;#34;b&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;range&lt;span style="color:#f92672"&gt;.&lt;/span&gt;include?(&lt;span style="color:#e6db74"&gt;&amp;#34;bb&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# =&amp;gt; false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;range&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_a &lt;span style="color:#75715e"&gt;# =&amp;gt; [&amp;#34;a&amp;#34;, &amp;#34;b&amp;#34;, &amp;#34;c&amp;#34;] &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;cover?&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;引数がRangeの両端の値の範囲ないにあればtrueとなります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;range &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;..&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;c&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;range&lt;span style="color:#f92672"&gt;.&lt;/span&gt;cover?(&lt;span style="color:#e6db74"&gt;&amp;#34;b&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;range&lt;span style="color:#f92672"&gt;.&lt;/span&gt;cover?(&lt;span style="color:#e6db74"&gt;&amp;#34;bb&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;range.cover?(&amp;quot;bb&amp;quot;)&lt;/code&gt;が&lt;code&gt;true&lt;/code&gt;になるというのが特徴的です。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;quot;bb&amp;quot;&lt;/code&gt;はrangeに含まれる要素（&lt;code&gt;range.to_a&lt;/code&gt;に含まれる要素）ではありませんので&lt;code&gt;include?&lt;/code&gt;では&lt;code&gt;false&lt;/code&gt;が返りますが、&lt;code&gt;cover?&lt;/code&gt;では&lt;code&gt;&amp;quot;bb&amp;quot;&lt;/code&gt;を&lt;code&gt;&amp;quot;a&amp;quot;&lt;/code&gt;、&lt;code&gt;&amp;quot;c&amp;quot;&lt;/code&gt;と比較して&lt;code&gt;&amp;quot;a&amp;quot; &amp;lt;= &amp;quot;bb&amp;quot; &amp;lt;= &amp;quot;c&amp;quot;&lt;/code&gt;になるかどうかを調べるので&lt;code&gt;true&lt;/code&gt;となるわけです。&lt;/p&gt;</description></item><item><title>NSCopyingって何？</title><link>https://blog.piyo.tech/posts/2014-01-15-204803/</link><pubDate>Wed, 15 Jan 2014 20:47:34 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-15-204803/</guid><description>&lt;p&gt;先日書いた「ペア要素をキーにしたNSDictionary」という記事でNSDictionaryのキーにしたPairクラスは&lt;code&gt;NSCopying&lt;/code&gt;プロトコルを実装するように書きました。&lt;/p&gt;
&lt;p&gt;この&lt;code&gt;NSCopying&lt;/code&gt;に関してはこれまで詳しいことを知らなかったのでヘッダーやリファレンスで調べてみました。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;あるクラスをコピー可能にする場合は&lt;code&gt;NSCopying&lt;/code&gt;プロトコルを継承しておく必要がある&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NSCopying&lt;/code&gt;プロトコルを継承するクラスは&lt;code&gt;copyWithZone:&lt;/code&gt;を実装する必要がある&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;ということらしいです。&lt;/p&gt;
&lt;h2 id="nscopyingプロトコルの継承"&gt;&lt;code&gt;NSCopying&lt;/code&gt;プロトコルの継承&lt;/h2&gt;
&lt;p&gt;Objective-Cクラスのインスタンスをコピーするために&lt;code&gt;copy&lt;/code&gt;というメソッドが用意されています。この&lt;code&gt;copy&lt;/code&gt;メソッドは実際は&lt;code&gt;copyWithZone:&lt;/code&gt;を呼び出して結果をそのまま返す実装になっているようです。&lt;/p&gt;
&lt;p&gt;iOS Developer Libraryにはこのような記述があります。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;copy&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns the object returned by copyWithZone:.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;なお、&lt;code&gt;copyWithZone:&lt;/code&gt;を定義していない（つまり&lt;code&gt;NSCopying&lt;/code&gt;を継承していない）クラスに対して&lt;code&gt;copy&lt;/code&gt;メソッドを呼ぶと例外が投げられます。&lt;/p&gt;
&lt;p&gt;つまり、自前クラスをコピーできるようにしたい場合は&lt;code&gt;NSCopying&lt;/code&gt;を継承して&lt;code&gt;copyWithZone:&lt;/code&gt;を書いておく必要があります。&lt;/p&gt;
&lt;h2 id="copywithzoneの実装"&gt;&lt;code&gt;copyWithZone:&lt;/code&gt;の実装&lt;/h2&gt;
&lt;p&gt;これはそもそもObjective-Cのプロトコルとはそういうものなので詳しく説明するまでもないか、、、&lt;/p&gt;
&lt;p&gt;&lt;code&gt;NSCopying&lt;/code&gt;はメソッドを1つだけ持ち、それが&lt;code&gt;copyWithZone:&lt;/code&gt;です。&lt;code&gt;NSCopying&lt;/code&gt;を継承した場合は&lt;code&gt;copyWithZone:&lt;/code&gt;メソッドを定義し、適切なコピーを行う実装を書く必要があります。ちゃんとプロパティごとにコピーした要素を返すとかね。&lt;/p&gt;
&lt;p&gt;先日の記事の例で言えば、NSDictionaryのキーになる要素は必ず&lt;code&gt;copy&lt;/code&gt;されるので、&lt;code&gt;NSCopying&lt;/code&gt;プロトコルを継承し、適切な&lt;code&gt;copyWithZone:&lt;/code&gt;の実装が必要だったというわけでした。&lt;/p&gt;</description></item><item><title>ペア要素をキーにしたNSDictionary</title><link>https://blog.piyo.tech/posts/2014-01-14-204804/</link><pubDate>Tue, 14 Jan 2014 20:47:37 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-14-204804/</guid><description>&lt;p&gt;NSDictionaryで複数要素をキーにしようというお話です。&lt;/p&gt;
&lt;p&gt;普通の連想配列はキーとバリューで1つの組み合わせになりますが、片方が◯でもう片方が☆のときはこの値みたいなケースの場合は最初から用意されているデータ型では間に合わないことが多いです。&lt;/p&gt;
&lt;p&gt;C++では&lt;code&gt;std::pair&lt;/code&gt;をキーにした&lt;code&gt;std::map&lt;/code&gt;を使えばよいです。Objective-Cではどうやるかわからなかったので調べた結果をまとめます。&lt;/p&gt;
&lt;p&gt;ちなみに、複数要素をキーにするようなデータ構造に入れたくなるデータはこんなような感じです。&lt;/p&gt;
&lt;p&gt;|Key1|Key2|Value|
|::|::|::|
|hoge|huga|value1|
|hoge|piyo|value2|
|hoge|foo|value3|
|huga|piyo|value4|
|huga|foo|value5|
|huga|hoge|value6|&lt;/p&gt;
&lt;h2 id="なにはともあれpairクラス"&gt;なにはともあれPairクラス&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;NSObject&lt;/code&gt;を継承した&lt;code&gt;Pair&lt;/code&gt;クラスを作って必要なメソッドをオーバーライドして実装しておくことで、NSdictionaryのキーとして使えるようになります。この&lt;code&gt;Pair&lt;/code&gt;クラスができてしまえば今回やりたいことはできるようになったも同然です。&lt;/p&gt;
&lt;h3 id="pairh"&gt;Pair.h&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Pair&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;NSObject&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;NSCopying&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;readonly&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;id&lt;/span&gt; first;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;readonly&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;id&lt;/span&gt; second;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;+ (&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;pairWithFirst:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)f &lt;span style="color:#a6e22e"&gt;second:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)s;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;initWithFirst:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)f &lt;span style="color:#a6e22e"&gt;second:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)s;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="pairm"&gt;Pair.m&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;#34;Pair.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@implementation&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Pair&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@synthesize&lt;/span&gt; first, second;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;+ (&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;pairWithFirst:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)f &lt;span style="color:#a6e22e"&gt;second:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [[[self &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt;] alloc] initWithFirst:f second:s];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;initWithFirst:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)f &lt;span style="color:#a6e22e"&gt;second:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (self &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [super init]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; first &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [f &lt;span style="color:#66d9ef"&gt;copy&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; second &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [s &lt;span style="color:#66d9ef"&gt;copy&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; self;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;copyWithZone:&lt;/span&gt;(NSZone &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)zone
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; Pair&lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;copy&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[[self &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt;] alloc] initWithFirst:[self first] second:[self second]];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;copy&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;isEqual:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)other
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ([other isKindOfClass:[Pair &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt;]] &lt;span style="color:#f92672"&gt;==&lt;/span&gt; NO) { &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; NO; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; ([[self first] isEqual:[(Pair&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)other first]] &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; [[self second] isEqual:[(Pair&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)other second]]);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt;- (NSUInteger) &lt;span style="color:#a6e22e"&gt;hash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [[self first] hash] &lt;span style="color:#f92672"&gt;+&lt;/span&gt; [[self second] hash];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="使い方"&gt;使い方&lt;/h2&gt;
&lt;p&gt;こんな風に使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;NSMutableDictionary&lt;span style="color:#f92672"&gt;*&lt;/span&gt; dic &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[NSMutableDictionary alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;[dic setObject:&lt;span style="color:#e6db74"&gt;@&amp;#34;A&amp;#34;&lt;/span&gt; forKey:[Pair pairWithFirst:&lt;span style="color:#e6db74"&gt;@&amp;#34;hoge&amp;#34;&lt;/span&gt; second:&lt;span style="color:#e6db74"&gt;@&amp;#34;huga&amp;#34;&lt;/span&gt;]];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;[dic setObject:&lt;span style="color:#e6db74"&gt;@&amp;#34;B&amp;#34;&lt;/span&gt; forKey:[Pair pairWithFirst:&lt;span style="color:#e6db74"&gt;@&amp;#34;foo&amp;#34;&lt;/span&gt; second:&lt;span style="color:#e6db74"&gt;@&amp;#34;bar&amp;#34;&lt;/span&gt;]];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;[dic setObject:&lt;span style="color:#e6db74"&gt;@&amp;#34;C&amp;#34;&lt;/span&gt; forKey:[Pair pairWithFirst:&lt;span style="color:#e6db74"&gt;@&amp;#34;hoge&amp;#34;&lt;/span&gt; second:&lt;span style="color:#e6db74"&gt;@&amp;#34;bar&amp;#34;&lt;/span&gt;]];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;[dic setObject:&lt;span style="color:#e6db74"&gt;@&amp;#34;D&amp;#34;&lt;/span&gt; forKey:[Pair pairWithFirst:&lt;span style="color:#e6db74"&gt;@&amp;#34;foo&amp;#34;&lt;/span&gt; second:&lt;span style="color:#e6db74"&gt;@&amp;#34;bar&amp;#34;&lt;/span&gt;]];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;[dic setObject:&lt;span style="color:#e6db74"&gt;@&amp;#34;E&amp;#34;&lt;/span&gt; forKey:[Pair pairWithFirst:[NSNumber numberWithInt:&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;] second:[NSNumber numberWithInt:&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;]]];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;[dic setObject:&lt;span style="color:#e6db74"&gt;@&amp;#34;F&amp;#34;&lt;/span&gt; forKey:[Pair pairWithFirst:[NSNumber numberWithInt:&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;] second:[NSNumber numberWithInt:&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;]]];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;同じキーに値を上書きしていることもあって、上のdicには4つ要素が入っていることになります。&lt;/p&gt;
&lt;h2 id="かいせつ"&gt;かいせつ〜&lt;/h2&gt;
&lt;p&gt;基本は2つのObjective-Cクラスを受け取って保持しておくクラスです。&lt;/p&gt;
&lt;p&gt;NSDictionaryのキーとして使用したいクラスには次のメソッドを正しく実装しておく必要があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;copyWithZone&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isEqual&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hash&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="copywithzone"&gt;copyWithZone&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;NSCopying&lt;/code&gt;プロトコルの&lt;code&gt;copyWithZone&lt;/code&gt;を実装しておかないとNSDictionaryのキーとしては使えません。キーとして格納する際にコピーが走るから（だと思います）です。&lt;/p&gt;
&lt;h2 id="isequal"&gt;isEqual&lt;/h2&gt;
&lt;p&gt;連想配列のキーとして使用するには、キー同士が同じであうるかどうかの比較を行うことができなければいけません。そのために必要なメソッドです。&lt;/p&gt;
&lt;h2 id="hash"&gt;hash&lt;/h2&gt;
&lt;p&gt;インスタンス毎に一意（異なる）の値を返すように実装しておき、キーが同じであるかの判定に用いられます。先ほど紹介した実装ではペアとなっている要素の&lt;code&gt;hash&lt;/code&gt;の和を返しており厳密には一意の値ではない可能性もあるので、ちゃんとやりたい場合は実装を考える必要があります。&lt;/p&gt;</description></item><item><title>Xcodeでメインのターゲット名を変更するとのUnitテストが起動しないよ</title><link>https://blog.piyo.tech/posts/2014-01-13-134106/</link><pubDate>Mon, 13 Jan 2014 13:40:39 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-13-134106/</guid><description>&lt;p&gt;iOSアプリのユニットテストを実行しようとしたらエラーが起きて起動しないということがありました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;It is likely that dyld cannot locate a framework framework
or library that the the test bundle was linked against,
possibly because the framework or library had an incorrect install path at link time.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;なんかリンクできないよー、というようなエラーが出ていました。&lt;/p&gt;
&lt;p&gt;なんだろうなと思ってググっていろいろ試したんですが直らず、ってことをしているときにふと思い出しました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ターゲット名変えたわ！！&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="サンプルプロジェクトで試してみる"&gt;サンプルプロジェクトで試してみる&lt;/h2&gt;
&lt;p&gt;最初、ユニットテストにはアプリケーションが関連付けられています。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/afe30e1e-36e0-4f5b-bba3-36979550db7d/31514af5f068f852e8707412f9a1037c/deep/0/AppName.xcodeproj.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;このあとでメインのターゲット名を変更すると、、&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0c585a05-d303-4a49-a27a-17cead9a17da/3478351294a3ebebc0bb3f1a39d6f681/deep/0/AppName.xcodeproj.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ユニットテストに関連付けられているターゲットがこんな風に空欄になってしまいます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/d5263fa2-6813-4174-9a94-47ab0dd9066f/95b4618366c56eb779ec1b4a80176964/deep/0/AppName.xcodeproj.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;なのでプルダウンから選んであげれば良いです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/33420bfc-790b-46f3-a8b3-29cd58d0194c/adc675f952610cefa3e7cfabf6efd981/deep/0/OtherViews-%E3%81%A8-AppName.xcodeproj.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ちょっとはまりました&lt;/p&gt;</description></item><item><title>Xcodeで改行したつもりが改行じゃないらしくて警告が出てしまう</title><link>https://blog.piyo.tech/posts/2014-01-12-162806/</link><pubDate>Sun, 12 Jan 2014 16:27:39 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-12-162806/</guid><description>&lt;p&gt;Xcodeでコードを書いていて普通に改行したつもりが、なぜかこんな警告が出ていることがあります。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Treating Unicode character as whitespace
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;僕がこれを出すときは決まって無意識のうちにコントロールキーを押したままReturnキーを押して改行しようとしています。どうやら&lt;code&gt;Ctrl＋Return&lt;/code&gt;だとnew lineではなく、line breakとして扱われるようです。&lt;/p&gt;
&lt;p&gt;でもソース書くときは&lt;code&gt;Ctrl+n&lt;/code&gt;とか&lt;code&gt;Ctrl+p&lt;/code&gt;とかでカーソル移動をすることが多いのでCtrl押しっぱってことがかなり多いんですよね。なので設定を変えてしまうことにしました。&lt;/p&gt;
&lt;p&gt;XcodeのPreferenceから&lt;code&gt;Key Bindings&lt;/code&gt;を選んで、&lt;code&gt;Insertions and indentations&lt;/code&gt;から&lt;code&gt;Insert Line Break&lt;/code&gt;を探します。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/d24bae67-8d41-4913-9da8-6158c8eff5e0/288699e4e01f63ac842dd046bfcbdfe5/deep/0/Key-Bindings.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;そして、&lt;code&gt;Ctrl＋リターン&lt;/code&gt;を削除します。&lt;/p&gt;
&lt;p&gt;次に&lt;code&gt;Insert NewLine&lt;/code&gt;のところに&lt;code&gt;Ctrl＋リターン&lt;/code&gt;を追加してあげればOK。うっかり入力しても警告が出ず快適にコードを書けるようになりました。&lt;/p&gt;</description></item><item><title>XcodeインスペクタのState Config</title><link>https://blog.piyo.tech/posts/2014-01-11-214809/</link><pubDate>Sat, 11 Jan 2014 21:47:43 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-11-214809/</guid><description>&lt;p&gt;UIButtonってタップ中の状態に色とか背景とか画像とか変えられますよね。てっきりコードでしか出来ないと思っていたらそんなことありませんでした。恥ずかしい。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/83171592-b48c-4aff-8519-659c1b4d11fa/dc4bb4de3dc9f0a9e81f9dd4657c93a9/deep/0/CustomButton.xcodeproj---Main.storyboard.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;この&lt;code&gt;State Config&lt;/code&gt;を変えてから設定を変えると、そのStateに対して値が用いられるみたいですね。例えばタップ中の文字列を変えたいなら&lt;code&gt;State Config&lt;/code&gt;を&lt;code&gt;Highlighted&lt;/code&gt;にしてからタイトルを編集すればいいってことです。&lt;/p&gt;
&lt;p&gt;いやー、知らなかった恥ずかしい。&lt;/p&gt;</description></item><item><title>画像付きUIButtonのレイアウト調整</title><link>https://blog.piyo.tech/posts/2014-01-10-215106/</link><pubDate>Fri, 10 Jan 2014 21:50:42 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-10-215106/</guid><description>&lt;p&gt;UIButtonに画像をつけるとデフォルトでは画像の右側にテキストが回りこむような形でレイアウトされますが、このレイアウトはカスタマイズ可能です。&lt;/p&gt;
&lt;p&gt;画像とテキストはそれぞれ独立して動かすことができますので、次のようなレイアウトを作ることも可能です。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/11517a5f-f1e3-40cb-851e-b8f65a80a457/6e893fe6d64bdaea2e6c1a54d23e9396/deep/0/InsetsExample.xcodeproj---Main.storyboard.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="storyboardまたはibで設定"&gt;storyboard（またはIB）で設定&lt;/h2&gt;
&lt;p&gt;UIButtonを選択するとインスペクタでInsetsという欄が現れます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c3f90aca-c699-4a22-8cf4-85ded906758b/09fa554d0aa648e0ffb5203d35b49ee7/deep/0/InsetsExample.xcodeproj---Main.storyboard.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ここにあるEdgeという項目では、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Content&lt;/li&gt;
&lt;li&gt;Title&lt;/li&gt;
&lt;li&gt;Image&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;の3つを選択でき、&lt;code&gt;Insets&lt;/code&gt;欄に入力する値を何に効かせるのかを切り替えるのに使用します。&lt;code&gt;Content&lt;/code&gt;では画像とテキスト両方を、&lt;code&gt;Title&lt;/code&gt;はテキストのみ、&lt;code&gt;Image&lt;/code&gt;は画像のみです。&lt;/p&gt;
&lt;p&gt;例えば、このような配置にする場合には、&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/04fb60de-de9b-4e88-bda2-1af974b0f70e/b389d9633f106ee2086902558007c083/deep/0/InsetsExample.xcodeproj---Main.storyboard.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;画像を右上にずらし、テキストを左下にずらします。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b27afb31-0c2e-4afa-aed3-ac2624861653/cca95f151f7b071f419fb48f5346c470/deep/0/InsetsExample.xcodeproj---Main.storyboard.png" alt=""&gt;
&lt;img src="https://www.evernote.com/shard/s15/sh/960a1f22-26c5-4a0b-b92a-89fc13e67092/c0743684d9205a85525bc5c47b5eae58/deep/0/InsetsExample.xcodeproj---Main.storyboard.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="コードで設定"&gt;コードで設定&lt;/h2&gt;
&lt;p&gt;コードでも簡単に設定可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;button.imageEdgeInsets &lt;span style="color:#f92672"&gt;=&lt;/span&gt; UIEdgeInsetsMake(&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;button.titleEdgeInsets &lt;span style="color:#f92672"&gt;=&lt;/span&gt; UIEdgeInsetsMake(&lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>ARCを使ったiOS開発でのプロパティ名</title><link>https://blog.piyo.tech/posts/2014-01-09-214907/</link><pubDate>Thu, 09 Jan 2014 21:48:43 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-09-214907/</guid><description>&lt;p&gt;こんな謎のビルドエラーに遭遇しました。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;property&amp;#39;s synthesized getter follows Cocoa naming convention for returning &amp;#39;owned&amp;#39; objects
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;どうやらnewから始まるプロパティ名は使用できないようです。エラーメッセージがわかりにくいので調べないとわかりませんでした。&lt;/p&gt;</description></item><item><title>Skitchのスクリーンショットのデフォルト名の変え方</title><link>https://blog.piyo.tech/posts/2014-01-08-205206/</link><pubDate>Wed, 08 Jan 2014 20:51:44 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-08-205206/</guid><description>&lt;p&gt;Skitchでスクリーンショットを取るとウィンドウのタイトルか&lt;code&gt;スクリーンショット+タイムスタンプ&lt;/code&gt;という名前のノートが作られます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/5fd867b8-2777-4507-8d8d-0a4da060981a/b59a04b1654de30586fcfc4dcfadb8cc/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2014-01-03-19-43.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;このタイトルに日本語が入っているので気に食わなかったので設定で変えてやろうと思ったらそんな項目がありません。そこでいくつか試したり英語のサポートに頑張って問い合わせたりしたのですが、変えられないということがわかりました。&lt;/p&gt;
&lt;p&gt;同じようなことをしたい人がいるかもしれないので、どのようなことを試してどのような回答をサポートからもらったのかを書いておきます。&lt;/p&gt;
&lt;h2 id="mac標準のスクリーンショット名を変更する方法"&gt;Mac標準のスクリーンショット名を変更する方法&lt;/h2&gt;
&lt;p&gt;もしやOS標準のスクリーンショット名と関係が…？と思ったんですが、そんなことはありませんでした。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://weekly.ascii.jp/elem/000/000/177/177317/"&gt;OS Xのスクリーンショットの長～いファイル名は変えられる｜Mac&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="特定のアプリケーションの言語を変える方法"&gt;特定のアプリケーションの言語を変える方法&lt;/h2&gt;
&lt;p&gt;せめて日本語の文字は無くせないかと思いSkitchを英語で起動するようにしておけばいいんじゃないかと思ったんですが、これもうまくいきませんでした。Skitchを英語で起動すること自体はうまくいったんですけどね。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://rcmdnk.github.io/blog/2013/07/15/computer-mac-english/"&gt;App Language ChooserでMail.app等特定のアプリだけ英語設定にする - rcmdnk&amp;rsquo;s blog&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="サポート"&gt;サポート&lt;/h2&gt;
&lt;p&gt;Evernoteの有料会員になっているのでサポートに英語で質問を投げました。何回かやりとりをした後、最終的に得られたのがこの回答です。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I just talked wit the Skitch people here and they say that the screen snap is named based on what windows you are snapping. The only way to change this is to click on the name once the screen shot is in skitch and rename it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;名前を変えたかったらスクリーンショット撮ったあとで変えてね、だって。&lt;/p&gt;
&lt;p&gt;諦めました。&lt;/p&gt;
&lt;p&gt;ハックする方法があったら是非知りたいです。&lt;/p&gt;</description></item><item><title>個別ページのURLからRSSフィードURLを取得するfeedbag</title><link>https://blog.piyo.tech/posts/2014-01-07-203404/</link><pubDate>Tue, 07 Jan 2014 20:33:45 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-07-203404/</guid><description>&lt;p&gt;自分用のメモも兼ねて今は亡きRSSリーダーを作ったときのノウハウを少しずつときどき書いていこうと思います。&lt;/p&gt;
&lt;p&gt;RSSリーダーによくある機能として現在開いているページのRSSフィードを購読するというフローがあるんですが、それと同じ機能を実現しようとしたときに使用したruby gemを紹介します。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/damog/feedbag"&gt;damog/feedbag&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このfeedbagは渡されたURLからフィードのURLをいろいろ頑張って抽出し、URLのArrayを返すというシンプルなライブラリです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ gem install feedbag
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;でインストールでき、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Feedbag&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find(&lt;span style="color:#e6db74"&gt;&amp;#34;URL&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とすれば使用できます。&lt;/p&gt;
&lt;p&gt;ためしにこのブログのトップページのURLを渡してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ pry
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&amp;gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;feedbag&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;2&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;2&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&amp;gt; Feedbag.find &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.piyo.tech/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.piyo.tech/feed&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.piyo.tech/rss&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;http://developer.hatena.ne.jp/ja/documents/bookmark/apis/atom&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このように3つのURLを得ることができました。1つ目と2つ目が使えそうです。3つ目は関係ないURLですが、フィードだと判定されてしまったようです。&lt;/p&gt;
&lt;p&gt;次にこのブログの個別ページのURLを渡してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;3&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&amp;gt; Feedbag.find &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.piyo.tech/posts/2014-01-02-204306&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.piyo.tech/feed&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.piyo.tech/rss&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今度は2つになりましたが、トップページを渡したときに得られたうちの2つと一致しています。どちらも使えそう。&lt;/p&gt;
&lt;p&gt;このライブラリの実装を見てみるとHTMLタグを解析していろいろ頑張ってくれているみたい。&lt;/p&gt;
&lt;p&gt;体感的にはフィードを持つ全てのサイトで動く感じがしたので、このライブラリに任せれば良いと思います。&lt;/p&gt;</description></item><item><title>Macで引用符を入力すると勝手に変換されるのをやめたい</title><link>https://blog.piyo.tech/posts/2014-01-06-205101/</link><pubDate>Mon, 06 Jan 2014 20:50:42 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-06-205101/</guid><description>&lt;p&gt;このブログはEmacsやSublime Text2、Evernoteで書いてから投稿しています。特に多いのはEvernoteです。&lt;/p&gt;
&lt;p&gt;技術系のネタばかりなのでよくシングルクォートやダブルクォートをタイプするんですが、Evernoteで書いた記事をはてなブログに貼り付けてプレビューするとシンタックスハイライト効いてないみたいなことがよく起こっていました。&lt;/p&gt;
&lt;p&gt;よくよく見ると引用符が勝手に開き引用符と閉じ引用符っていうんですか？別のものに勝手に変換されていました。マイクロソフトのOfficeじゃないんだから勝手に変えてんじゃないよ、と。どうやらこれはMacのおせっかいらしいです。&lt;/p&gt;
&lt;p&gt;あまりにも邪魔なので設定画面から解除しました。&lt;/p&gt;
&lt;p&gt;「システム環境設定」→「キーボード」→「ユーザー辞書」といって、右側に&lt;code&gt;スマート引用符とスマートダッシュを使用&lt;/code&gt;というチェックがあるのでこれを外します。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/23eb83ba-5b5b-45e1-a08d-aa9cf6ad5702/642f4caf494a5f59da3e8934bd49e7d9/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-30-22-09.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;これで安心！&lt;/p&gt;
&lt;p&gt;でも過去の記事全部チェックするのしんどいな、、&lt;/p&gt;</description></item><item><title>CocoaPods使用プロジェクトで新しいConfigurationを作ったときの注意</title><link>https://blog.piyo.tech/posts/2014-01-05-212908/</link><pubDate>Sun, 05 Jan 2014 21:28:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-05-212908/</guid><description>&lt;p&gt;テストコード実行時のみ通るコードを書くためにTesting用のConfigurationを作成してビルドしたら次のようなリンクエラーがでました&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;library not found for -lPods
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;CocoaPodsを使っているプロジェクトだったのですが、CocoaPods周りの設定が新しいConfigurationに反映されていないために起こるエラーだったようで、もう一度&lt;code&gt;$ pod install&lt;/code&gt;をかければすぐに直りました。&lt;/p&gt;</description></item><item><title>Xcodeでテストのときのみ特定のコードを実行する方法</title><link>https://blog.piyo.tech/posts/2014-01-04-214706/</link><pubDate>Sat, 04 Jan 2014 21:46:48 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-04-214706/</guid><description>&lt;p&gt;テストコードのときのみ実行したいコードってありますよね？例えばサーバーのURLを変えたり、テスト用のデータを用意したりいろいろな用途があり得そうです。&lt;/p&gt;
&lt;p&gt;シンプルにやるにはプリプロセッサマクロを使ってこんな風にやるのがよさそうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;method&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#ifdef TESTING
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; [self hogehoge];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ではどうやって実現するか、順を追って説明します。&lt;/p&gt;
&lt;h2 id="configurationを新しく作る"&gt;Configurationを新しく作る&lt;/h2&gt;
&lt;p&gt;Xcodeのプロジェクトの設定画面のinfoからConfigurationsを新しく作ります。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/cd2c544b-963d-4259-bf2e-77f99c95dd09/bb778101a564415704a857528a11035e/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-30-21-44.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;＋ボタンをクリックし、&lt;code&gt;Duplicate “Debug” Configuration&lt;/code&gt;を選び名前を&lt;code&gt;Testing&lt;/code&gt;などとします（テスト用の設定なのでDebugから複製すれば良いでしょう）。&lt;/p&gt;
&lt;p&gt;;&lt;img src="https://www.evernote.com/shard/s15/sh/7fc3d718-0989-496d-a088-6474a7999edd/55d8c7920abca62c98c9db9f68f1243b/deep/0/OtherViews.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="プリプロセッサマクロを追加する"&gt;プリプロセッサマクロを追加する&lt;/h2&gt;
&lt;p&gt;同じく設定画面からBuild Settingsのタブを開いてマクロを追加します。右上のウィンドウで絞り込みをすると楽。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0f8863d7-0a0a-4c1c-9704-d04a3f3e9683/8d217aeb15defc7d4703e8999f31c204/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-30-21-51.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Testing設定に&lt;code&gt;TESTING=1&lt;/code&gt;というプリプロセッサマクロを追加します。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/42f30d80-b2b8-49ee-b3bb-18eddbe04cc6/4b6ade11643202badfb2215494b93b61/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-30-21-52.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="edit-schemeする何て呼べばいいの"&gt;Edit Schemeする（何て呼べばいいの？）&lt;/h2&gt;
&lt;p&gt;これで最後です。&lt;code&gt;Edit Scheme&lt;/code&gt;して、テスト時のConfigurationを先ほど作った&lt;code&gt;Testing&lt;/code&gt;に変えます。&lt;/p&gt;
&lt;p&gt;まずは&lt;code&gt;Edit Scheme&lt;/code&gt;の画面を開き、、、&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/f5f64275-6b59-4c28-8fdb-7062c714b759/4387abdc337665567111f9acbbff8350/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-30-21-55.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;左側の項目からTestを選んで、&lt;code&gt;Build Configuration&lt;/code&gt;を&lt;code&gt;Testing&lt;/code&gt;に変更します。&lt;/p&gt;
&lt;p&gt;これで、最初に例示したようなコードが動くようになりました。&lt;/p&gt;</description></item><item><title>Alfred+Dashで秒速リファレンス検索</title><link>https://blog.piyo.tech/posts/2014-01-03-203206/</link><pubDate>Fri, 03 Jan 2014 20:31:50 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-03-203206/</guid><description>&lt;p&gt;いやー、知らなかった。AlfredもDashも使っててこの連携をやってないなんて。もしかして普通の人は連携してるのかな。&lt;/p&gt;
&lt;h2 id="連携の前にそれぞれの概要"&gt;連携の前にそれぞれの概要&lt;/h2&gt;
&lt;h3 id="alfred"&gt;Alfred&lt;/h3&gt;
&lt;p&gt;ランチャーアプリケーションです。僕はControl+Spaceをホットキーに使っています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://itunes.apple.com/jp/app/alfred/id405843582?mt=12"&gt;Alfred&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="dash"&gt;Dash&lt;/h3&gt;
&lt;p&gt;リファレンス（docset）を閲覧したり、スニペットを管理できるアプリケーションです。僕はもっぱらスニペット管理に使っていました。日記（日々の記録）のテンプレとか自分のメールアドレスとか。リファレンスのほうはあまり使っていませんでした。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://itunes.apple.com/jp/app/dash-docs-snippets/id458034879?mt=12"&gt;Dash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="dashの検索をalfredから行う"&gt;Dashの検索をAlfredから行う&lt;/h2&gt;
&lt;p&gt;DashにはURLスキームがあります。&lt;/p&gt;
&lt;p&gt;AlfredにはURLを指定したカスタム検索ができます。&lt;/p&gt;
&lt;p&gt;つまり、この2つの機能を組み合わせればAlfredからDashの検索が可能になります。Alfredから操作できるということはいつなんどきでも秒速でリファレンス検索ができるということです。&lt;/p&gt;
&lt;h3 id="設定方法"&gt;設定方法&lt;/h3&gt;
&lt;p&gt;Dash側の設定は要りません。&lt;/p&gt;
&lt;p&gt;Alfred側の設定のためAlfredのPreferenceを開きます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/4c55b1a4-e1a6-4e35-ad23-834022448813/3b7c2f8129da35ce0fa202a82cc3ced3/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-27-20-44.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;左側の項目から&lt;code&gt;Custom Searches&lt;/code&gt;を選択し、右側に現れたリストの＋ボタンを押します。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0112bdd9-c00f-46c1-9b9f-be0bf5ed08ec/6df54a64efde5b294b76bdc9f514af9f/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-27-20-46.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;次のような画面が現れるので項目を埋めます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/90e417ee-bc77-42d4-abbe-a6bb6f557abb/d55629ff661d6cdf996fe4ed59702cdc/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-27-20-50.png" alt=""&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Search URL&lt;br /&gt;
&lt;code&gt;dash://{query}&lt;/code&gt;と入れておきます。これでDashがURLスキーム経由で呼び出されます&lt;/li&gt;
&lt;li&gt;Title&lt;br /&gt;
これはAlfredで検索するときに出るタイトルで、なんでも良いです&lt;/li&gt;
&lt;li&gt;Keywords&lt;br /&gt;
Alfredは基本的にはアプリケーションランチャーなので、いきなりリファレンス検索したい語句を入力しても検索はしてくれません。ここで作るカスタム検索を呼び出すよということを指示するためのキーワードを決めておく必要があります。通常は短いアルファベットにするはず。ここではdsとしました。&lt;/li&gt;
&lt;li&gt;Validation&lt;br /&gt;
ここに入れた語句をSearch URLの&lt;code&gt;query&lt;/code&gt;の部分に入れて検索テストを行います。無事Dashで検索ができていればOK&lt;/li&gt;
&lt;li&gt;アイコン&lt;br /&gt;
右側のアイコン部分に好みの画像をドロップするとアイコンを設定できます。見た目で何の検索をするのかわかりやすくなるので入れておいたほうがいいかも&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="使う"&gt;使う&lt;/h3&gt;
&lt;p&gt;Alfredを起動して&lt;code&gt;ds &lt;/code&gt;（最後はスペース）と入れてあげるとさっき設定した画像やタイトルがでてきます。ここに語句を入力して決定すればDashでの検索が完了します。便利すね。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/90e417ee-bc77-42d4-abbe-a6bb6f557abb/d55629ff661d6cdf996fe4ed59702cdc/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-27-20-50.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="特定のdocsetのみを検索したい"&gt;特定のDocsetのみを検索したい&lt;/h2&gt;
&lt;p&gt;さきほどはDash全体で検索をかけましたが、特定のリファレンスのみを対象とした検索をしたいことのほうが多いでしょう。そのためには2つの方法があります。&lt;/p&gt;
&lt;p&gt;どちらもキーワードというものを使います。Dashの設定画面の&lt;code&gt;Docset&lt;/code&gt;タブを見るとそれぞれのDocsetに対応するキーワードがわかります。&lt;/p&gt;
&lt;p&gt;例えばC++のリファレンスのキーワードは&lt;code&gt;cpp:&lt;/code&gt;です。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/9e734c61-86cf-4e8f-a36e-c0d68d187696/e6a4196f185630bff7f03bc4649166f7/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-27-21-02.png" alt=""&gt;&lt;/p&gt;
&lt;h3 id="検索語句でキーワードを指定"&gt;検索語句でキーワードを指定&lt;/h3&gt;
&lt;p&gt;先ほど設定したカスタム検索をそのまま使えます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/f9f04a53-0b4b-46c4-a9f8-917c76308efa/35466311376972bb7689f85d20cb847c/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-27-21-04.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;上のようにキーワード付きで検索語句を入力すれば対象のDocset内で検索をしてくれます。&lt;/p&gt;
&lt;p&gt;こんな風に。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/ff408885-381e-4548-8ced-eb5b8303106e/0216f15e6695122e8c59baca28a285df/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-27-21-06.png" alt=""&gt;&lt;/p&gt;
&lt;h3 id="alfredでキーワードを指定したカスタム検索を作る"&gt;Alfredでキーワードを指定したカスタム検索を作る&lt;/h3&gt;
&lt;p&gt;最初と同じ手順でAlfredの&lt;code&gt;Custom Searches&lt;/code&gt;を新規作成し、&lt;code&gt;Search URL&lt;/code&gt;にはキーワードも入れておくようにします。これで対象のDocsetのみを検索するAlfredのカスタム検索が作れました。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/3da0f7a6-3d70-4a3c-b1f4-d8816f25cad1/e79e6d7101d14e471acdde278467b538/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-27-21-08.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="最後に"&gt;最後に&lt;/h2&gt;
&lt;p&gt;Docsetを指定するためのキーワードは独自のものに編集できます。特にDashに手動で認識させたDocsetは物によってはキーワードが&lt;code&gt;doxygen&lt;/code&gt;になっていたりするので編集しないと使い物にならないかもしれません。&lt;/p&gt;
&lt;p&gt;あと、Alfredで作る新しい検索とかの条件（上でカスタム検索とか適当に呼んでるやつ）のことを普通はなんて言うんでしょうかね？&lt;/p&gt;</description></item><item><title>Highcharts JSは1000件を超えるデータはプロットできません。デフォルトでは。</title><link>https://blog.piyo.tech/posts/2014-01-02-204306/</link><pubDate>Thu, 02 Jan 2014 20:42:52 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-02-204306/</guid><description>&lt;p&gt;昨日の記事でHighchartsについて話題にしました。今日は実際にHighchartsを使った際に思いっきりハマったところがあるので、そこについて書いておきます。&lt;/p&gt;
&lt;p&gt;昨日紹介したシンプルな例ではHighchartsに渡したデータ列には値のみが入っていました。このようなケースではデータ数は問題になりません（リファレンスによるとそのはず）。&lt;/p&gt;
&lt;p&gt;ですが、Highchartsではデータ1つ一つに名前を付けたり任意のキーで値を渡したりできます。&lt;/p&gt;
&lt;p&gt;1つ一つのデータはjson的な構造になっています。&lt;code&gt;y&lt;/code&gt;というキーはY軸用の値、&lt;code&gt;name&lt;/code&gt;というキーはツールチップに用いられる名前用の値です。それ以外にも任意のキーを使うことができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;#chart&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;highcharts&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [{&lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;s6w1vnde&amp;#34;&lt;/span&gt;},{&lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;,&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;t4g5qc7h&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;”&lt;/span&gt;},&lt;span style="color:#960050;background-color:#1e0010"&gt;…&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; }]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;iframe width="100%" height="300" src="https://jsfiddle.net/Zr2f4/2/embedded" allowfullscreen="allowfullscreen" frameborder="0"&gt;&lt;/iframe&gt;
&lt;p&gt;このようなデータを渡す場合はデフォルトのデータ上限が1000までとなっていて、1000よりも多いデータを渡すと何も表示されなくなってしまいます。エラーは出ません。&lt;/p&gt;
&lt;p&gt;確認のためにデータ数を1001にしてみます。&lt;/p&gt;
&lt;iframe width="100%" height="300" src="https://jsfiddle.net/rtBhK/3/embedded" allowfullscreen="allowfullscreen" frameborder="0"&gt;&lt;/iframe&gt;
&lt;p&gt;resultタブを見ればわかりますが、グラフが描画されていません。&lt;/p&gt;
&lt;p&gt;どうせなんかパラメータがあるんだろうと思ってHighchartsのリファレンスを&lt;code&gt;limit&lt;/code&gt;とか&lt;code&gt;max&lt;/code&gt;で検索したのですが全然ヒットせず、困り果てました。&lt;/p&gt;
&lt;p&gt;結局なんだったかというと、&lt;code&gt;turboThreshold&lt;/code&gt;とかいう直感的でないパラメータがありました。わかりづれえ！&lt;/p&gt;
&lt;p&gt;この&lt;code&gt;turboThreshold&lt;/code&gt;は次のような感じで設定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;#chart&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;highcharts&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;turboThreshold&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// ゼロで無制限、数値でその値まで許す
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#960050;background-color:#1e0010"&gt;…&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; }]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;さきほどと同じデータ数ですが、こちらは表示されます。&lt;/p&gt;
&lt;iframe width="100%" height="300" src="https://jsfiddle.net/DWxDp/1/embedded" allowfullscreen="allowfullscreen" frameborder="0"&gt;&lt;/iframe&gt;</description></item><item><title>JavaScriptでかっこいいグラフを書けるHighcharts JS</title><link>https://blog.piyo.tech/posts/2014-01-01-193806/</link><pubDate>Wed, 01 Jan 2014 19:37:52 +0900</pubDate><guid>https://blog.piyo.tech/posts/2014-01-01-193806/</guid><description>&lt;p&gt;あけましておめでとうございます。&lt;/p&gt;
&lt;p&gt;12月の途中から集中的に更新してみたんですが、何でもいいから書くっていうのが少し楽しくなってきました。今年もそんな感じでいければと思います。&lt;/p&gt;
&lt;p&gt;さて本題。&lt;/p&gt;
&lt;p&gt;HTMLでグラフを扱うライブラリは多数ありますが、その中でもとりわけ使いやすくて見た目もきれいなのがHighcharts JSです。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.highcharts.com/"&gt;Highcharts - Interactive JavaScript charts for your webpage&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;はてなブックマーク数が多いことから考えると日本でもかなりの認知度があるようです。&lt;/p&gt;
&lt;h2 id="導入使い方"&gt;導入・使い方&lt;/h2&gt;
&lt;p&gt;普通のJavascriptなライブラリと同様、Webサイトからダウンロードしてきてscriptタグに入れるだけです。ホスティングされているファイルを使うっていうのも有りかもしれません。なお商用利用は有料のようなので注意が必要です。&lt;/p&gt;
&lt;p&gt;使い方はかなりシンプルですが、オプションが複雑です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;“chart”&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#960050;background-color:#1e0010"&gt;“#&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;chart&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;”&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;highcharts&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// オプションやデータをずらずら〜っと書く
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ミニマルな折れ線グラフ"&gt;ミニマルな折れ線グラフ&lt;/h2&gt;
&lt;p&gt;適当にデータを渡すだけでこれだけのグラフを書いてくれます。すごいです。CorePlotをディスるわけじゃないですが比べ物にならないですねｗ&lt;/p&gt;
&lt;iframe width="100%" height="300" src="https://jsfiddle.net/DZw99/3/embedded" allowfullscreen="allowfullscreen" frameborder="0"&gt;&lt;/iframe&gt;
&lt;h2 id="デモ集"&gt;デモ集&lt;/h2&gt;
&lt;p&gt;ここで色々書くよりもデモを紹介したほうが早いことに気がついたので。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.highcharts.com/demo/"&gt;Highcharts - Basic line&lt;/a&gt;&lt;/p&gt;</description></item><item><title>iOS用グラフ描画ライブラリCorePlot超入門</title><link>https://blog.piyo.tech/posts/2013-12-30-214504/</link><pubDate>Mon, 30 Dec 2013 21:44:56 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-30-214504/</guid><description>&lt;p&gt;iOS（とかOSX）でグラフを書けるCorePlotいいよー。オプションとかいろいろあって煩雑だけどそこはさておいて簡潔にまとめてみようと思います。&lt;/p&gt;
&lt;h2 id="まずは導入編"&gt;まずは導入編&lt;/h2&gt;
&lt;p&gt;CocoaPods使いましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#39;CorePlot&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;からの&lt;code&gt;$ pod install&lt;/code&gt;でいけます。&lt;/p&gt;
&lt;h2 id="散布図折れ線グラフ"&gt;散布図、折れ線グラフ&lt;/h2&gt;
&lt;p&gt;サンプルとしてグラフは2つ書きました。Aがオプションをできるだけ省略したほう、Bがオプションをいくつか付けてみたほうです。配列に20個のランダムな整数値を入れ、配列のインデックスを横軸、その値を縦軸にとった折れ線のグラフを描画しました。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/95ad4c5e-df28-40c5-9431-7db4d6754aa1/b3d8cbc2bf8a18901659d20ee1d1e241/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-27-23-37.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ちゃんと使うにはグラフ用のUIViewクラスを作ってラップしたほうがいいと思いますが、今回はそれも面倒なのでViewControllerに直接書きます！&lt;/p&gt;
&lt;p&gt;散布図を載せたいViewControllerを作ってヘッダーにはプロトコルの指定とプロット用データ置き場を書き加えました。Objective-CのArrayはちょっと面倒なので、、、なお、C++のコードなのでViewControllerの拡張子は&lt;code&gt;.mm&lt;/code&gt;にしておく必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;UIKit/UIKit.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;CorePlot/CorePlot-CocoaTouch.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;vector&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ScatterViewController&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;UIViewController&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;CPTPlotDataSource&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;vector&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; _dataA;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;vector&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; _dataB;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次に実装ファイルのほう。&lt;/p&gt;
&lt;p&gt;グラフ領域やオプションなどの初期設定は&lt;code&gt;viewDidLoad&lt;/code&gt;で行いました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; [super viewDidLoad];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Do any additional setup after loading the view.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// CorePlotのセットアップ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; [self setupPlotA];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; [self setupPlotB];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="グラフa"&gt;グラフA&lt;/h3&gt;
&lt;p&gt;次にグラフA用のセットアップです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;setupPlotA&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; CGRect rect &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CGRectMake(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;320&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; CPTGraphHostingView&lt;span style="color:#f92672"&gt;*&lt;/span&gt; hostingView &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[CPTGraphHostingView alloc] initWithFrame:rect];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; CPTGraph&lt;span style="color:#f92672"&gt;*&lt;/span&gt; graph &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[CPTXYGraph alloc] initWithFrame:rect];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; hostingView.hostedGraph &lt;span style="color:#f92672"&gt;=&lt;/span&gt; graph;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; CPTScatterPlot&lt;span style="color:#f92672"&gt;*&lt;/span&gt; plot &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[CPTScatterPlot alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; plot.identifier &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;A&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; plot.dataSource &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; [graph addPlot:plot];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; CPTXYPlotSpace&lt;span style="color:#f92672"&gt;*&lt;/span&gt; space &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (CPTXYPlotSpace&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)graph.defaultPlotSpace;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; space.yRange &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInt(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) length:CPTDecimalFromInt(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;)];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; space.xRange &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInt(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) length:CPTDecimalFromInt(&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt;)];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; [self.view addSubview:hostingView];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// プロット用データのセットアップ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; _dataA.clear();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;; &lt;span style="color:#f92672"&gt;++&lt;/span&gt;i){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; _dataA.push_back(rand()&lt;span style="color:#f92672"&gt;%&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;いくつかCorePlotのクラスが登場しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CPTGraphHostingView&lt;br /&gt;
グラフが描画されるUIViewで親のViewに&lt;code&gt;addSubview&lt;/code&gt;されます&lt;/li&gt;
&lt;li&gt;CPTGraph&lt;br /&gt;
グラフのメタデータ？的なものです。グラフ全体を管理しているイメージ&lt;/li&gt;
&lt;li&gt;CPTScatterPlot&lt;br /&gt;
データをどのように処理するか（描画するか）ということを扱っているクラス（というイメージ）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;大雑把に言うと、&lt;code&gt;CPTScatterPlot&lt;/code&gt;を&lt;code&gt;CPTGraph&lt;/code&gt;にセットして、&lt;code&gt;CPTGraph&lt;/code&gt;を&lt;code&gt;CPTGraphHostingView&lt;/code&gt;にセット、その&lt;code&gt;CPTGraphHostingVIew&lt;/code&gt;を&lt;code&gt;addSubview&lt;/code&gt;するという流れです。&lt;/p&gt;
&lt;h3 id="グラフb"&gt;グラフB&lt;/h3&gt;
&lt;p&gt;グラフBではオプションをいくつか設定しました。本当はもっとたくさんのオプションがあるのですが、把握しきれないため適当にいくつか選んでいじっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;setupPlotB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; CGRect rect &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CGRectMake(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;210&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;320&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; CPTGraphHostingView&lt;span style="color:#f92672"&gt;*&lt;/span&gt; hostingView &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[CPTGraphHostingView alloc] initWithFrame:rect];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; CPTGraph&lt;span style="color:#f92672"&gt;*&lt;/span&gt; graph &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[CPTXYGraph alloc] initWithFrame:rect];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; hostingView.hostedGraph &lt;span style="color:#f92672"&gt;=&lt;/span&gt; graph;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; CPTScatterPlot&lt;span style="color:#f92672"&gt;*&lt;/span&gt; plot &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[CPTScatterPlot alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; plot.identifier &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;B&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; plot.dataSource &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; [graph addPlot:plot];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; CPTXYPlotSpace&lt;span style="color:#f92672"&gt;*&lt;/span&gt; space &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (CPTXYPlotSpace&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)graph.defaultPlotSpace;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; space.yRange &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInt(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) length:CPTDecimalFromInt(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;)];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; space.xRange &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInt(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) length:CPTDecimalFromInt(&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt;)];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; [self.view addSubview:hostingView];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// プロット用データのセットアップ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; _dataB.clear();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;; &lt;span style="color:#f92672"&gt;++&lt;/span&gt;i){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; _dataB.push_back(rand()&lt;span style="color:#f92672"&gt;%&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// いろいろ設定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; graph.plotAreaFrame.paddingBottom &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; graph.plotAreaFrame.paddingLeft &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; graph.plotAreaFrame.paddingTop &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; graph.plotAreaFrame.paddingRight &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 軸の設定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; CPTXYAxisSet&lt;span style="color:#f92672"&gt;*&lt;/span&gt; axisSet &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (CPTXYAxisSet&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)graph.axisSet;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; CPTMutableLineStyle&lt;span style="color:#f92672"&gt;*&lt;/span&gt; style &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [CPTMutableLineStyle lineStyle];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; style.lineColor &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [CPTColor orangeColor];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; style.lineWidth &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; axisSet.xAxis.axisLineStyle &lt;span style="color:#f92672"&gt;=&lt;/span&gt; style;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; axisSet.yAxis.axisLineStyle &lt;span style="color:#f92672"&gt;=&lt;/span&gt; style;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; CPTXYAxis&lt;span style="color:#f92672"&gt;*&lt;/span&gt; xAxis &lt;span style="color:#f92672"&gt;=&lt;/span&gt; axisSet.xAxis;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; xAxis.majorIntervalLength &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CPTDecimalFromInt(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt; NSNumberFormatter&lt;span style="color:#f92672"&gt;*&lt;/span&gt; tickFormatter &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[NSNumberFormatter alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;42&lt;/span&gt;&lt;span&gt; [tickFormatter setGeneratesDecimalNumbers:NO];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;43&lt;/span&gt;&lt;span&gt; [tickFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;44&lt;/span&gt;&lt;span&gt; xAxis.labelFormatter &lt;span style="color:#f92672"&gt;=&lt;/span&gt; tickFormatter;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;45&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;46&lt;/span&gt;&lt;span&gt; xAxis.title &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;X軸&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;47&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;48&lt;/span&gt;&lt;span&gt; CPTXYAxis&lt;span style="color:#f92672"&gt;*&lt;/span&gt; yAxis &lt;span style="color:#f92672"&gt;=&lt;/span&gt; axisSet.yAxis;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;49&lt;/span&gt;&lt;span&gt; yAxis.majorIntervalLength &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CPTDecimalFromInt(&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;50&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;51&lt;/span&gt;&lt;span&gt; yAxis.title &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;Y軸&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;52&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;53&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// プロットの設定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;54&lt;/span&gt;&lt;span&gt; plot.dataLineStyle &lt;span style="color:#f92672"&gt;=&lt;/span&gt; nil;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;55&lt;/span&gt;&lt;span&gt; plot.plotSymbol &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [CPTPlotSymbol diamondPlotSymbol];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;56&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;すごく長くなってしまうのがわかりますね。正直、ここは結構面倒です。&lt;/p&gt;
&lt;h3 id="datasourceのメソッド"&gt;DataSourceのメソッド&lt;/h3&gt;
&lt;p&gt;さきほどまでのコードでは、肝心のグラフに載せるためのデータはほとんど登場しません。せいぜいランダムな値をvectorに追加したぐらい。CorePlotではデータを返すメソッドを使います。TableViewみたいな感じで。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;numberForPlot&lt;/code&gt;&lt;br /&gt;
プロット用の値で、ScatterPlotの場合はidxに対応したXの値またはYの値を返します&lt;/li&gt;
&lt;li&gt;&lt;code&gt;numberOfRecordsForPlat&lt;/code&gt;&lt;br /&gt;
プロットの項目数を返してあげます&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (NSNumber &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;numberForPlot:&lt;/span&gt;(CPTPlot &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)plot &lt;span style="color:#a6e22e"&gt;field:&lt;/span&gt;(NSUInteger)fieldEnum &lt;span style="color:#a6e22e"&gt;recordIndex:&lt;/span&gt;(NSUInteger)idx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; NSNumber&lt;span style="color:#f92672"&gt;*&lt;/span&gt; num;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (fieldEnum) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; CPTScatterPlotFieldX:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; num &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSNumber numberWithInt:idx];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; CPTScatterPlotFieldY:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// plot.identifierで分岐することで、2種類以上のグラフを同じDataSourceクラスで書くことができる
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;([(NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)plot.identifier isEqualToString:&lt;span style="color:#e6db74"&gt;@&amp;#34;A&amp;#34;&lt;/span&gt;]){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; num &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSNumber numberWithInt:_dataA[idx]];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; }&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; num &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSNumber numberWithInt:_dataB[idx]];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; num;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;- (NSUInteger)&lt;span style="color:#a6e22e"&gt;numberOfRecordsForPlot:&lt;/span&gt;(CPTPlot &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)plot
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;([(NSString&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)plot.identifier isEqualToString:&lt;span style="color:#e6db74"&gt;@&amp;#34;A&amp;#34;&lt;/span&gt;]){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;)_dataA.size();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;)_dataB.size();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今回の例ではグラフA、Bという2つのグラフが登場します。これらはどちらも同じDataSourceメソッドを使うことになるので、&lt;code&gt;plot.identifier&lt;/code&gt;を使ってどちらのグラフのための情報を返すときなのかを判別して値を返しています。&lt;/p&gt;
&lt;h2 id="円グラフ"&gt;円グラフ&lt;/h2&gt;
&lt;p&gt;こんな感じのグラフを書けます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/954ea992-84c2-43d3-b8cb-bf4ae15b187f/cb981ca3fe17af005e6330bba5abae14/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-27-23-58.png" alt=""&gt;&lt;/p&gt;
&lt;h3 id="ヘッダーファイル"&gt;ヘッダーファイル&lt;/h3&gt;
&lt;p&gt;ヘッダーはこんな感じ。基本は似通っています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;UIKit/UIKit.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;CorePlot/CorePlot-CocoaTouch.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;vector&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PieViewController&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;UIViewController&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;CPTPieChartDataSource,CPTPieChartDelegate&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;vector&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;float&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; _data;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="実装ファイル"&gt;実装ファイル&lt;/h3&gt;
&lt;p&gt;実装はこんな感じです。&lt;code&gt;CPTScatterPlot&lt;/code&gt;の変わりに&lt;code&gt;CPTPieChart&lt;/code&gt;が登場し（どちらも同じ親クラスを持ちます）、それに関連した設定が必要となっています。&lt;/p&gt;
&lt;p&gt;また、&lt;code&gt;CPTTheme&lt;/code&gt;という概念があって、グラフのビジュアルをいくつかのテーマに基づいて切り替えることができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;setupChartA&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; CGRect rect &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CGRectMake(&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; CPTGraphHostingView&lt;span style="color:#f92672"&gt;*&lt;/span&gt; hostingView &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[CPTGraphHostingView alloc] initWithFrame:rect];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; CPTGraph&lt;span style="color:#f92672"&gt;*&lt;/span&gt; graph &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[CPTXYGraph alloc] initWithFrame:rect];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; graph.axisSet &lt;span style="color:#f92672"&gt;=&lt;/span&gt; nil;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; hostingView.hostedGraph &lt;span style="color:#f92672"&gt;=&lt;/span&gt; graph;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; [self.view addSubview:hostingView];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; CPTTheme&lt;span style="color:#f92672"&gt;*&lt;/span&gt; theme &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [CPTTheme themeNamed:kCPTDarkGradientTheme];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; [graph applyTheme:theme];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; CPTPieChart&lt;span style="color:#f92672"&gt;*&lt;/span&gt; plot &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[CPTPieChart alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; plot.identifier &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;PIE&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; plot.dataSource &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; plot.delegate &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; [graph addPlot:plot];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; plot.pieRadius &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; _data.clear();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; _data.push_back(&lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; _data.push_back(&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; _data.push_back(&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; _data.push_back(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; _data.push_back(&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="データソース"&gt;データソース&lt;/h3&gt;
&lt;p&gt;円グラフの場合は2次元ではないので返す値は場合分けの必要はありません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;- (NSNumber &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;numberForPlot:&lt;/span&gt;(CPTPlot &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)plot &lt;span style="color:#a6e22e"&gt;field:&lt;/span&gt;(NSUInteger)fieldEnum &lt;span style="color:#a6e22e"&gt;recordIndex:&lt;/span&gt;(NSUInteger)idx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [NSNumber numberWithFloat:_data[idx]];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="棒グラフ"&gt;棒グラフ&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/5f2eae63-cb81-4285-b04e-447dce681fbd/410aecde110a97d8913a5bddc97cbf79/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-28-0-01.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;こんなグラフを書けます。使ったテーマが悪いのか、めちゃくちゃシンプルだな、、&lt;/p&gt;
&lt;p&gt;長くなったのでソースは省略します。以下にサンプルアプリ一式があるのでどぞー。
&lt;a href="https://github.com/pi-chan/CorePlotExample"&gt;pi-chan/CorePlotExample&lt;/a&gt;&lt;/p&gt;</description></item><item><title>SimpleOAuthでAPI呼び出し</title><link>https://blog.piyo.tech/posts/2013-12-29-194003/</link><pubDate>Sun, 29 Dec 2013 19:39:52 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-29-194003/</guid><description>&lt;p&gt;TwitterAPIのRuby用ラッパーのソース（&lt;a href="https://github.com/sferik/twitter"&gt;sferik/twitter&lt;/a&gt; ）を読んでいてSimpleOAuthというライブラリを知ったので、はてなブックマークのAPIを例にしてちょっとした使い方の例を書いてみます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/laserlemon/simple_oauth"&gt;laserlemon/simple_oauth&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;はてなのAPIについてはこちらを参考にしています。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://developer.hatena.ne.jp/ja/documents/bookmark/apis/atom"&gt;はてなブックマークAtomAPI - Hatena Developer Center&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;はてなの公式ドキュメントではOAuthライブラリを使った実装のサンプルが紹介されています。OAuthライブラリとSimpleOAuthの書き方の違いを見るために、あるURLのサイトをブックマークする場合について2パターン書いてみました。&lt;/p&gt;
&lt;p&gt;個人的にはSimpleOAuthが名前通りシンプルで好きです。&lt;/p&gt;
&lt;h2 id="oauthではてなブックマーク"&gt;OAuthではてなブックマーク&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;create_hatena_bookmark&lt;/span&gt;(url)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; @consumer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;OAuth&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Consumer&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;HATENA_CONSUMER_KEY&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;HATENA_CONSUMER_SECRET&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;site&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;request_token_path&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;https://www.hatena.com/oauth/initiate&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;access_token_path&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;https://www.hatena.com/oauth/token&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;authorize_path&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;https://www.hatena.ne.jp/oauth/authorize&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; access_token &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;OAuth&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;AccessToken&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; @consumer,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;token,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;secret
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; xml &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;lt;&amp;lt;-XML
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;entry xmlns&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://purl.org/atom/ns#&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;title&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;dummy&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/title&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;link rel=&amp;#34;related&amp;#34; type=&amp;#34;text/&lt;/span&gt;html&lt;span style="color:#e6db74"&gt;&amp;#34; href=&amp;#34;&lt;/span&gt;&lt;span style="color:#75715e"&gt;#{url}&amp;#34; /&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/entry&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; XML
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; response = access_token.post(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;http:/&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;b&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hatena&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ne&lt;span style="color:#f92672"&gt;.&lt;/span&gt;jp&lt;span style="color:#f92672"&gt;/&lt;/span&gt;atom&lt;span style="color:#f92672"&gt;/&lt;/span&gt;post&lt;span style="color:#e6db74"&gt;&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; xml,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; {&amp;#39;Content-Type&amp;#39; =&amp;gt; &amp;#39;application/xml&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; end
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="simpleoauthでブックマーク"&gt;SimpleOAuthでブックマーク&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;create_hatena_bookmark&lt;/span&gt;(url)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; credentials &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;consumer_key&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;HATENA_CONSUMER_KEY&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;consumer_secret&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;HATENA_CONSUMER_SECRET&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;token&lt;/span&gt;: user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;token,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;token_secret&lt;/span&gt;: user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;secret
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; post_url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;http://b.hatena.ne.jp/atom/post&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; auth_header &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;SimpleOAuth&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Header&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#e6db74"&gt;:post&lt;/span&gt;, post_url, {}, credentials)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; xml &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;lt;&amp;lt;-XML
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;entry xmlns&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://purl.org/atom/ns#&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;title&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;dummy&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/title&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;link rel=&amp;#34;related&amp;#34; type=&amp;#34;text/&lt;/span&gt;html&lt;span style="color:#e6db74"&gt;&amp;#34; href=&amp;#34;&lt;/span&gt;&lt;span style="color:#75715e"&gt;#{url}&amp;#34; /&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/entry&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; XML
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; conn = Faraday.new
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; response = conn.post(post_url) do |req|
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; req.headers[:authorization] = auth_header.to_s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; req.headers[:content_type] = &amp;#39;application/xm&lt;/span&gt;l&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; req&lt;span style="color:#f92672"&gt;.&lt;/span&gt;body &lt;span style="color:#f92672"&gt;=&lt;/span&gt; xml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Azureのサブスクリプションをまとめて管理するための設定</title><link>https://blog.piyo.tech/posts/2013-12-28-201608/</link><pubDate>Sat, 28 Dec 2013 20:15:57 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-28-201608/</guid><description>&lt;p&gt;QiitaのWindow Azure Advent Calendarの記事でも紹介されていますが、起業5年以内云々の条件に当てはまる会社の場合BizSparkというマイクロソフトの起業支援プログラムに加入できます。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qiita.com/oden@github/items/ba8e7d511f6bdf30c9fe"&gt;WindowsAzure - MicrosoftからAzureの使用料1080万円をもらう方法 - Qiita [キータ]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;BizSparkにはAzureの使用料も含まれており、1マイクロソフトアカウントあたり毎月12500円分の無料枠を使用できます。 プログラムでは8アカウント分の無料アカウントを使うことができるので毎月10万円の無料枠を使えるわけ。お得。&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;b&gt;（※このあたりの数字はいろいろ変わっているかもしれないので、そのときの最新情報を参照するといいと思います。）&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;この制度を使ってAzureを利用するときにちょっと面倒なことがあって、無料枠がアカウント毎に設けられているのでインスタンスをいろいろなアカウントで管理する必要がでてきます。アカウント1ではウェブサーバー、アカウント2ではDBみたいなね。そうしないと1アカウント分の無料枠なんてすぐなくなるしね。&lt;/p&gt;
&lt;p&gt;Azureではこういう場合でも1つのアカウントで他のアカウントをまとめて管理できるようになっています。なので、アカウント1のインスタンスをいじった後でアカウント2の管理をするためにログアウト→ログインを行うっていう面倒なプロセスは必要ありません。&lt;/p&gt;
&lt;h2 id="共同管理者を使う"&gt;共同管理者を使う&lt;/h2&gt;
&lt;p&gt;共同管理者という設定項目を使います。&lt;/p&gt;
&lt;p&gt;例えばアカウント1〜8の8つのアカウントがあって、アカウント1で2〜8を一括管理したいとします。&lt;/p&gt;
&lt;p&gt;その場合、アカウント2〜8の全てで共同管理者にアカウント1を追加してあげる必要があります。ここだけはログインログアウトを繰り返すので少し面倒ですが、仕方ない。&lt;/p&gt;
&lt;p&gt;Azure管理画面のメニューから設定を選び、&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7d5e4e9a-b817-4c97-be4c-d5bb63dd3fa6/d25427b1c1172563a0bc3baddad88694/deep/0/%E8%A8%AD%E5%AE%9A---Windows-Azure.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;管理者タブを開いて追加をクリックします。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/b9174166-8cd1-443a-88d0-ab7562b281b3/1b5a48ac57cf77445347473da12a17a9/deep/0/%E8%A8%AD%E5%AE%9A---Windows-Azure.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;その後、アカウント2（3〜8）の情報を入れて管理者設定を済ませます。&lt;/p&gt;
&lt;p&gt;全てのアカウントで共同管理者設定を済ませたあとアカウント1でログインし直し、先ほどの管理者タブを見ると他のアカウントの共同管理者になっていることがわかるはず。&lt;/p&gt;
&lt;p&gt;インスタンス生成時に、どのアカウントのサブスクリプション（アカウントとほぼ同義みたいなもん）で作るかなどを指定すれば無料枠を分けてインスタンスを管理できます！&lt;/p&gt;
&lt;h2 id="というのは2013年12月現在嘘"&gt;というのは、2013年12月現在嘘、、、&lt;/h2&gt;
&lt;p&gt;僕がよく使っていた2013年9月頃までは先ほど書いた方法でいけたのですが、最近はアクティブディレクトリの概念がマイクロソフトアカウントにも導入されたようで、アクティブディレクトリに関わる設定も必要になってしまいました。&lt;/p&gt;
&lt;p&gt;一覧表示するときに、ご丁寧にアクティブディレクトリ毎にフィルタリングをかけられてしまっています。めちゃくちゃ面倒くさいです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/ef4f2794-edad-4c37-9686-6f3609ca9353/fa5788a88891acfc099a3460ec6a16e5/deep/0/Active-Directory---Windows-Azure.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="アクティブディレクトリを使う"&gt;アクティブディレクトリを使う&lt;/h2&gt;
&lt;p&gt;まず一括管理したいアカウント（さっきの例でいうアカウント1）でログインし、メニューからACTIVE DIRECTORYを開きます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c6c35d44-92df-4d3a-b3ae-c10b2447bc47/c558711fafcef00b83cb32e4543fb504/deep/0/Active-Directory---Windows-Azure.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;そしてユーザーの追加をクリックし、アカウント2〜8を追加します。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/a64c4a1c-c013-4dfc-a843-a9d5ff7e2688/31874a5e72092c88a0b7275c90b65709/deep/0/Active-Directory---Windows-Azure.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;これでアカウント1でも設定は終わり。&lt;/p&gt;
&lt;p&gt;次のステップはアカウント2〜8全てで行う必要があります。ああめんどくさい。&lt;/p&gt;
&lt;p&gt;設定メニュー、サブスクリプションタブからサブスクリプションを選びます。通常1つしかないはずです。そしてディレクトリの編集をします。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/cd251926-e50b-4c4e-8467-6997d06b6ed3/15a4849f9b89c0fc749dc49cf2b20d9c/deep/0/%E8%A8%AD%E5%AE%9A---Windows-Azure.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;アカウント1のディレクトリに変更してあげればOKです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/0521f959-ae27-4010-b827-6dfff5a88c31/bb592b458c68b3f21d3350a75cb2303f/deep/0/%E8%A8%AD%E5%AE%9A---Windows-Azure.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;できた！&lt;/p&gt;
&lt;p&gt;これで、アカウント1のディレクトリ内に全てのアカウントのサブスクリプションが含まれるので一括で管理できるようになりました。&lt;/p&gt;</description></item><item><title>UIImageの色相をフィルターで変えるには</title><link>https://blog.piyo.tech/posts/2013-12-27-203706/</link><pubDate>Fri, 27 Dec 2013 20:36:56 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-27-203706/</guid><description>&lt;p&gt;iOSのアプリを開発していてこんな要望がありました。&lt;/p&gt;
&lt;p&gt;「撮影した写真を半透明にした上で色を少し変えて出したいから、ちょうどいい値を探したい」&lt;/p&gt;
&lt;p&gt;どの程度半透明にするかはalpha値に対応したスライダーをおけばいいなというのはすぐにわかりましたが、色を変えるってどうやんの？と。&lt;/p&gt;
&lt;p&gt;結論を言えば、&lt;code&gt;CoreImage&lt;/code&gt;のフィルターを使えば余裕でした。&lt;/p&gt;
&lt;h2 id="cifilterを使って色を変える"&gt;CIFilterを使って色を変える&lt;/h2&gt;
&lt;p&gt;色を変えると言ってもいろいろありますが、ここでは全体的な色合いを赤っぽくしたり青っぽくしたり、といったことを意味します。CIFilterを使って色相を調整するのがこれにあたります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;UIImageからCIImageを作る&lt;/li&gt;
&lt;li&gt;CIImageと各種パラメータを渡したCIFiterを作る&lt;/li&gt;
&lt;li&gt;CGImageを取り出す&lt;/li&gt;
&lt;li&gt;UIImageに直す&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;一般的に色相は色相環という輪っかで表現されます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/584bd18e-09a8-49ea-a7b7-7fd13afb6a9f/72bd3459152247041d85bcff38580a7c/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-24-20-50.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;そのためCIFilterで色相を調整するときも-3.14〜3.14の範囲でパラメータを指定できます。&lt;/p&gt;
&lt;p&gt;今回は値の範囲が-3.14〜3.14のスライダーを配置し、スライダーの値が変わったときのイベントで元画像にフィルターをかけてUIImageViewに設定し直すという方法を取ります。&lt;/p&gt;
&lt;p&gt;これで先方の要望である、ちょうどいい値を探すという目的に合ったスライダーを実装できました。&lt;/p&gt;
&lt;h2 id="ソース"&gt;ソース&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;IBAction&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;hueChanged:&lt;/span&gt;(UISlider &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)sender {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; UIImage&lt;span style="color:#f92672"&gt;*&lt;/span&gt; image &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [UIImage imageNamed:&lt;span style="color:#e6db74"&gt;@&amp;#34;image.png&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; CIImage &lt;span style="color:#f92672"&gt;*&lt;/span&gt;ciImage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[CIImage alloc] initWithImage:image];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; CIFilter &lt;span style="color:#f92672"&gt;*&lt;/span&gt;ciFilter &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [CIFilter filterWithName:&lt;span style="color:#e6db74"&gt;@&amp;#34;CIHueAdjust&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; keysAndValues:kCIInputImageKey, ciImage,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;inputAngle&amp;#34;&lt;/span&gt;,[NSNumber numberWithFloat:sender.value], nil];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; CIContext &lt;span style="color:#f92672"&gt;*&lt;/span&gt;ciContext &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [CIContext contextWithOptions:nil];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; CGImageRef cgimg &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [ciContext createCGImage:[ciFilter outputImage] fromRect:[[ciFilter outputImage] extent]];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; UIImage&lt;span style="color:#f92672"&gt;*&lt;/span&gt; newImage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [UIImage imageWithCGImage:cgimg scale:&lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt; orientation:UIImageOrientationUp];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; CGImageRelease(cgimg);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; self.imageView.image &lt;span style="color:#f92672"&gt;=&lt;/span&gt; newImage;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="結果"&gt;結果&lt;/h2&gt;
&lt;p&gt;こんな感じ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/QVUhhGj4FSUUacT_Te2_3uS8gymW58ON_bAJTLkfjMUwHR5WrS90dw17sZ2dgrl6LAU8JhudooVeqRe3vWGLTeI4Zhwn96cQhrnWW0cpJM1LzQ5roPuMxs1fRIvKV5K32IqlKxMxOxmE3zE8C8QpqMWxt_7BARJ26S2k3dlHL9T_eYRMxwwhFSykc3scR0t6WJ7WVTCb8ZYeiUmgJO1saJlK8p3UgDuS-fmxQoZvZsah-c3zJdfmGQ0b5iPOQqP0GYNMPBjIywgGjsG6EIwK8dFw-5PtIYIgGfmk9mcdOCz0HqXd7cWhISdmARhCaS4jmUFo_STlKiFmP3HwU2JMgLFDXfq_LX6zsrpDSYCeXcWEXljAaZvLYuYH8CKGXJQIuJRTJbKtnGtJAkxYrfUoznPd8tlV7-zpUVulQqKnLyKeQkGw1Oe6DSVvX764hSSRxf1_u9frqiezCRIA0xj6vBTmQIJbfqtQhS4_sjJ7VQCQVm3PWJp6UUqRW4KzSGiNIEF17wSSWm60TVx9Ai619_cfvUaU7LdzBg10A-wNmJJcysHlWsp4Ft4D8BKmvIFpcjDl6Fzq0h20ogk0pIaS2OMBnWDDJMsba8w-xmU5mgBg2nQWuNs35xPpxcIjNd_2KFQqGmOhp6U7Jkztwl5e3_hzcBM1T3z1yQ=w304-h540-no" alt=""&gt;&lt;/p&gt;
&lt;p&gt;リアルタイム処理に使うには少々重いのですが、検証用ということで細かいことは考えていません。&lt;/p&gt;</description></item><item><title>iOSで他のUIViewの下（裏）に隠れているボタン等を押させる</title><link>https://blog.piyo.tech/posts/2013-12-26-202107/</link><pubDate>Thu, 26 Dec 2013 20:20:58 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-26-202107/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/f7c40c6c-57c6-4c66-8c69-c3568f43af31/4401abae2c2d94185ba714be945c66c2/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-23-20-00.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;先日、この図に相当するケースでUIViewに隠れているボタンを押せるようにしたいということがありました。&lt;/p&gt;
&lt;p&gt;何も指示しないと手前のUIViewがイベントを受け取ってしまうのでその下にあるUIButtonはタップできませんが、UIViewの&lt;code&gt;userInteractionEnabled&lt;/code&gt;というパラメータを&lt;code&gt;NO&lt;/code&gt;にしてあげれば、そのUIViewはユーザー操作のイベントを無視して、裏の要素にイベントが伝わるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;view.userInteractionEnabled &lt;span style="color:#f92672"&gt;=&lt;/span&gt; NO;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Ruby単体でローカルWebサーバーを起動する方法</title><link>https://blog.piyo.tech/posts/2013-12-25-205107/</link><pubDate>Wed, 25 Dec 2013 20:51:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-25-205107/</guid><description>&lt;p&gt;先日の記事内でも触れたけど、ちゃんと見出しを付けて記事にしておいたほうがいいかなと思い抜粋しました。シングルカットみたいなもんです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-12-17-202105"&gt;md2review+ReVIEW+guard+livereloadで快適ドキュメントライティング - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[https://blog.piyo.tech/posts/2013-12-17-202105:image:large]&lt;/p&gt;
&lt;p&gt;Rubyが入っていれば以下のコマンドで静的ファイルをサーブするWebサーバーを立てることができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ ruby -run -e httpd -- --port&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5000&lt;/span&gt; ./
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;--port=&lt;/code&gt;に任意のポートを指定できるし、Webサーバーのドキュメントルートを指定することもできます（先のコマンドでは最後の引数&lt;code&gt;./&lt;/code&gt;）。&lt;/p&gt;</description></item><item><title>Deviseでログイン後のURLを変える方法</title><link>https://blog.piyo.tech/posts/2013-12-24-212603/</link><pubDate>Tue, 24 Dec 2013 21:25:57 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-24-212603/</guid><description>&lt;p&gt;RailsでDeviseを使っているときの話。いくらでも情報がある話ですが、自分のためにメモります。&lt;/p&gt;
&lt;p&gt;http://hostname/ にログインボタンを置いておいて、ログイン後はhttp://hostname/memberとかに移動したいケースがあると思いますが、これは比較的簡単に書けます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# application_controller.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ApplicationController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;after_sign_in_path_for&lt;/span&gt;(resource)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; member_path &lt;span style="color:#75715e"&gt;# ログイン後に遷移したいパス&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="応用例"&gt;応用例&lt;/h2&gt;
&lt;p&gt;Deviseのドキュメントからの引用です。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;after_sign_in_path_for&lt;/code&gt;ログイン前のパスを覚えておいて、ログイン後にはそちらのURLに戻るという遷移を実現できます。&lt;/p&gt;
&lt;p&gt;ありそうなシチュエーションとしては、FacebookとかでシェアされたコンテンツのURLを踏んだ人がサインアップしたらそのコンテンツのURLに飛ぶみたいな場合ですね。&lt;/p&gt;
&lt;p&gt;次のようなコードで実現できるようです。要はリクエストのたびにフルパスの情報をセッションに残しておいて、ログイン後のURLは保存しておいた値を使うというものです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# application_controller.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;after_filter &lt;span style="color:#e6db74"&gt;:store_location&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;store_location&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# store last url - this is needed for post-login redirect to whatever the user last visited.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fullpath &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/users/sign_in&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fullpath &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/users/sign_up&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fullpath &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/users/password&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;xhr?) &lt;span style="color:#75715e"&gt;# don&amp;#39;t store ajax calls&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; session&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:previous_url&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fullpath
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;after_sign_in_path_for&lt;/span&gt;(resource)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; session&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:previous_url&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; root_path
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>iOSでUIButtonの選択時の背景色をグラデーションにする</title><link>https://blog.piyo.tech/posts/2013-12-23-214708/</link><pubDate>Mon, 23 Dec 2013 21:47:03 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-23-214708/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/7acee576-abab-43c0-9b52-5253832ce812/c13bfcd5ef066ef848c25d6c858fefcd/deep/0/images.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;UIButtonの背景色をグラデーションにする方法は簡単です。適当にググればでてきますし。ですが、ボタンをタップしたときの色をグラデーションにする方法はちょっと面倒でトリッキーだったので紹介します。&lt;/p&gt;
&lt;p&gt;その前に、背景色を普通にグラデーションにする方法はこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qiita.com/hal_sk/items/200cafdf1ee381453f1a"&gt;Objective-C - UIButton をグラデーションにする - Qiita [キータ]&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="uibuttonのサブクラスを作る"&gt;UIButtonのサブクラスを作る&lt;/h2&gt;
&lt;p&gt;オリジナルのButton用クラスを用意しておくと便利です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// GradientButton.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;GradientButton&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;UIButton&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// GradientButton.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;#34;GradientButton.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@implementation&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;GradientButton&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;initWithCoder:&lt;/span&gt;(NSCoder &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)aDecoder
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; self &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [super initWithCoder:aDecoder];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; [self setupBackgroundGradientForState:UIControlStateNormal
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; colors:&lt;span style="color:#ae81ff"&gt;@[&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)[[UIColor cyanColor] CGColor],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)[[UIColor greenColor] CGColor]&lt;span style="color:#ae81ff"&gt;]&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; [self setupBackgroundGradientForState:UIControlStateHighlighted
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; colors:&lt;span style="color:#ae81ff"&gt;@[&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)[[UIColor magentaColor] CGColor],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; (&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)[[UIColor redColor] CGColor]&lt;span style="color:#ae81ff"&gt;]&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; self;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;setupBackgroundGradientForState:&lt;/span&gt;(NSUInteger)state
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;colors:&lt;/span&gt;(NSArray&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)colors
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; CAGradientLayer &lt;span style="color:#f92672"&gt;*&lt;/span&gt;gradient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[CAGradientLayer alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; gradient.frame &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self.bounds;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; gradient.colors &lt;span style="color:#f92672"&gt;=&lt;/span&gt; colors;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; UIGraphicsBeginImageContext(CGSizeMake(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, [self bounds].size.height));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; [gradient renderInContext: UIGraphicsGetCurrentContext()];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; UIImage &lt;span style="color:#f92672"&gt;*&lt;/span&gt;bgImage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; UIGraphicsGetImageFromCurrentImageContext();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; UIGraphicsEndImageContext();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; [self setBackgroundImage:bgImage forState:state];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;基本的にはUIViewの背景色をグラデーションにするときと同じく、&lt;code&gt;CAGradientLayer&lt;/code&gt;を用いてグラデーションを設定します。凝ったグラデーションを作る場合は&lt;code&gt;CAGradientLayer&lt;/code&gt;でいろいろやっている人を探せば見つかると思うので丸投げです。&lt;/p&gt;
&lt;p&gt;で、今回の肝なんですが、作った&lt;code&gt;CAGradientLayer&lt;/code&gt;を&lt;code&gt;addSubLayer&lt;/code&gt;するのではなく、&lt;code&gt;CAGradientLayer&lt;/code&gt;から&lt;code&gt;UIImage&lt;/code&gt;を生成して背景画像に設定してしまうという方法をとっています。背景画像の設定のときに&lt;code&gt;UIControlState&lt;/code&gt;を渡すのでUIControlStateHighlightedを渡してあげれば、タップ時の背景画像をグラデーションにするという目的を果たすことができます。&lt;/p&gt;
&lt;p&gt;ストーリーボードやXIBを使っている場合には、配置したUIButtonのカスタムクラスをこの&lt;code&gt;GradientButton&lt;/code&gt;クラスにしてあげれば良いです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/5855b9ab-f4ba-4bfe-b79c-fb90db3a484c/7c69a9630b2a1dc395cd54815f178cfd/deep/0/button.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="結果"&gt;結果&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/qQz7ZIi8cATZjev6xFS-bSi-i41huqXsE9-hU5HJPOimlkjpUQr_zlU3MAbWK6dIeuVPtj5iQ54GB3E7qLuuu8NjUhp-xNPF4FlW4K4SkU8vpF1B9NXOTlp5Mdm6haVXUJCtayeCX8e8Ye2cyBcLtm_OQY5fyWw0viWVDN6hN0sNReAGijRaUb7SABgvNmmc3y0PQ6ovWLokGWx1vf80TL-P8XaA-23d_QCqiDGjQHPfu-iORX54TGohN1k5-EQoNQppMPwRn198QHsxneUmH9CO6S-RGCFO7DZECMTIl-3kgiNOMSp0dr21sweTkt0rh4i7iFhq2C93bxUEw4K0yDiWtxd9TFsMxd39vz_8KLAnlEvotnrNzVjmkzhjhF344UaWvs3ui_nKa_kwuwXwFa55Oxh9PCJ37k0mY2OvyvNCA5MlWo-vUDrqPQsW7RgpJXJ6fNcA4wS366jPyDzcoqXNMVK8hgZrKGImFl2hJPX2U5pH7p-h7v8tmEZGIs7cP_qWg51S--JbO89fvG-TBsF3VIySZ6MuhDKee9x7BgG6SLOCnQECxe3lvGn34jovwy4RbQo7ePunn-9s3ly8oZ2h08PAgtRhhdTldLRmU7RxrSAZjLgO43IjlI9fzR_gJm09HlU4DaqtVMbF06Rz67DZ51WgpZ6u_g=w316-h458-no" alt=""&gt;&lt;/p&gt;
&lt;p&gt;タップがわかりづらいかもですが、ちゃんとタップ時の色をグラデーションにできていると思います。&lt;/p&gt;
&lt;h2 id="余談ハイライト時のエフェクトを無くす"&gt;余談:ハイライト時のエフェクトを無くす&lt;/h2&gt;
&lt;p&gt;上のGIF画像を見ると、タップしたときの背景色が指定したものよりも薄いことがわかると思います。これはデフォルトでつけられているエフェクトによってぼんやりと薄くなってしまっているわけですね。&lt;/p&gt;
&lt;p&gt;せっかく背景色をグラデーションにカスタマイズしたのに勝手にエフェクト掛けられたら困ると思い、エフェクトを消す方法をstackoverflowあたりでググって見ると、インスペクタで&lt;code&gt;Highlighted Adjusts Image&lt;/code&gt;をオフにする、またはコードで&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;button.adjustsImageWhenHighlighted &lt;span style="color:#f92672"&gt;=&lt;/span&gt; NO;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;のようにすればいいよ、ということでした。&lt;/p&gt;
&lt;p&gt;ですが、それは効かず！&lt;/p&gt;
&lt;p&gt;結局ボタンタイプを&lt;code&gt;System&lt;/code&gt;から&lt;code&gt;Custom&lt;/code&gt;にすればエフェクトはなくなりました。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/d0327afd-e581-4a99-9c33-68e1583504e3/f82b906e21ff565a60a871f93ff13b1a/deep/0/buttontype.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;設定後のグラデーションの様子はこちら。タップ時の色が濃くなったのがわかると思います。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/5C-P5Q4YcgXvuPZuTT5SxAWMyG26ZTKV7Upum6Obq1EYVXY9a7wMgXsYuF0ofMEvA6qtgg2MaEdhxpBePH46ZZ4BIQNTn6POTgNJaBl2gbPZGC8YlkxV02v29KVtzldHfO_aIuBLTIgNP8T62eHg8vbiOgf5l2I1FeQGuMauTmb8LNZUPgnBFG22vZud0du0A5KJC7kBkJzhpvUUqw-hXaDbrOUWHZJ6ps8ORO0_OSBjgbN0zl7fr1nB6QfKVKZHKPPDkzg6SuQhjHZxBxutxrSnaw0Exyxj-LdPNHsSZk4DGwuDvsUnBZXDHl5f1vVdcx2vSgv8VqM8pgBjR7ZWnvaDL5KDHLaOebTSuF66Wb0f_-mTZu0KggY4HQVXPFp32ny0yyfV7ZVN3Suf-Lq87SXlRuBtpJ4PqNQTBabJzB3dsfaG8IE_3-rkSHqHPrrU1NbLDAMG1S96Odp6YlnHs-15_7di172okHjUVhHzFvu98DIJsfYFQChYYPouvLj88OvC7DkJr8Hio06aqjHBdLvfWQZgPvm1YCrYVDo7CF0ZA1i9G21i7XhE3ZOzxaFo14-w4RZ4IQS4RJNXefzzHeVCjDKFjMBtkiVxhnfoLjNWKy_Hd6fvX8i6DFDFe3JqFAu_gX8pmWw6YBCOnDv6YsvBWeX01BBLnQ=w318-h464-no" alt=""&gt;&lt;/p&gt;</description></item><item><title>Skitch(Evernote)の画像URL共有がブログの画像に便利</title><link>https://blog.piyo.tech/posts/2013-12-22-204206/</link><pubDate>Sun, 22 Dec 2013 20:42:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-22-204206/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/a11ec9af-4f7e-4acb-922a-6227386f498f/c80507aecf1cb272562c90663d095c20/deep/0/hero_skitch-v2.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ブログに画像貼るのって面倒ですよね。このはてなブログで画像を貼るとしたら一旦アップロードしないといけません。それが嫌で少し前からDropboxのPublicディレクトリを使っているのですが、それすら面倒になってきました。&lt;/p&gt;
&lt;p&gt;ところが先日スクリーンショットを撮るためにSkitchを触っていたら、画像を共有できることを知りました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://evernote.com/intl/jp/skitch/"&gt;Skitch | Evernote&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Skitchの一覧で画像を右クリックするとメニューに共有してURLをコピーという機能があることがわかります。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/22e9446d-935e-443d-adef-12490beb23f1/2663150489394f659504557c118bdc02/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-18-19-06.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ここで共有すると対象の画像がノートとして公開されてURLをコピーできます。&lt;/p&gt;
&lt;p&gt;ブログに挿入するためにはEvernoteのノートでは困るので、少し設定を変えます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/91fc203b-e7db-432f-a419-800561821c99/f9a1e04acc7145db19dd5316f04205a3/deep/0/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2013-12-18-19-11.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;共有するURLを&lt;code&gt;画像の直URL&lt;/code&gt;に変えると画像の直リンクとして使えるようになります。この記事で貼り付けている画像ファイルもSkitchで編集した画像の共有URLを用いています。&lt;/p&gt;
&lt;p&gt;これでいちいちアップロードする必要もなくなりました。&lt;/p&gt;
&lt;p&gt;なおこのURLは同じ画像（というか、ノート）であればずっと有効で、Skitchで編集すれば新しい内容が反映されるようです。すごく便利では。&lt;/p&gt;</description></item><item><title>AVFoundationを使ったカメラ機能はちゃんとメモリを開放しましょう</title><link>https://blog.piyo.tech/posts/2013-12-21-205107/</link><pubDate>Sat, 21 Dec 2013 20:51:06 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-21-205107/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/48e9418f-a0d0-4e28-a8ac-f7e6a065f358/b149d9b9e02763b743239fa62175f703/deep/0/ios7_cameraapp.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;こちらを参考にAVFoundationを使ったカメラを実装したのですが、このやり方だとどうもメモリを圧迫するということがわかりました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://dev.classmethod.jp/smartphone/ios-camera-intro/"&gt;iOSのカメラ機能を使う方法まとめ【13日目】 ｜ Developers.IO&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;カメラ機能を使うビューに移動→戻る、を繰り返すとだんだんと移動が重くなっていきます。1分以上反応しなかったりとか。Xcodeでモニタリングしているメモリ使用量も増え続けます。&lt;/p&gt;
&lt;p&gt;調べてみると、viewDidLoadでセットアップを行ったAVFoundation系のオブジェクトを開放をしていないのが原因のようです。&lt;/p&gt;
&lt;p&gt;先の記事ではセットアップメソッド&lt;code&gt;setupAVCapture&lt;/code&gt;を&lt;code&gt;viewDidLoad&lt;/code&gt;で呼んでいます。ビューの移動、戻るを繰り返すとviewDidLoadでひたすらsetupAVCaptureが呼ばれ続けるわけですね。多分ARCで開放してくれるんでしょうけど、実用上は自前で開放を実装しておかないと使い物にならないようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// iOSのカメラ機能を使う方法まとめ【13日目】から引用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; [super viewDidLoad];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 略
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; [self setupAVCapture];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;setupAVCapture&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; NSError &lt;span style="color:#f92672"&gt;*&lt;/span&gt;error &lt;span style="color:#f92672"&gt;=&lt;/span&gt; nil;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 入力と出力からキャプチャーセッションを作成
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; self.session &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[AVCaptureSession alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 正面に配置されているカメラを取得
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; AVCaptureDevice &lt;span style="color:#f92672"&gt;*&lt;/span&gt;camera &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// カメラからの入力を作成し、セッションに追加
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; self.videoInput &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[AVCaptureDeviceInput alloc] initWithDevice:camera error:&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;error];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; [self.session addInput:self.videoInput];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 画像への出力を作成し、セッションに追加
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; self.stillImageOutput &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[AVCaptureStillImageOutput alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; [self.session addOutput:self.stillImageOutput];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// キャプチャーセッションから入力のプレビュー表示を作成
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; AVCaptureVideoPreviewLayer &lt;span style="color:#f92672"&gt;*&lt;/span&gt;captureVideoPreviewLayer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; captureVideoPreviewLayer.frame &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self.view.bounds;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; captureVideoPreviewLayer.videoGravity &lt;span style="color:#f92672"&gt;=&lt;/span&gt; AVLayerVideoGravityResizeAspectFill;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// レイヤーをViewに設定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; CALayer &lt;span style="color:#f92672"&gt;*&lt;/span&gt;previewLayer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self.previewView.layer;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; previewLayer.masksToBounds &lt;span style="color:#f92672"&gt;=&lt;/span&gt; YES;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; [previewLayer addSublayer:captureVideoPreviewLayer];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// セッション開始
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; [self.session startRunning];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="変更後"&gt;変更後&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;setupAVCapture&lt;/code&gt;を&lt;code&gt;viewDidLoad&lt;/code&gt;ではなく&lt;code&gt;viewWillAppear&lt;/code&gt;で呼び、開放処理を&lt;code&gt;viewDidDisappear&lt;/code&gt;で呼ぶようにすれば良いです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;tearDownAVCapture&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; [self.session stopRunning];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (AVCaptureOutput &lt;span style="color:#f92672"&gt;*&lt;/span&gt;output &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; self.session.outputs) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; [self.session removeOutput:output];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (AVCaptureInput &lt;span style="color:#f92672"&gt;*&lt;/span&gt;input &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; self.session.inputs) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; [self.session removeInput:input];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; self.stillImageOutput &lt;span style="color:#f92672"&gt;=&lt;/span&gt; nil;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; self.videoInput &lt;span style="color:#f92672"&gt;=&lt;/span&gt; nil;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; self.session &lt;span style="color:#f92672"&gt;=&lt;/span&gt; nil;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewWillAppear:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt;)animated
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; [self setupAVCapture];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;viewDidDisappear:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt;)animated
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; [self tearDownAVCapture];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでメモリを消費しすぎるということはなくなります。&lt;/p&gt;</description></item><item><title>Railsでログインとは別に複数のサービスとの連携を行う方法</title><link>https://blog.piyo.tech/posts/2013-12-20-212109/</link><pubDate>Fri, 20 Dec 2013 21:21:13 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-20-212109/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/c8beeb36-3895-4492-b910-e9a4417654b7/3b5bbe1ab3190583c6d16adc5be9c635/deep/0/rails1.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;ログインはメールアドレスでさせておいてログイン後に各種SSOサービスとの連携を済ませる方法を考えてみます。&lt;/p&gt;
&lt;p&gt;まず、お手軽にやりたいのでDeviseとOmniauthを使うのは確定です。&lt;code&gt;omniauth-facebook&lt;/code&gt;や&lt;code&gt;omniauth-twitter&lt;/code&gt;などを使うと簡単に連携できますよね。&lt;/p&gt;
&lt;p&gt;ところが、よくあるDevise+Omniauthのサンプルを見ると大体ユーザーモデルにOAuthの結果を結びつけていることが多いです。ユーザー1人に対してサービス一種類が関連づけられるみたいな。&lt;/p&gt;
&lt;p&gt;でも複数のサービスと接続したいということもありそうです。というか、実際多くのサービスでログインしたあとで他のサービスとの関連付けを行ったりできます。QiitaとかChatworkとか、Gunosyとかもそうだったかも。&lt;/p&gt;
&lt;h2 id="モデルを分けます"&gt;モデルを分けます&lt;/h2&gt;
&lt;p&gt;ユーザーモデルにサービスと認証したフィールドを持たせるからいけないのであって、ユーザーは独立して存在し認証情報は別モデルとしてユーザーと関連づければ、複数のサービスとの連携も可能です。&lt;/p&gt;
&lt;p&gt;複数のサービスを区別なく扱える認証モデルみたいなのを作って、ユーザーモデルと1対多の関係をもてばよさそう。&lt;/p&gt;
&lt;p&gt;実はまだ試していないので、今から実装しつつ試してみます。&lt;/p&gt;
&lt;h2 id="の方法でできました"&gt;↑の方法でできました&lt;/h2&gt;
&lt;p&gt;サンプルアプリケーションはこちらにあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/multi-oauth"&gt;pi-chan/multi-oauth&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="全体の流れ"&gt;全体の流れ&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;gemを追加&lt;/li&gt;
&lt;li&gt;omniauthの設定ファイルを作る&lt;/li&gt;
&lt;li&gt;Modelを作る&lt;/li&gt;
&lt;li&gt;Controllerを作る&lt;/li&gt;
&lt;li&gt;Viewを作る&lt;/li&gt;
&lt;li&gt;ブラウザで確認！&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="gemを追加する"&gt;gemを追加する&lt;/h3&gt;
&lt;p&gt;Gemfileに必要なGemを追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Gemfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;devise&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;omniauth&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;omniauth-hatena&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;omniauth-github&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;omniauth-twitter&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;figaro&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;haml&lt;span style="color:#f92672"&gt;-&lt;/span&gt;rails&lt;span style="color:#960050;background-color:#1e0010"&gt;’&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ユーザー認証のためのDeviseとOAuth連携のためのomniauth各種は当然。ConsumerKey等を隠すためのfigaroとHamlを入れています。&lt;/p&gt;
&lt;p&gt;今回はTwitter、Github、はてなとの連携をしてみました。&lt;/p&gt;
&lt;h3 id="omniauthの設定ファイルを作る"&gt;omniauthの設定ファイルを作る&lt;/h3&gt;
&lt;p&gt;omniauth用の設定ファイルでConsumerKey等を指定してあげます。Keyはそれぞれ以下のリンクから発行可能。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.twitter.com/apps/"&gt;twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/settings/applications"&gt;github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.hatena.ne.jp/"&gt;hatena&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# config/initializers/omniauth.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;.&lt;/span&gt;config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;middleware&lt;span style="color:#f92672"&gt;.&lt;/span&gt;use &lt;span style="color:#66d9ef"&gt;OmniAuth&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Builder&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; provider &lt;span style="color:#e6db74"&gt;:hatena&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;HATENA_CONSUMER_KEY&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;HATENA_CONSUMER_SECRET&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;scope&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;write_public,read_public,write_private,read_private&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; provider &lt;span style="color:#e6db74"&gt;:twitter&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;TWITTER_CONSUMER_KEY&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;TWITTER_CONSUMER_SECRET&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; provider &lt;span style="color:#e6db74"&gt;:github&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;GITHUB_CONSUMER_KEY&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;GITHUB_CONSUMER_SECRET&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Figaroを使っているので、KeyやSecretは&lt;code&gt;config/application.yml&lt;/code&gt;に書きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# config/application.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;development&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;HATENA_CONSUMER_KEY&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;YOUR_HATENA_KEY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;HATENA_CONSUMER_SECRET&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;YOUR_HATENA_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;TWITTER_CONSUMER_KEY&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;YOUR_TWITTER_KEY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;TWITTER_CONSUMER_SECRET&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;YOUR_TWITTER_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;GITHUB_CONSUMER_KEY&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;YOUR_GITHUB_KEY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;GITHUB_CONSUMER_SECRET&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;YOUR_GITHUB_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="modelを作る"&gt;Modelを作る&lt;/h3&gt;
&lt;p&gt;続いて、ユーザーモデルと認証モデルを作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ rails g devise:install
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ rails g devise User &lt;span style="color:#75715e"&gt;# ←コメントで指摘をいただいたので修正しました&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ rails g model Auth uid:string provider:string user_id:integer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ユーザーモデルと認証モデルはこんな感じ。ユーザーモデルは複数のAuthモデルと関連できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# user.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;User&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Include default devise modules. Others available are:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# :confirmable, :lockable, :timeoutable and :omniauthable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; devise &lt;span style="color:#e6db74"&gt;:database_authenticatable&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:registerable&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:confirmable&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;:recoverable&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:rememberable&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:trackable&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:validatable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; has_many &lt;span style="color:#e6db74"&gt;:auths&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# auth.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Auth&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; belongs_to &lt;span style="color:#e6db74"&gt;:user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="controllerを作る"&gt;Controllerを作る&lt;/h3&gt;
&lt;p&gt;ログインなどのリンクを置くためのルートページ用コントローラと、認証を取り扱うコントローラを作っておきましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ rails g controller home index
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ rails g controller auth create destroy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;HomeControllerでユーザーが触るページを作ります。ログイン済みの場合は現在連携中のサービスをArrayで持っておき、あとでViewで使用します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# home_controller.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;HomeController&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ApplicationController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;index&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; user_signed_in?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; @providers &lt;span style="color:#f92672"&gt;=&lt;/span&gt; current_user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;auths&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pluck(&lt;span style="color:#e6db74"&gt;:provider&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;AuthControllerでは認証後のcallback先としての&lt;code&gt;create&lt;/code&gt;と、連携解除のための&lt;code&gt;destroy&lt;/code&gt;メソッドを用意します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# auth_controller.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AuthController&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ApplicationController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; before_filter &lt;span style="color:#e6db74"&gt;:authenticate_user!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;create&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; auth &lt;span style="color:#f92672"&gt;=&lt;/span&gt; request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;env&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;omniauth.auth&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; uid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; auth&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;uid&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; provider &lt;span style="color:#f92672"&gt;=&lt;/span&gt; auth&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;provider&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Auth&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find_by_uid_and_provider(uid,provider)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Auth&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create(&lt;span style="color:#e6db74"&gt;uid&lt;/span&gt;:uid, &lt;span style="color:#e6db74"&gt;provider&lt;/span&gt;:provider, &lt;span style="color:#e6db74"&gt;user_id&lt;/span&gt;:current_user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;id)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; redirect_to root_url
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;destroy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; provider &lt;span style="color:#f92672"&gt;=&lt;/span&gt; params&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:provider&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; auth &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Auth&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find_by_provider_and_user_id(provider,current_user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;id)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; auth&lt;span style="color:#f92672"&gt;.&lt;/span&gt;destroy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; redirect_to root_url
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;create&lt;/code&gt;ではauth_hashから認証オブジェクトを生成しユーザーと関連づけ、&lt;code&gt;destroy&lt;/code&gt;では認証オブジェクトを削除します。&lt;/p&gt;
&lt;p&gt;routingの設定も必要なので、&lt;code&gt;config/routes.rb&lt;/code&gt;は次のようにします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# config/routes.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; root &lt;span style="color:#e6db74"&gt;&amp;#34;home#index&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; devise_for &lt;span style="color:#e6db74"&gt;:users&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; get &lt;span style="color:#e6db74"&gt;&amp;#34;/auth/:provider/callback&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;auth#create&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; delete &lt;span style="color:#e6db74"&gt;&amp;#34;/auth/destroy/:provider&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;auth#destroy&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;as&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:destroy_connection&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="viewを作る"&gt;Viewを作る&lt;/h3&gt;
&lt;p&gt;最後にViewを作ります。&lt;/p&gt;
&lt;p&gt;ログインしていない場合はログインリンクとサインアップリンクを、ログイン済みの場合は各種サービスとの連携/連携解除リンクとログアウトボタンを表示します。&lt;/p&gt;
&lt;p&gt;さきほど&lt;code&gt;home#index&lt;/code&gt;で取っておいた&lt;code&gt;@provider&lt;/code&gt;はここで使っています。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-haml" data-lang="haml"&gt;%h1 multi auth
- if user_signed_in?
%ul
%li= link_to &amp;#34;ログアウト&amp;#34;, destroy_user_session_path, method: :delete
- if @providers.include? &amp;#34;twitter&amp;#34;
%li
twitterと接続済み
= link_to &amp;#34;接続解除&amp;#34;, destroy_connection_path(:twitter), method: :delete, data:{confirm:&amp;#34;Sure？&amp;#34;}
- else
%li= link_to &amp;#34;twitterと接続&amp;#34;, &amp;#34;/auth/twitter&amp;#34;
- if @providers.include? &amp;#34;github&amp;#34;
%li
githubと接続済み
= link_to &amp;#34;接続解除&amp;#34;, destroy_connection_path(:github), method: :delete, data:{confirm:&amp;#34;Sure？&amp;#34;}
- else
%li= link_to &amp;#34;githubと接続&amp;#34;, &amp;#34;/auth/github&amp;#34;
- if @providers.include? &amp;#34;hatena&amp;#34;
%li
hatenaと接続済み
= link_to &amp;#34;接続解除&amp;#34;, destroy_connection_path(:hatena), method: :delete, data:{confirm:&amp;#34;Sure？&amp;#34;}
- else
%li= link_to &amp;#34;hatenaと接続&amp;#34;, &amp;#34;/auth/hatena&amp;#34;
- else
%ul
%li= link_to &amp;#34;ログイン&amp;#34;, new_user_session_path
%li= link_to &amp;#34;サインアップ&amp;#34;, new_registration_path(:user)
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="ブラウザで確認"&gt;ブラウザで確認！&lt;/h3&gt;
&lt;p&gt;こんな感じになりました。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/bMDu2mDB9kCveACE3WL-rDBX86uQPP_qMUXfRDwK0f-1_9UaeA0M4tQrXuonpSuyNHXHTgf_HT9D4AOBw7FgvjuvWXVmcfvnI-01qCQ51eGfbpUg2blLhSOTSgEPaMxIV5w6fL9PnoYZa_Z5Y1ZkhGbYIdyfG1rK-vjUDmhyBpRY35_Ki_m8Vt8KlF2XSFDuuy_JJoZUMXJ47gKaOV7-UsV1JcZQt0oW2oVcXsJcDTmYH36jsSlBI-FZuKvEcd_5gvJ5a8sftBHWkE5ZGLvFP7-mfJqk__7-s0kSJwMGr2sWCOMzLlVNlZwoot9QODuHknaSDDcLKe9pv5EAN_5_MWEjAOkIYui7QKQlW8dZ0BzFKV-H4XTtgCwsRk6jDH20c7DO5UFCgZXbLxZD25AFVDH0ByN_hAy27IGahY7scpkBvULjsZ3yH4jX33TumhC6AQPHTLXBgiow7MlSqPBPyVS4HphMoq23CNiWkHvt-ly5zPOeUtBPsfuUEuEjkGGekg4B3oXxAaNhkcxoATT27lU9k51dFT33E9sWPa3s0o9Ptuc9bZdbkn1KbhwEJ5uV2Rw0KonnsLvt7NhNIVTmGcdPiM_k5D7pXj9CtZ69WgSxkkDDaAQEn8bBD3zovqfEsWHM9u7yl8XYGcZ-6uz5XIKAVALqqm_maw=w367-h236-no" alt="multioauth"&gt;&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ&lt;/h2&gt;
&lt;p&gt;今回作ったAuthモデルには認証によって得ることができる情報うち&lt;code&gt;uid&lt;/code&gt;と&lt;code&gt;provider&lt;/code&gt;の2つの情報しか残していませんでしたが、ここにアクセストークンなどをいい感じで置いておくことでサービスのAPIを叩いていろいろな連携を行うことができるようになります。&lt;/p&gt;
&lt;h3 id="超参考リンク"&gt;超参考リンク&lt;/h3&gt;
&lt;p&gt;id:hirayosさんの&lt;a href="http://tech.hatenadiary.jp/entry/2013/05/01/OmniAuth%E3%81%A7%E8%AA%8D%E8%A8%BC%E6%A9%9F%E8%83%BD%E3%82%92%E4%BD%9C%E3%82%8B"&gt;OmniAuthで認証機能を作る - RuntimeError&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Gitで追跡されていないファイルを消したりignoreしたり</title><link>https://blog.piyo.tech/posts/2013-12-19-205305/</link><pubDate>Thu, 19 Dec 2013 20:53:06 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-19-205305/</guid><description>&lt;p&gt;&lt;img src="https://www.evernote.com/shard/s15/sh/bfccc276-61cc-4a0f-b8e8-d6baf8e68eab/6c8f6623f08c718ffa4ab78aa019bc58/deep/0/20130910082500.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Gitを使い始めてから使っている俺々スクリプトの紹介。Gitで管理したくないファイルを消したり.gitignoreに追加したりを簡単にするスクリプトです。&lt;/p&gt;
&lt;h2 id="git-status--s"&gt;git status -s&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;$ git status&lt;/code&gt;の出力って色々うるさくないですか？あれがすげー見づらいので僕は&lt;code&gt;$ git status -s&lt;/code&gt;を使っています。&lt;/p&gt;
&lt;p&gt;もっと言うとglobalな.gitconfigにエイリアスを書いてあるのでこんな風に使えるようにしています。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ git s&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;おまけ&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-conf" data-lang="conf"&gt;# ~/.gitconfig
[alias]
co = checkout
s = status -s --branch
br = branch
di = diff
d = diff
dc = diff --cached
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="追跡されていないファイルを無視指定する"&gt;追跡されていないファイルを無視指定する&lt;/h2&gt;
&lt;p&gt;ローカルで自動生成されたファイルを無視したりしたいときありますよね。手動で書くのは面倒なので、&lt;code&gt;$ git s&lt;/code&gt;の出力から&lt;code&gt;?? &lt;/code&gt;なものだけを抽出するスクリプトを噛ませて使うと便利です。&lt;/p&gt;
&lt;p&gt;このスクリプトをパスが通ったところに置きます。sedとか使えばスクリプトを使う必要もないしシェルスクリプトでも全然できるんですが、楽なのでRubyで書きました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;git-untrack-files.rb&lt;/strong&gt;&lt;/p&gt;
&lt;script src="https://gist.github.com/pi-chan/7938591.js"&gt;&lt;/script&gt;
&lt;p&gt;例えばこんな状況化だとします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ git s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;M Hoge
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;A HogeHoge
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; M HogeHogeHoge
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;?? Piyo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;?? PiyoPiyo/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;さっきのスクリプトを通すとこう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ git s | git-untrack-files.rb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;Piyo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;PiyoPiyo/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;で、こうしましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ git s | git-untrack-files.rb &amp;gt;&amp;gt; .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="追跡されていないファイルを削除する"&gt;追跡されていないファイルを削除する&lt;/h2&gt;
&lt;p&gt;さっきのスクリプトを使ってもできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ git s | git-untrack-files.rb | xargs rm -rf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;が、それも面倒だったので専用スクリプト書きました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;git-remove-untrack.rb&lt;/strong&gt;&lt;/p&gt;
&lt;script src="https://gist.github.com/pi-chan/7938583.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ git s | git-remove-untrack.rb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>resque-schedulerで予約済みのJobを複数削除</title><link>https://blog.piyo.tech/posts/2013-12-18-212105/</link><pubDate>Wed, 18 Dec 2013 21:21:08 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-18-212105/</guid><description>&lt;p&gt;公開されているresque-schedulerで条件に該当するジョブをまとめて削除する方法が見当たらなかったのでハックしたという話です。&lt;/p&gt;
&lt;p&gt;resque-schedulerはバックグラウンド用gemであるResqueをさらに拡張したもので、cronのような定期的な動作をさせたり、特定の時刻に動作をさせたりするためのgemです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/resque/resque-scheduler"&gt;resque/resque-scheduler&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;resque-schedulerのジョブを削除するために少し手をいれる必要があったのでそれについて書き残しておきます。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;i&gt;なお、この記事に書いてある内容はresque-scheduler 2.3.1時点のものであり、これ以降のバージョンでは以下に記す内容は必要なくなっている可能性があります。&lt;/i&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="resqueのジョブ"&gt;Resqueのジョブ&lt;/h2&gt;
&lt;p&gt;まずResqueの概要ですが、Resqueでバックグラウンドジョブを登録するときはジョブを処理するクラスの名前と任意のパラメータを渡します。たとえば&lt;code&gt;JobHandler&lt;/code&gt;というジョブを処理するクラスがあって、パラメータを2つ受け取るとすると、クラス定義とジョブの登録はそれぞれ次のようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# job handler class&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;JobHandler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;perform&lt;/span&gt;(hoge_id,piyo_id)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# do something in background...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# enqueue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;hoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; hoge &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Hoge&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where( &lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; piyo &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Piyo&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where( &lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Resque&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;enqueue(&lt;span style="color:#66d9ef"&gt;JobHandler&lt;/span&gt;, hoge&lt;span style="color:#f92672"&gt;.&lt;/span&gt;id, piyo&lt;span style="color:#f92672"&gt;.&lt;/span&gt;id)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際の動作はというと、まず&lt;code&gt;Resque.enqueue&lt;/code&gt;では渡されたクラス名やパラメータを&lt;code&gt;Resque.encode&lt;/code&gt;メソッドにより1つの文字列化したものをRedisに入れます。そうするとバックグラウンドで動いているプロセスがRedis内のデータを参照し、処理する必要があるジョブの文字列を&lt;code&gt;Resque.decode&lt;/code&gt;メソッドでクラス名とパラメータに分解し直します。そして、そのクラスの&lt;code&gt;perform&lt;/code&gt;メソッドにパラメータを渡して実行するという流れになっています。&lt;/p&gt;
&lt;p&gt;resque-schedulerも基本的には同じですが、時間を指定できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Resque&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;enqueue_at(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;day&lt;span style="color:#f92672"&gt;.&lt;/span&gt;from_now, &lt;span style="color:#66d9ef"&gt;JobHandler&lt;/span&gt;, hoge&lt;span style="color:#f92672"&gt;.&lt;/span&gt;id, piyo&lt;span style="color:#f92672"&gt;.&lt;/span&gt;id)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="スケジュールされたジョブを取りやめたい場合"&gt;スケジュールされたジョブを取りやめたい場合&lt;/h2&gt;
&lt;p&gt;resque-schedulerには&lt;code&gt;Resque.enqueue_at&lt;/code&gt;の時間指定以外の引数を与えることができる&lt;code&gt;Resque.remove_delayed&lt;/code&gt;というメソッドがあります。このメソッドを使って指定したジョブを削除できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Resque&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;enqueue_at(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;day&lt;span style="color:#f92672"&gt;.&lt;/span&gt;from_now, &lt;span style="color:#66d9ef"&gt;JobHandler&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Rescue&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;remove_delayed(&lt;span style="color:#66d9ef"&gt;JobHandler&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こんな風にして、ジョブの追加や削除が可能です。&lt;/p&gt;
&lt;p&gt;では、条件に該当する複数のジョブを一気に削除したいときはどうすればいいのでしょう。上の例で言えば、&lt;code&gt;hoge_id=5&lt;/code&gt;となる全てのジョブを削除したい、というような場合です。&lt;/p&gt;
&lt;p&gt;実は2013年12月17日現在gemとしてリリースされているresque-schedulerの最新バージョン(2.3.1)にはそのためのメソッドが定義されていません。実はgithubのコードにはそのためのメソッドが新しく実装されているので、Gemfileでgithubリポジトリを参照するようにしてもよかったのですが、githubのバージョンではResqueのWeb UIに不具合があって困るので僕は使えないと判断しました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/resque/resque-scheduler/blob/master/lib/resque_scheduler.rb#L291"&gt;githubの該当箇所&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;先ほど紹介したようにResqueのジョブは少しばかりencodeされていて非常に取り回しづらい上、Redisを直に叩くとなるとさらにコードが煩雑になりかねません。そこで、githubリポジトリで導入されている、条件に当てはまるジョブを削除するためのメソッドだけを取り込むことにしました。&lt;/p&gt;
&lt;p&gt;ここでは、resque-schedulerがそうしているように、Resqueをextendする形で拡張します。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;config/initializers/resque_init.rb&lt;/code&gt;あたりのresque用ファイルに次のコードを追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;module&lt;/span&gt; ResqueSchedulerExt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# this methods is not implemented in current version (2.3.1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;remove_delayed_selection&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; fail &lt;span style="color:#66d9ef"&gt;ArgumentError&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Please supply a block&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;unless&lt;/span&gt; block_given?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; destroyed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# There is no way to search Redis list entries for a partial match, so we query for all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# delayed job tasks and do our matching after decoding the payload data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; jobs &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Resque&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;redis&lt;span style="color:#f92672"&gt;.&lt;/span&gt;keys(&lt;span style="color:#e6db74"&gt;&amp;#34;delayed:*&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; jobs&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;job&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; index &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Resque&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;redis&lt;span style="color:#f92672"&gt;.&lt;/span&gt;llen(job) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; index &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; payload &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Resque&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;redis&lt;span style="color:#f92672"&gt;.&lt;/span&gt;lindex(job, index)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; decoded_payload &lt;span style="color:#f92672"&gt;=&lt;/span&gt; decode(payload)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;yield&lt;/span&gt;(decoded_payload&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;args&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; removed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; redis&lt;span style="color:#f92672"&gt;.&lt;/span&gt;lrem job, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, payload
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; destroyed &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; removed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; index &lt;span style="color:#f92672"&gt;-=&lt;/span&gt; removed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; index &lt;span style="color:#f92672"&gt;-=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; destroyed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Resque&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;extend &lt;span style="color:#66d9ef"&gt;ResqueSchedulerExt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで&lt;code&gt;Resque.remove_delayed_selection&lt;/code&gt;というメソッドを使えるようになりました。&lt;/p&gt;
&lt;p&gt;あとは、必要な箇所でこのメソッドを呼び出すだけでOKです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Resque&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;remove_delayed_selection &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;args&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#75715e"&gt;# args is [hoge_id, piyo_id]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; args&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで&lt;code&gt;hoge_id=5&lt;/code&gt;であるジョブを全て削除できました。&lt;/p&gt;</description></item><item><title>md2review+ReVIEW+guard+livereloadで快適ドキュメントライティング</title><link>https://blog.piyo.tech/posts/2013-12-17-202105/</link><pubDate>Tue, 17 Dec 2013 20:21:08 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-17-202105/</guid><description>&lt;p&gt;先日はてなで見かけたこちらの記事みて自分なりにやってみたいことがでてきたのでそれについてメモってみます。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://d.hatena.ne.jp/dkfj/20131215/1387093204"&gt;Markdown記法+Git+md2review+ReVIEWで原稿・ドキュメント管理 - プログラマになりたい&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[http://d.hatena.ne.jp/dkfj/20131215/1387093204:image:large]&lt;/p&gt;
&lt;p&gt;やりたいことというのはこんな流れです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Markdownでドキュメントを書く&lt;/li&gt;
&lt;li&gt;自動でHTMLに変換しタブをリロード&lt;/li&gt;
&lt;li&gt;PDFに清書（？）する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;先の記事の方は手動で変換をかけているようですが、僕はそこを自動化してみようと思います。&lt;/p&gt;
&lt;h2 id="pandocについて"&gt;pandocについて&lt;/h2&gt;
&lt;p&gt;そもそも僕は上のようなドキュメントライティングプロセスをpandocを用いて行っていました。それがこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/Pandoc-Guard"&gt;pi-chan/Pandoc-Guard&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PandocはMS Wordのドキュメントを生成できるのであるとき仕事で使ったことがありますが、見た目が超見づらいです。正直使い物にはなりませんでした。ですが、Markdownで書いてHTMLで読めるというところはとても良いです。&lt;/p&gt;
&lt;p&gt;今回はReVIEWというものがどの程度使えるかを知ってみようと思います。&lt;/p&gt;
&lt;h2 id="登場するソフトウェア"&gt;登場するソフトウェア&lt;/h2&gt;
&lt;h3 id="guard"&gt;Guard&lt;/h3&gt;
&lt;p&gt;ファイルの変更を監視して、変更があったら何かするといった自動化をサポートするRubyのソフトウェア。&lt;/p&gt;
&lt;h3 id="livereload"&gt;LiveReload&lt;/h3&gt;
&lt;p&gt;ブラウザで開いているWebページを自動的に更新するツールで、Guardと連携して特定のファイルが更新されたら特定のタブを更新するといった機能を実現できる。&lt;/p&gt;
&lt;h3 id="md2review"&gt;md2review&lt;/h3&gt;
&lt;p&gt;Markdown形式で書かれたテキストファイルをReVIEW形式に変換するRubyプログラム。&lt;/p&gt;
&lt;h3 id="review"&gt;ReVIEW&lt;/h3&gt;
&lt;p&gt;ReVIEW用のフォーマットからHTMLやTeX、PDFなど様々なフォーマットに変換可能な電子書籍向けフォーマットとそのプログラム群。&lt;/p&gt;
&lt;h2 id="サンプル環境"&gt;サンプル環境&lt;/h2&gt;
&lt;p&gt;（おそらく）簡単に導入できるであろう環境を作ってみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/review-livereload"&gt;pi-chan/review-livereload&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="guardでmdとhtmlを監視する"&gt;Guardで*.mdと*.htmlを監視する&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Guardfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;guard &lt;span style="color:#e6db74"&gt;&amp;#39;shell&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; watch(&lt;span style="color:#e6db74"&gt;/.*markdown\/(.*)\.md$/&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;m&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;`./bin/md2review &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;m&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &amp;gt; review/&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;m&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.re`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Dir&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;chdir(&lt;span style="color:#e6db74"&gt;&amp;#34;./review&amp;#34;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;`../bin/review-compile --target=html &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;m&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.re &amp;gt; ../html/&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;m&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.html`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#34;built &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;m&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.html&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;guard &lt;span style="color:#e6db74"&gt;&amp;#39;livereload&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:apply_js_live&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; watch(&lt;span style="color:#e6db74"&gt;%r{html/.+\.(html)}&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;markdown/&lt;/code&gt; 以下の&lt;code&gt;*.md&lt;/code&gt;ファイルを監視して、変更があったら&lt;code&gt;md2review&lt;/code&gt;コマンドでReVIEW形式に一旦変換します。その後&lt;code&gt;review-compile&lt;/code&gt;コマンドでHTMLファイルを生成します。&lt;/p&gt;
&lt;p&gt;2番めのwatch文では&lt;code&gt;html&lt;/code&gt;ディレクトリ以下のhtmlファイルを監視しており、htmlに変更があった場合にそのファイルを開いているブラウザタブを更新しにいきます。つまり、Markdown形式のファイルを更新するとブラウザが勝手にリロードして確認できるというわけです。&lt;/p&gt;
&lt;h2 id="スタティックファイルをサーブするwebサーバーを起動する"&gt;スタティックファイルをサーブするWebサーバーを起動する&lt;/h2&gt;
&lt;p&gt;ローカル用のウェブサーバーなのでRubyで気軽に起動する方法をとりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;bundle exec ruby -run -e httpd -- --port&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5000&lt;/span&gt; ./html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="スタイルシートを指定する"&gt;スタイルシートを指定する&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;review-compile&lt;/code&gt;コマンドではスタイルシートを指定することもできます。これをやらないと見た目がプレーンすぎて味気なく、テンションがあがりません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;review-compile --target&lt;span style="color:#f92672"&gt;=&lt;/span&gt;html --stylesheet&lt;span style="color:#f92672"&gt;=&lt;/span&gt;style.css input.re &amp;gt; output.html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このように書くと生成されるhtmlファイルにstyleタグが生成されます。相対パスで書かれるのでウェブサーバーやhtmlファイルのパスに注意が必要です。&lt;/p&gt;
&lt;h2 id="章立て"&gt;章立て&lt;/h2&gt;
&lt;p&gt;記事を書きながら使っていて気がついたのですが、複数ファイルあると複数の章立てになるんですね！これはうまく使うとすごく便利？だけど、1ファイルごとに独立させたい場合はちょっと不便なのかも。&lt;/p&gt;
&lt;h2 id="pandocとの比較"&gt;pandocとの比較&lt;/h2&gt;
&lt;p&gt;様々な入出力に対応しているという点ではpandocのほうが優秀かも。だけど、ReVIEWが標榜しているように書籍などの長めの文章を書く際はReVIEWのほうがいいのかな。&lt;/p&gt;
&lt;p&gt;今回はReVIEWを使い倒すというわけではなく、ReVIEWをカジュアルに使ってmarkdownでドキュメントを書いてみようという話でした。&lt;/p&gt;</description></item><item><title>忘れがちなXcodeの環境変数はコマンドで一覧できる</title><link>https://blog.piyo.tech/posts/2013-12-16-212804/</link><pubDate>Mon, 16 Dec 2013 21:27:51 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-16-212804/</guid><description>&lt;p&gt;XcodeでHeader Search PathやLibrary Search Pathを設定するときには環境変数を使ってマシンや人ごとの差を吸収すべきなんですが、環境変数名が覚えにくいので何度も調べる羽目になります。&lt;/p&gt;
&lt;p&gt;そんなとき便利なので、xcodebuildコマンドを使って環境変数一覧を表示させてしまう方法です。これを使うと全てを一覧できるので、あとは適当に使えそうなものを探すだけです。&lt;/p&gt;
&lt;p&gt;というか、300行ぐらい出力されるので、こんなにあったのって感じで驚きますね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ xcodebuild -project MyApp.xcodeproj -target &lt;span style="color:#e6db74"&gt;&amp;#34;MyApp&amp;#34;&lt;/span&gt; -showBuildSettings
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドを覚えておくのもしんどいのでシェルの関数として定義してしまうと楽です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# .bashrc または .bash_profile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;xcodeenv&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; xcodebuild -project $1 -target &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$2&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; -showBuildSettings
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この関数にxcodeprojファイルとターゲット名を引数として渡します。こんな感じで、&lt;code&gt;$ xcodeenv MyApp.xcodeproj MyTarget&lt;/code&gt;などとやればいいですね。&lt;/p&gt;
&lt;h2 id="よく使うけどすぐ忘れる環境変数"&gt;よく使うけどすぐ忘れる環境変数&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;$(PROJECT_DIR)&lt;/code&gt; → プロジェクトファイルがあるディレクトリ&lt;/p&gt;</description></item><item><title>iOS用UIテストフレームワークKIFで色々な要素をタップさせる方法</title><link>https://blog.piyo.tech/posts/2013-12-15-214107/</link><pubDate>Sun, 15 Dec 2013 21:40:57 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-15-214107/</guid><description>&lt;p&gt;この間のポストでKIFでフレームワークの導入方法と簡単な使い方について書いたけど、そこからさらに使ってみてもうちょっと使い方がわかったのでそれを書いてみます。&lt;/p&gt;
&lt;p&gt;その前に先日の記事。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-12-11-070003"&gt;XCode5対応！KIFでiPhoneアプリの受け入れ（統合）テスト - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[https://blog.piyo.tech/posts/2013-12-11-070003:image:large]&lt;/p&gt;
&lt;h2 id="accessibilitylabelは必ずしも必要ではない"&gt;AccessibilityLabelは必ずしも必要ではない&lt;/h2&gt;
&lt;p&gt;先日の記事で、テストでタップしたり有無を確認したりするためのUI要素にはAccessibilityLabelを設定する必要があると書きましたが、どうやらそうではないようです。というか、Storyboard上でAccessibilityLabelを設定できない要素もたくさんあります。&lt;/p&gt;
&lt;h3 id="accessibilitylabelが必要なケース"&gt;AccessibilityLabelが必要なケース&lt;/h3&gt;
&lt;p&gt;いくつか確認した中では&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UILabel&lt;/li&gt;
&lt;li&gt;UIButton&lt;/li&gt;
&lt;li&gt;UITextField&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などの要素はAccessibilityLabelの設定が必要でした。察するに開発者が配置する要素にはAccessibilityLabelが必要なのだと思われます。&lt;/p&gt;
&lt;h3 id="accessibilitylabelが要らないケース"&gt;AccessibilityLabelが要らないケース&lt;/h3&gt;
&lt;p&gt;storyboardでAccessibilityLabelを設定できない要素もたくさんあります。たとえばTabBarControllerのTabBarItemや、NavigationControllerにEmbedしたViewControllerのタイトル、UIAlertViewのボタンなどもそれにあたります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;タブ&lt;/li&gt;
&lt;li&gt;Navigationの戻るボタン&lt;/li&gt;
&lt;li&gt;UIAlertViewのボタン&lt;/li&gt;
&lt;li&gt;UIActionSheetのボタン&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などなど。他にもあると思いますが確認できたのはこのあたりです。要素によってはソースコードからAccessibilityLabelを設定できる風にみえることもありますが、KIFフレームワークから使うことはできませんでした（そんなAccessibilityLabelを持った要素はない、という例外が飛ぶ）。&lt;/p&gt;
&lt;p&gt;こういった要素をタップさせるまとまった情報がなく困っていましたが、すごく単純な解決法がありました。それは、&lt;strong&gt;要素のテキストがAccessibilityLabelになっている&lt;/strong&gt;ということを利用します。つまり、KIFのに渡すAccessibilityLabelとして表示されているままのテキストを渡してあげればいいらしいです。&lt;/p&gt;
&lt;p&gt;お気に入りタブをタップさせたいなら&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;[tester tapViewWithAccessibilityLabel:&lt;span style="color:#e6db74"&gt;@&amp;#34;お気に入り&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とやれば良いです。日本語もいけます。&lt;/p&gt;
&lt;p&gt;同様にUIActionSheetを使ってユーザーに選択肢を与えたい場合も、次のようなやり方でタップさせることが可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;[tester tapViewWithAccessibilityLabel:&lt;span style="color:#e6db74"&gt;@&amp;#34;選択肢1&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;[tester tapViewWithAccessibilityLabel:&lt;span style="color:#e6db74"&gt;@&amp;#34;Do something&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="実例"&gt;実例！&lt;/h2&gt;
&lt;p&gt;ソースはGitHubにおいてあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/KIFExample"&gt;&lt;img src="https://capture.heartrails.com/200x150/shadow/border?https://github.com/pi-chan/KIFExample" alt=""&gt;&lt;/a&gt;
&lt;a href="https://github.com/pi-chan/KIFExample"&gt;https://github.com/pi-chan/KIFExample&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;前のサンプルを進化させてこんな遷移を持たせました。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/-_nfX4Ey5xnUmOqYM2ZlOvOvUUrIEYD8EBmEA5B7lkdpyc9qKvq9qHmlPJ7xHNmZLOzSpDAkryegqxEINq3RG2DhRi73yAoRu6z0xc8mcscAQulY9ir7xJODJ9HhW6ZGPHj-XXqo8XKQgrRfBWK7aV1n_x4tw4pi1UBje8jVxnilub4PRIu7ZgDqGhYfLOfdDJ9Md8kGmkoeDsLwhEBuk2UCYgvZG1A8x84zJMJX2ERFZlXo-4ND3UhknrO-5NpgFFeVNWQM7ySgcj2QgX94J4v5lmhZb-tNcNJHZ0AbnsFwgGcvaI5XdonAz269e7VSq-wllYbNiiog5sUpHASiQWvFlHSPz5RoDFMFnD6-EwDyuBHgVwYGIzituUCYlFfhfM02JJjevxX24E9SJ1TSYxMn5AiyMdZQeMOxkvcyOwHo6o43nuRoPTPziGi8o94f6SpLKif5HM_uo0m4kaH7ntHwke3fbkWR3lVtenOFgtybB1h_5rGW0gAKiO1zM552U2XiSv9P5bZPX65iMsIxefyKIBxPpyn40Rdo7RXEL144FjCtvw3VpoHP4AZ8U4C-coD8Zo-xZ7LbkWWEfzIDHXEq1Sdwqu-JDZe4YB9VVyEQizYX-HW9w6WfF6YAsdmuuqaeE3k0XL47HOQ6KcVagGe1eL-IKalPxw=w961-h705-no" alt="画面遷移"&gt;&lt;/p&gt;
&lt;p&gt;この遷移をテストするために2つのテストメソッドを用意し、いろいろ詰め込んでみました。この内容でどちらもパスします。&lt;/p&gt;
&lt;script src="https://gist.github.com/pi-chan/7929375.js"&gt;&lt;/script&gt;</description></item><item><title>railsのサブコマンドが使えなくなる問題の原因はbinstubs</title><link>https://blog.piyo.tech/posts/2013-12-14-203805/</link><pubDate>Sat, 14 Dec 2013 20:38:05 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-14-203805/</guid><description>&lt;p&gt;半年ほど前ですがアプリケーションをデプロイした先でコンソールを起動できない問題に遭遇しました。よくわからなかったのでQA＠ITで質問を投げたのですが、結局解決には至らず。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qa.atmarkit.co.jp/q/2925"&gt;AWSにデプロイしたRailsアプリケーションのコンソールを起動したいがUsageが出てしまう - QA@IT&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;その代わり同じような機能を実現するスクリプトを書いて回避したというところで僕としてはこの問題をスルーしていました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-08-28-100000"&gt;デプロイ先のサーバーでrails consoleできないときの対応とCapistranoからの使い方 - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;その原因が今更ながらわかったのでメモしておきます。&lt;/p&gt;
&lt;h2 id="rails4以降binstubsで起こる問題"&gt;Rails4以降+binstubsで起こる問題&lt;/h2&gt;
&lt;p&gt;bundlerにbinstubsという機能があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ bundle install --binstubs
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とやると、実行ファイル系のgemを実行するのに便利なスクリプトを&lt;code&gt;./bin&lt;/code&gt;に生成してくれます。&lt;code&gt;$ bundle exec cap ...&lt;/code&gt;などと実行していたところを&lt;code&gt;$ ./bin/cap&lt;/code&gt;とタイプするだけでいける、みたいな。&lt;/p&gt;
&lt;p&gt;ところがこの&lt;code&gt;--binstubs&lt;/code&gt;オプションがRails4が予め用意しているファイルを上書きしてしまいます。試しにRails4のアプリケーションを作って確認してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ rails new sample -T --skip-bundle
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ cd sample/bin
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;bundle rails rake
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このように3つのファイルが最初から用意されています。この状況で&lt;code&gt;bundle install --binstubs&lt;/code&gt;を実行すると&lt;code&gt;rails&lt;/code&gt;と&lt;code&gt;rake&lt;/code&gt;がbundlerが生成したものに上書きされてしまい&lt;code&gt;rails&lt;/code&gt;コマンドが正しく動かないという状況が生まれるようです。&lt;/p&gt;
&lt;p&gt;元々あるものとbundlerが生成したものの違いはコードを読めばわかると思いますがまだ読んでません。。。&lt;/p&gt;
&lt;p&gt;最近ではbinstubsが上書きされている場合に警告メッセージを出る機能が追加されたようです。新しいめのRails4を使用している人は気づくのかも。僕んときはベータ版だったのでそんなのなかったよ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/rails/rails/pull/9843"&gt;Rails 4 prints help for &amp;ldquo;rails new&amp;rdquo; when running &amp;ldquo;rails console&amp;rdquo; by indirect · Pull Request #9843 · rails/rails&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="なぜデプロイ先のサーバーで使えなかったか"&gt;なぜデプロイ先のサーバーで使えなかったか&lt;/h2&gt;
&lt;p&gt;僕はローカルではbinstubsを使っていなかったので、上記の問題はアプリケーションをデプロイしたときにのみ遭遇しました。原因がなかなかわからなかったのは、デプロイをCapistranoに任せていた上、デプロイ用設定ファイルの書き方をいろいろな記事からつまみ食いしたせいで、自分でもよくわかったいなかったからです。&lt;/p&gt;
&lt;p&gt;さっきよく見たらこんな風に書いてありました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# config/deploy.rb for Capistrano 2.15.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Bundler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;bundler/capistrano&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;set &lt;span style="color:#e6db74"&gt;:bundle_flags&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;--deployment --binstubs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;--binstubs&lt;/code&gt;指定してる(´・ω・｀)&lt;/p&gt;
&lt;p&gt;特に必要なわけではないので&lt;code&gt;--binstubs&lt;/code&gt;を外したらうまくいきました。&lt;/p&gt;
&lt;h2 id="binstubsを使いたいときの回避策"&gt;binstubsを使いたいときの回避策&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ bundle install --binstubs&lt;span style="color:#f92672"&gt;=&lt;/span&gt;.bin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このように&lt;code&gt;--binstubs=ディレクトリ&lt;/code&gt;とすると&lt;code&gt;./bin&lt;/code&gt;を上書きしなくて済みます。&lt;/p&gt;</description></item><item><title>【失敗】iOSの統合テストフレームワークSubliminal</title><link>https://blog.piyo.tech/posts/2013-12-13-070008/</link><pubDate>Fri, 13 Dec 2013 06:59:58 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-13-070008/</guid><description>&lt;p&gt;先日のKIFの記事に続いてSubliminalというフレームワークを試そうと思ったのですが、GithubのREADMEにしたがって1時間ぐらい格闘しても動かすところまでいけませんでした。&lt;/p&gt;
&lt;div class="embed-card my-4 border border-gray-300 overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://github.com/inkling/Subliminal" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;img src="https://opengraph.githubassets.com/637944bb1f52c50f992e8b6c1795de4b99aa417c0713df42c2228a6313555839/inkling/Subliminal" alt="" class="flex-shrink-0 w-32 h-32 object-cover" loading="lazy"&gt;
&lt;div class="flex-1 py-4 px-4 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-1 truncate"&gt;GitHub - inkling/Subliminal: An understated approach to iOS integration testing.&lt;/div&gt;
&lt;div class="text-xs text-gray-600 mb-2 truncate"&gt;An understated approach to iOS integration testing. - inkling/Subliminal&lt;/div&gt;
&lt;div class="flex flex-row items-center text-xs text-gray-500"&gt;
&lt;img src="https://github.githubassets.com/favicons/favicon.svg" alt="" class="w-4 h-4 mr-1" loading="lazy"&gt;
&lt;span class="truncate"&gt;github.com&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/inkling/Subliminal"&gt;https://github.com/inkling/Subliminal&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;CocoaPodsに対応していないので最初に動かすまでのセットアップに苦労しそうです。実際そこで躓いたわけなので。&lt;/p&gt;
&lt;p&gt;サンプルを眺めた感じではKIFと同じく&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AccessibilityLabelを使う&lt;/li&gt;
&lt;li&gt;Xcodeからコマンドキー＋Uで実行できる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;といった特徴がありそうです。
CocoaPods対応に期待。&lt;/p&gt;</description></item><item><title>slideshareをPDFダウンロードするRubyスクリプト&amp;Webアプリ</title><link>https://blog.piyo.tech/posts/2013-12-12-071507/</link><pubDate>Thu, 12 Dec 2013 07:15:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-12-071507/</guid><description>&lt;p&gt;slideshareのスライドをPDFでダウンロードしてEvernoteに入れてあとで閲覧する、っていうフローで読むことがあります。ところが、たまにSAVEできないスライドがあってそれができなくて困ったりします。&lt;/p&gt;
&lt;p&gt;そういう場合は諦めてWebで読めば問題ないと言えば問題ないのですが、Evernoteに突っ込めないっていうのが気持ち悪いと感じてしまいます。
かといって1スライドごとにスクリーンショットを撮ってスライド化するのもバカみたいだし。&lt;/p&gt;
&lt;p&gt;幸い僕はプログラマーなのでslideshareのスライドをPDF化するスクリプトを作り、さらにSinatraでWebアプリケーション化しました。&lt;/p&gt;
&lt;p&gt;※規約を読んで問題ないんじゃないかと判断してこのようなコードを書いていますが、英語の理解力が足りなくてそう思い込んでいる可能性もあるので間違ってたらどうしよう。&lt;/p&gt;
&lt;h2 id="まずはrubyスクリプト"&gt;まずはRubyスクリプト&lt;/h2&gt;
&lt;p&gt;全体像はGistに。
&lt;a href="https://gist.github.com/pi-chan/7891891"&gt;download slideshare slide as PDF&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ざっくり言うと、スライドのURLからスライド1枚ごとの画像のURLを抽出して保存。それをprawnというgemでPDF化します。&lt;/p&gt;
&lt;p&gt;以下、一部解説します。&lt;/p&gt;
&lt;h2 id="各スライドを画像としてダウンロード"&gt;各スライドを画像としてダウンロード&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 対象のスライド(@nippondanjiさんの偉大なスライドをリスペクト！)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;http://www.slideshare.net/nippondanji/db-engineerstudyanim&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ..略..&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# スライドページのHTMLをパースして、、&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;doc &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Nokogiri&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;HTML&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;parse(html,&lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;,charset)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# スライドの一覧が載っているXMLのURLを作る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;item &lt;span style="color:#f92672"&gt;=&lt;/span&gt; doc&lt;span style="color:#f92672"&gt;.&lt;/span&gt;xpath(&lt;span style="color:#e6db74"&gt;&amp;#39;/html/head/meta[@name=&amp;#34;thumbnail&amp;#34;]&amp;#39;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;first
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;thumbnail_url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; item&lt;span style="color:#f92672"&gt;.&lt;/span&gt;attributes&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;].&lt;/span&gt;value
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;xml_url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; thumbnail_url&lt;span style="color:#f92672"&gt;.&lt;/span&gt;gsub(&lt;span style="color:#e6db74"&gt;/phpapp(\d+)?(.+)$/&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;phpapp\1&amp;#39;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;gsub(&lt;span style="color:#e6db74"&gt;/ss_thumbnails\//&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;.xml&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;xml &lt;span style="color:#f92672"&gt;=&lt;/span&gt; open(xml_url) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;f&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; f&lt;span style="color:#f92672"&gt;.&lt;/span&gt;read
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# XMLをパースしてスライドの枚数をカウント&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;xml_doc &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Nokogiri&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;XML&lt;/span&gt;(xml)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;slide_count &lt;span style="color:#f92672"&gt;=&lt;/span&gt; xml_doc&lt;span style="color:#f92672"&gt;.&lt;/span&gt;xpath(&lt;span style="color:#e6db74"&gt;&amp;#34;/Show/Slide&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;count
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 一時ディレクトリで&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Dir&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;mktmpdir &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;dir&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Dir&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;chdir(dir) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; slide_count&lt;span style="color:#f92672"&gt;.&lt;/span&gt;times &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;i&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 各スライドの画像が置いてあるURLを作成しダウンロード&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;http://image.slidesharecdn.com/&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;slide_name&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/95/slide-&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;i&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;-1024.jpg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#34;downloading &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;path&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; ...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; filename &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;basename(path)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; open(filename, &lt;span style="color:#e6db74"&gt;&amp;#39;wb&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;out&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; open(path) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;data&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; out&lt;span style="color:#f92672"&gt;.&lt;/span&gt;write(data&lt;span style="color:#f92672"&gt;.&lt;/span&gt;read)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ..略..&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="保存した画像をpdfに変換"&gt;保存した画像をPDFに変換&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Dir&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;mktmpdir &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;dir&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Dir&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;chdir(dir) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ..画像をダウンロード..&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ダウンロードした画像名を番号順にして保持&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; images &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Dir&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;glob(&lt;span style="color:#e6db74"&gt;&amp;#34;slide-*.jpg&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; images &lt;span style="color:#f92672"&gt;=&lt;/span&gt; images&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sort_by{&lt;span style="color:#f92672"&gt;|&lt;/span&gt;str&lt;span style="color:#f92672"&gt;|&lt;/span&gt; str&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/\d+/&lt;/span&gt;&lt;span style="color:#f92672"&gt;].&lt;/span&gt;to_i}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#34;generating &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;pdf_file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; ...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# prawnを使ってPDFを生成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Prawn&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Document&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;generate(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; pdf_file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path, &lt;span style="color:#75715e"&gt;# 出力ファイル名&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;page_size&lt;/span&gt;:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;768&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;, &lt;span style="color:#75715e"&gt;# 1枚のサイズは1024x768&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;margin&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; ) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; images&lt;span style="color:#f92672"&gt;.&lt;/span&gt;each &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;img&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# imgというファイルパスを画像としてページに追加、という意味&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; image(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; img,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;fit&lt;/span&gt;:&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;768&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; start_new_page &lt;span style="color:#75715e"&gt;# 新しいページに移る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="webアプリケーション版"&gt;Webアプリケーション版&lt;/h2&gt;
&lt;p&gt;Sinatra on Herokuで超シンプルなアプリケーションを作りました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pi-chan/slideshare-downloader"&gt;pi-chan/slideshare-downloader&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/fkQ_kTnuoDmL_aEo_HsYuU0Cl343e6TG4aah0RSQSnU8Uqh19WzozGDrtv8U4yGJWy0Oz1xec5eGe2xRK6BVNILEsWp7q2wk0s96yWaJwkoY0UdK23d2aL2w6VKnVvz-piZeYQin5v2Y7G1W8PRpVQ7wWxyCyP8xIkxxFW20sXZXG9LvjqQtIVgAwC--XDZNWOKUsNoNxJ-xSv9GAd42ggjo7HXvlHzqP_ltFAaKipG8blkYD0dqAjjZ8t85GhZDAfIiYTw_rdzTYlZ-u2HTtgLpFqZGExnqoxziKVtqgtLcWjo3MYGDcx26XwkI9Tk1c-5MuvbRGtOIEA2xnOYN9aMF0Cvt_w7zYYXR0rnkBy-M9x-ukzV32L3ErsJDCIosOUxvZXyaNDPKFS86Z4ib-1ulvkIgkP_h-CxFzs6QwDfRx7rlQWm0RgvB2iJAMnCP9c92C-_Rh_z3OVG5WDP6V9ea4Yu5BH9Ut7tueX4miGBhr2Kss3vMEgg5r2ugqH8vhA-JP72yvJ0KY3ewk1cKvA1ThLvkeJPNyAJBmnXKfpxOEU5eA7MhE91Dfo19N9yqxjFNyK3ZFQFjQ-zjHy_Vc2ig9D_7xRw1MhIKEEXbdgLkLEdAC6RYaflnYzlfcceoJVVz1XN09TjamCUgu2BB3KUAWaBpt8isug=w456-h182-no" alt="slideshare-downloader"&gt;&lt;/p&gt;
&lt;p&gt;フォームにslideshareの該当スライドのURLを入れてボタンを押すだけ！超カンタンです。動かないパターンがある気がするのでその場合は教えて欲しいです。&lt;/p&gt;</description></item><item><title>XCode5対応！KIFでiPhoneアプリの受け入れ（統合）テスト</title><link>https://blog.piyo.tech/posts/2013-12-11-070003/</link><pubDate>Wed, 11 Dec 2013 06:59:58 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-11-070003/</guid><description>&lt;p&gt;最近初めてiPhoneアプリでテストを書く機会がありました。テストを書くならこの際ユニットテストだけではなく画面遷移を含めたテストも書いてみようと思い、環境を整えてみました。&lt;/p&gt;
&lt;h2 id="テストフレームワークの選択肢"&gt;テストフレームワークの選択肢&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kif-framework/KIF"&gt;kif-framework/KIF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/inkling/Subliminal"&gt;inkling/Subliminal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.testingwithfrank.com/"&gt;Testing With Frank — Painless iOS and Mac Testing With Cucumber&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/allending/Kiwi"&gt;allending/Kiwi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ざっと調べた感じ、受け入れテストに使えるテストフレームワークは以上のような感じ。ですが、FrankやKiwiはCucumberベースで癖がありそうだったり設計思想が大掛かりな感じがして回避しました。この中では一番シンプルなKIFを選択しました。ちなみにKIFは決済サービスsquareで使用されているフレームワークらしいです。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2013/12/12追記：KiwiはUIのテストは想定されてないっぽいです。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="kif環境のセットアップ"&gt;KIF環境のセットアップ&lt;/h2&gt;
&lt;p&gt;セットアップについてはここ（&lt;a href="https://github.com/kif-framework/KIF"&gt;kif-framework/KIF&lt;/a&gt; ）が詳しいけど、一応メモ。&lt;/p&gt;
&lt;h3 id="テスト用のターゲットを追加する"&gt;テスト用のターゲットを追加する&lt;/h3&gt;
&lt;p&gt;XCodeでこうやって&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/W4wmtPaeQMYX3FZTPm3V6CRYab0h6A9S43O9a8plLH49grBo302RyMWL45Coqx9Tq6o6ddIwS9AqZIt5icJLA7z6u1dAQPYDBmKp8zj9TE2qONXPI2EkQMbSQwm6npcrGbHsZnHrAWVDpwDeh18jc-onOFm8GZ1YxBsVh6ivpy87qVlu0gtaXXrng_QooT97CFe-ESVgQ2bzHw9UnYTmQBtaKUrKLP6O5I5vByuwqz7muQ6GbYNElEz27uHUxlSntOLx7etamtypPbspf2dV0bVdbH9j-NYu8KlfKc6N2ZoTOO484LcBEvBVM6KULtu0McoBXahU7vihe9s6GKJzQzCboyAUpBNZ0ZUSOdPA4JJ2zJZB8jetK93eAg0CwupOetWwQ8cpe8wCV8ZCxF4GWK6Gkbhu42Je2Sp4jyKtbmMC4_kh-ZRORxK_k43l82K-bigT2b8AXOwbjWiFSnVnLaXIJQ_Cgpl1cfd10fPquM6SQqM8qXou2pHXjdd7HwjHtJsWJRFDfLiWPMFBiJgOeNWEx-Nw3C_uETfUF7bioYF6OawpWwLSzf4y-WwBVueIIrfmK8kR72e156VIYevQDvSiWhLeBytnFzDVv7vo_9q2DfMrNfHVBdWDBpqQWK_SfoIIZG_zlQ7oswtm_RHlfdMhIuqPE6fwOg=w222-h244-no" alt="ターゲット追加"&gt;&lt;/p&gt;
&lt;p&gt;こうやって&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/qkPhP8fgQ_7KABGEOGpy35G_YyE2CK0wn-HOTufN8hV9rje0jqaTQGvZiuOjGwp3J-p77fFUSd9hsRixew4obRfkSTzskSrmyPRbnJKDq8-LHrTah9YMg6aS5WXv08hgPmD29ZvxZmDLG--hb-4vY0Mug7OVj6Uy-vtT08GbP1V5bst1sFPze8Q8xv5O1r50aDDYixekaUyWHJVw68f3c9Gr_Xjvspmhm9kLnQXUn2JaERZ3NHa66ltk6V4RJq_x1NOSsvH9BXcVUU4atxOwP_n8jpscBb5Xs5yoA9DiatkhEH6g2dvQbmQAvzBgbxVUNkyd7ebQwa98Kug4I-5i8tLaszc8JiAYkz8wZlYPG0bjJWZtd7VIWaqgxzqxbioicEHHIYzls7_xyFXz5DckPOci2MjyYv8ABnOzSSNWBDZ4l4d9fvbi3kBobt4ogV0-FFHnkbCimuYG5I9TOSGqB2hrY77kkC-PgxcBQpfW9FRy-dRtCpSf7NTHM9FHozfSldmG4gIWbtXxizf-WCo8MzO6I_74P8SuS85i-vm4x6Z8SWKRevbmIQVEg3I15U89gvHx75qAXU_vngkIH_gFgHqRnjIqyzzgF6USnm4usyYIfvoG7bwpk-fa2NT-x5o2prA-7P5Dg4NxateVGFhqXI0q3SP8BpsoBw=w423-h129-no" alt="ターゲット追加"&gt;&lt;/p&gt;
&lt;p&gt;ドーン&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/QNMdHTHks3Fnyi29VhUgdO7GN_QOjWcx-ZJrFiibfAeyfjEnSHKzdxOOjGpKnmkdW4Q_srujmvvnllnC96R8JCddcNvKeZgjrHPBYpXn0IG0UX6N_upDXx7ak99VumGR9ohpQD1CX5loNMMrUUMICOGFMCNe72HwgGB2YP_EzNlWlcelyyUFNWif7Ew1kx3MxIabsE253IllqVaQCHZfVT6YyaXPsJ8wzfXAiYmOfsqfBvzaG-MiJayM_Gy1QVl_anUBMr0MEQw8vkvbFGJ1hq5n6ny7PTtUXSapxa8nZSVX6zckQBQzaGOQiRLxpbBCj2ZxqVJRQZZUrtLbDHtprzHrHEhcLfa6bVsmNPrp46iRxyDqdY9mF33ZgP-5O7ME5SjjXpA23cRGBN8hks90KUK4jUIWpbClPmY_tqN5MFOXmIcNDZKQFcwTCG75kx9QfgKSZHAUCypx6QiJa6OzkTgI3eOzyC7WVbo_FqHeTr3H7zeG1VQFYJvzA8-vPOJFumJxng39ihSufgsIiJTc7sjWORADOtWYi8B4fRudXqi7bXdA-BkVjIcjvTqVV_xE-z_w53uJpvt7LwvbqB44ldqfwTr8S5dP0_ieL6rFdOq5nRiRoB8Ru2P7divzDoBRWOzM22x5IJvCMsLJFhdXMiNv1OUwi7-49w=w525-h229-no" alt="ターゲット追加"&gt;&lt;/p&gt;
&lt;p&gt;githubのREADMEでは最後にBuildSettingsをいじりますが、3番の箇所でタイプをOCUnitに変更しておけばその変更も不要になります。&lt;/p&gt;
&lt;h3 id="cocoapodsでインストール"&gt;CocoaPodsでインストール&lt;/h3&gt;
&lt;p&gt;CocoaPodsからインストールする方法とgithubからインストールする方法の両方が紹介されていますが、圧倒的にCocoaPodsを使う方が楽です。&lt;code&gt;CocoaPods インストール&lt;/code&gt;とか検索して、CocoaPodsだけは入れとくべき。&lt;/p&gt;
&lt;p&gt;CocoaPodsが入ったらプロジェクトのルートディレクトリにPodfileを作ります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Podfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# IntegrationTestsの部分は先ほど追加したテストターゲットの名前に置き換える&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;target &lt;span style="color:#e6db74"&gt;&amp;#39;IntegrationTests&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;exclusive&lt;/span&gt;:&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; pod &lt;span style="color:#e6db74"&gt;&amp;#39;KIF&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;~&amp;gt; 2.0&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そしたらCocoaPodsでインストール。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ pod install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="kifを使用した最低限のテスト"&gt;KIFを使用した最低限のテスト&lt;/h2&gt;
&lt;h3 id="画面遷移を作る"&gt;画面遷移を作る&lt;/h3&gt;
&lt;p&gt;最低限のテストコードを書くためにStoryboardを使って画面遷移をちゃちゃっと作っておきます。&lt;/p&gt;
&lt;p&gt;ここが重要なところなのですが、KIFを使う上ではUIの要素が持つAccessibilityLabelに名前をつけておく必要があります。AccessibilityLabelをキーにして、タップさせたり要素の有無を確認したりするので。&lt;/p&gt;
&lt;p&gt;AccessibilityLabelはStoryboard上でUI要素を選択した状態でインスペクタから設定可能です。こんな感じ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/lkFbwAaoxD_begHvwBs9PjFau-LdDaMjufKxgWpj3m0LmEkXcJNkIRyo_DtPJilU5pRrZ7fnlx_yHQdHh8VxxRiHR6W1QWfYmatBpfbVwIEVq-MaKKphNmuChyG4RjcaAlfdo0V0z6jODEWTQ5tYJ2nmImaPyqrxDIBe0MeF9wJrUQdL2ja92sRn6x3Rkj5eMck6KO179-eUdhgn63R-K2AOf6UaXaKKHqTLh-s4rrzO1cpRVxrM_dGLepUyXyMeLrOQIYHQPIDkYA8ZM8kVuiij9kIkuYIhBba_1Uq4myJLm1WA4KG-JIBLb7sSPf59gvOLoNPwTPsdYWe5XA3LMVV-mLioBM8uKryZRW2eaAf-NiQomtBFBGFSS-JyCxmxYtF8831jlKWxUNwYkwnvqvFJNWlTyzZG52RLjMMrnEYmzFNN5EDxJDtUw4Eo90VNGGJ0yMj59YYUlToZe4mKb86KuB_wm35CpgYjpkQtX1Q3FA0fMORQX6GU0uB0QqIhHYaSfYaPggardzOjUtiles9F07PxZRKJvmXYuk7hl-nT7XoOa4MyqP15SfRPspI6GUSlNE1NuBTqqD87kzZPphEVkLLYQY17QVdW87z2jJQvcHSjOTAuSDvDsA5qwg5AFED7wAgR5nWNug2lopWd-gDWOVN2oHaLEQ=w259-h243-no" alt="AccessiblityLabel"&gt;&lt;/p&gt;
&lt;p&gt;全体としては次の図のような感じの画面構成にしました。赤文字はAccessibilityLabelに設定した内容です。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/YDffTb8Is0WneTv_Fkyk93PH9mL6LTtYnw3Rg4DUa9BOfQI8UzEGMj41vytF92dgnqgEAdkwGot7Trx6hnaX7kc1H7MYV7hHyZZ9v46QvodTWE-lXhQzrjEL0C-C7fo7GlRbULscWpCPucOOERvWlJTzkKqAcaoNgzj3uQ44E8yn88pUdTeHCW_OzWzFjdoBNcUAUZSJfqbeQ8-BCThPLEmlcA-Bj4HYe1o2aSnjQ25O9TrA-YEQE8twFdpcErdDJ6KRvnPHELL4k8WHc9pcxd9NwYdL-RYlgCzmM32JsnTu2_w4Nix1TSewB-rHuf5GsRR9aq2XiD7jnBoUN1wEi4A9x7csjLxUQX5feS3yPz5bgwyw6ToJDtaB_M6uK6RLN2EWIn5HihfiNOuVXMpUoMuzB1X96Y-tVPKcMaZd2EHk5boRi0hZAwv2SGEj-g_b2x3uc5cxGJXeIfciipnn2rmeuqZZzqb8TmQ5CAnUujaU2uiy-1QeTbRPt0ud5RaIacDEvqd6oFcmzpuRy9eNPnDhHw1VwlC0bgPjhSVupHXuAfd_cYYZh1rkwN-WKzn0Q6iRIO6c41dgbbcvCA_ZeWZ9MGARPLUhxTRtj3-33OO_-VrWhgEIw07TofdCtofxMg3bGbc2qw4gyb6AWoffrZFchpbORfHY0A=w641-h334-no" alt="画面遷移"&gt;&lt;/p&gt;
&lt;h3 id="テストコードを書く"&gt;テストコードを書く&lt;/h3&gt;
&lt;p&gt;ターゲットを追加したときに新たに作られたIntegrationTestsグループの中に新しくファイルを作成します。New FileからObjective-C test case classを選び&lt;code&gt;NavigationTests&lt;/code&gt;などといった名前にします。&lt;/p&gt;
&lt;p&gt;出来たファイルに次のように書きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;KIF/KIF.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NavigationTests&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;KIFTestCase&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@implementation&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NavigationTests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; [tester waitForViewWithAccessibilityLabel:&lt;span style="color:#e6db74"&gt;@&amp;#34;FirstPageLabel&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; [tester tapViewWithAccessibilityLabel:&lt;span style="color:#e6db74"&gt;@&amp;#34;NextPageButton&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; [tester waitForViewWithAccessibilityLabel:&lt;span style="color:#e6db74"&gt;@&amp;#34;SecondPageLabel&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; [tester tapViewWithAccessibilityLabel:&lt;span style="color:#e6db74"&gt;@&amp;#34;Back&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; [tester waitForViewWithAccessibilityLabel:&lt;span style="color:#e6db74"&gt;@&amp;#34;FirstPageLabel&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;testメソッドを見るとわかりますが、先ほど指定したAccessibilityLabelを使っています。各行は次のような内容です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“FirstPageLabel”という名前を付けたViewが現れるのを待つ&lt;/li&gt;
&lt;li&gt;“NextPageButton”という名前を付けたViewをタップする&lt;/li&gt;
&lt;li&gt;“SecondPageLabel”という名前を付けたViewが現れるのを待つ&lt;/li&gt;
&lt;li&gt;“Back”という名前を付けたViewをタップする&lt;/li&gt;
&lt;li&gt;“FirstPageLabel”という名前を付けたViewが現れるのを待つ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;BackというAccessibilityLabelは名づけた覚えはないと思いますが、これはiOSが標準でつけているものだそうです。他にもアラートなどのボタンにAccessibilityLabelがついています。&lt;/p&gt;
&lt;h3 id="実行"&gt;実行&lt;/h3&gt;
&lt;p&gt;XCodeからコマンドキー＋Uで実行可能です。&lt;/p&gt;
&lt;p&gt;このテストケースは何も例外が発生しなければ成功として扱われます。waitForXXXで10秒待っても想定したViewが表示されないなどの場合は例外が発生しテストが失敗します。&lt;/p&gt;
&lt;p&gt;以上が、KIFを用いた最低限のテストでした。&lt;/p&gt;
&lt;p&gt;他にもView指定の方法がいろいろあったり、Scenarioを扱ったりできるようです。そこまでカバーしきれていないので今後使うことがあったらまとめるかも。&lt;/p&gt;</description></item><item><title>jQueryで秒速アコーディオンUI</title><link>https://blog.piyo.tech/posts/2013-12-10-105423/</link><pubDate>Tue, 10 Dec 2013 10:54:23 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-12-10-105423/</guid><description>&lt;p&gt;ヘッダーをクリックすると展開するようないわゆるアコーディオンUIの実装が意外とめちゃくちゃ楽でした。
「アコーディオンUIって簡単にできますか？」って聞かれて、「うーん、どうでしょうか。調べてみます」みたいに返答した自分が恥ずかしいぐらい。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;jQuery&lt;/code&gt;の&lt;code&gt;slideToggle()&lt;/code&gt;というメソッドを使います。&lt;/p&gt;
&lt;h2 id="手順"&gt;手順&lt;/h2&gt;
&lt;p&gt;超カンタンです。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;展開したときに表示したい要素をjQueryでhide()しておく&lt;/li&gt;
&lt;li&gt;ヘッダー要素のclickイベントで、さっきhideした要素をslideToggle()する&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;以上！&lt;/p&gt;
&lt;h2 id="サンプル"&gt;サンプル&lt;/h2&gt;
&lt;p&gt;jsfiddleで作りました。Resultタブでheaderと書かれている部分をクリックすると展開します。&lt;/p&gt;
&lt;iframe width="100%" height="300" src="https://jsfiddle.net/DfrNT/14/embedded/" allowfullscreen="allowfullscreen" frameborder="0"&gt;&lt;/iframe&gt;
&lt;h2 id="展開にかかる時間を変える"&gt;展開にかかる時間を変える&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;slideToggle&lt;/code&gt;は引数にアニメーションの時間をミリ秒で取ることができるので展開する感じを変えることができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;.selector&amp;#34;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;slideToggle&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 1秒
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;.selector&amp;#34;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;slideToggle&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 0.1秒
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>自前のgemをRailsアプリと並行して開発するワークフロー</title><link>https://blog.piyo.tech/posts/2013-11-28-111247/</link><pubDate>Thu, 28 Nov 2013 11:12:47 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-11-28-111247/</guid><description>&lt;p&gt;Railsアプリケーションを書いていて一部機能をgemに切り出したほうがいいんじゃないか、という場面に遭遇したのでローカルでgemを作りました。&lt;/p&gt;
&lt;p&gt;Railsアプリケーション側ではbundlerでローカルにあるソースをrequireして使うことができます。なんでgithub等を介する必要はありません。さらに、サーバーの再起動無しにgem側のソースの更新を反映する方法もあるので、アプリケーションから切り離したgemであることを意識することなく開発をできます。&lt;/p&gt;
&lt;h2 id="まずgemを作る"&gt;まずgemを作る&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ pwd
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;/path/to/gems &lt;span style="color:#75715e"&gt;# ここにいるとする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ bundle gem piyopiyo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="bundlerでローカルのgem指定する"&gt;bundlerでローカルのgem指定する&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Gemfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;gem &lt;span style="color:#e6db74"&gt;&amp;#39;piyopiyo&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;path&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;/path/to/gems/piyopiyo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="サーバーの再起動無しにリロードする"&gt;サーバーの再起動無しにリロードする&lt;/h2&gt;
&lt;p&gt;ググると&lt;code&gt;config/application.rb&lt;/code&gt;や&lt;code&gt;config/environments/development.rb&lt;/code&gt;に色々書く方法が見つかるのですが、どれもうまく動きませんでした。&lt;/p&gt;
&lt;p&gt;幸い、この機能を提供してくれるgemがあるのでそれを使いましょう。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/teohm/require_reloader"&gt;teohm/require_reloader&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Gemfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;group &lt;span style="color:#e6db74"&gt;:development&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;require_reloader&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Gemfile&lt;/code&gt;に追記して&lt;code&gt;bundle&lt;/code&gt;します。&lt;/p&gt;
&lt;p&gt;次に、&lt;code&gt;config/environments/development.rb&lt;/code&gt;に1行追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# config/environments/development.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;AppName&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Application&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;configure &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;RequireReloader&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;watch_local_gems!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一旦サーバーを起動しなおせばreloaderが有効になります。それ以降はgem側のソースコードを変更したあとでサーバーの再起動は必要なくなります。&lt;/p&gt;</description></item><item><title>(追記有り)XCodeのファイルに挿入されるコメントが邪魔。変えたい。</title><link>https://blog.piyo.tech/posts/2013-11-26-142944/</link><pubDate>Tue, 26 Nov 2013 14:29:44 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-11-26-142944/</guid><description>&lt;blockquote&gt;
&lt;p&gt;(追記)この方法では全てのコメントを編集できるわけではないようです。わかったらまた書きます。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;XCodeで新しくプロジェクトを作ったりファイルを追加したりするとファイルの上部にこんなコメントが挿入されますよね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AppDelegate.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AppName
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Created by hoge-name on 2013/11/26.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Copyright (c) 2013年 fuga-company. All rights reserved.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これなんなんですか。みんな邪魔だと思わないんですか。勝手にやるって許せない。&lt;/p&gt;
&lt;p&gt;ちなみに、名前や会社名がどこから来ているかというと、XCode5.0.2の時点ではこのようになっています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;名前：Macのログインユーザー&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;会社名：プロジェクトのOrganization Name&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/IvTosjAnHRZGdN3qcGKeEehb_A8Uwll8r1Z9Ii0yt7U3uucwx4GOp9vzHCF07XC0zZvGfwQcc2koNX7aM4e4O1qtN1s3OUNGU5PwWWbkMhV74Lkgbu4532Wt9SX6jiIr4vNWTCl_Sg7U-eLpZ8mOvn5pzvAyI86b9ZwqhhQ9VR-dQdXUf8GRcZY6WHncl5hZTP4ryRF7dBhSjCvjATtF31YC7XxSRVNa3m2MIgIjL3zsRItgy49d62_XqK3aMrKh8RqrvclajeFSyr8ZxIqISPcW-54xC_as1QmdEto8aerLVtIqpR9_WJiT5iMdR4StH_yTPzw2nhTwsnlcNNNqgH-wgLYHmxtUyAlFWgHDqjfY1G8_nHotSxsDxK9fZMbEUwYn74z3ixkAbHZaM8bzTXw4dTov1dw5c1NMNFct9c3jdBsc9AqFBiQ000zff-OKGvMe0a00whVBQ3ezfbtS-9j6-pCMRiHJP3OUK2OMOHLkulZrkbemmEQjHD5DZTf8pQ5hg6KwxuCQ9OvBJJf_VsgdVkxH549stGrrzRyudVW_5h6-sE5grB2lJuRvKKoQzybNvcu1PEbV8gJFv1LfnwL872IcFAdGn06sLpNmwEoDZHrjc6vz8ZrMPV5r1o4lrgLVeQ0FbXldYn3YE8tN1ZX8IsN6Dr0h9g=w730-h491-no" alt="Organization Name"&gt;&lt;/p&gt;
&lt;h2 id="テンプレート"&gt;テンプレート&lt;/h2&gt;
&lt;p&gt;コメント全体はテンプレートファイルから来ていて、&lt;code&gt;/Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates&lt;/code&gt; に置いてあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;File Templates&lt;/li&gt;
&lt;li&gt;Project Templates&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;XCodeでファイルをプロジェクトを新規作成するときにここが参照されるのですね。また、テンプレートは自作することもできるので、オレオレなテンプレートを使って開発が捗るぜみたいなことも可能です。&lt;/p&gt;
&lt;p&gt;その方法についてはこの辺りを参照してもらえればよさそうです。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.slideshare.net/kaniza1/xcode-cocoa-20120324"&gt;Xcodeのファイルテンプレートを自作する - Cocoa勉強会関西 2012-03-24&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="テンプレートをいじってしまえ"&gt;テンプレートをいじってしまえ&lt;/h2&gt;
&lt;p&gt;ということは、元からあるテンプレートを変えてしまえばファイル上部のコメントを変えることができるわけです。&lt;/p&gt;
&lt;p&gt;例えば、NSObjectを継承したクラスのヘッダーは次のテンプレートを元に作成されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ___FILENAME___
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ___PROJECTNAME___
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Created by ___FULLUSERNAME___ on ___DATE___.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//___COPYRIGHT___
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;___IMPORTHEADER_cocoaSubclass___
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;___FILEBASENAMEASIDENTIFIER___&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;___VARIABLE_cocoaSubclass___&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;COPYRIGHTを出したくないと思ったらその行を削除してしまえば良いわけです。
ところでこのテンプレートファイルにはいろいろなパターンが存在していて、どれを変更すれと、どの場合に効いてくるのかよくわかりません。そこで、Templates配下のファイル内を一括検索＆一括置換してしまいます。&lt;/p&gt;
&lt;h3 id="念のためgitで管理"&gt;念のためgitで管理&lt;/h3&gt;
&lt;p&gt;この手のファイルを変更してしまうとあとあと困ることもあるので、変更をかけるまえに一旦現在の状態をコミットしておきます。&lt;code&gt;/Application&lt;/code&gt;配下なのでおそらく&lt;code&gt;sudo&lt;/code&gt;が必要になります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ sudo git init
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ sudo git add .
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ sudo git commit -m&lt;span style="color:#e6db74"&gt;&amp;#39;initial&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そしたらお好みのエディターで一括置換をかけましょう。例えば日付が要らないという場合は&lt;code&gt; on ___DATE___&lt;/code&gt;を``で置換すればOK。&lt;/p&gt;
&lt;p&gt;XCodeを再起動して新しくファイルを追加するとコメントの部分が変わっていることがわかります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AppDelegate.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AppName
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Created by hoge-name.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Copyright (c) 2013年 fuga-company. All rights reserved.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Emacsで特定のマイナーモードのキーバインドを無効にする</title><link>https://blog.piyo.tech/posts/2013-11-21-205540/</link><pubDate>Thu, 21 Nov 2013 20:55:40 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-11-21-205540/</guid><description>&lt;p&gt;新しく導入したマイナーモードが普段使っている（カスタマイズしてある）キーバインドを上書きしてしまってしばらく何が起こったかよくわからなくなるってことがあって、しかもそれを直すのに少々時間を食ったので覚え書きです。&lt;/p&gt;
&lt;h2 id="そのまえの雑談"&gt;そのまえの雑談&lt;/h2&gt;
&lt;p&gt;Emacsのページ送り、っつーか画面スクロールは&lt;code&gt;Ctrl+v（下側の行へ）&lt;/code&gt;と&lt;code&gt;Meta+v（上側の行へ）&lt;/code&gt;ですが、直感的じゃないと&lt;code&gt;Meta+v&lt;/code&gt;が押しづらいのとでカスタマイズしてます。結構おすすめです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;;; M-p for scroll down&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;(define-key esc-map &lt;span style="color:#e6db74"&gt;&amp;#34;p&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;scroll-down&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;;; M-n for scroll up&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;(define-key esc-map &lt;span style="color:#e6db74"&gt;&amp;#34;n&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;scroll-up&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このようにするとメタキーを押しっぱなしにした状態で&lt;code&gt;n&lt;/code&gt;や&lt;code&gt;p&lt;/code&gt;でページの上下が可能です。個人的な感覚ですが、&lt;code&gt;p&lt;/code&gt;は&lt;code&gt;Ctrl+p&lt;/code&gt;と同じく上側の部分を表示するように移動、&lt;code&gt;n&lt;/code&gt;は&lt;code&gt;Ctrl+n&lt;/code&gt;と同じく下側の部分へを表示するように移動だと思っているので、&lt;code&gt;p&lt;/code&gt;が&lt;code&gt;scroll-up&lt;/code&gt;、&lt;code&gt;n&lt;/code&gt;が&lt;code&gt;scroll-down&lt;/code&gt;と言うのかなと思っていました。&lt;/p&gt;
&lt;p&gt;逆なんですね。&lt;/p&gt;
&lt;h2 id="マイナーモードのキーバインドを無効化"&gt;マイナーモードのキーバインドを無効化&lt;/h2&gt;
&lt;p&gt;最近使っているモードのうち、markdown-modeが&lt;code&gt;Meta-p&lt;/code&gt;を再定義していました。長めのMarkdownファイルを編集していて、少し戻りたいなと思ったときに&lt;code&gt;Meta-p&lt;/code&gt;を押したらファイルの先頭近くに戻ってしまって自分の位置を見失うみたいな。それが多発しました。&lt;/p&gt;
&lt;p&gt;どうやら&lt;code&gt;Meta-p&lt;/code&gt;は1つ前のリンクにジャンプするようです。&lt;/p&gt;
&lt;p&gt;そこで、markdown-modeの&lt;code&gt;Meta-p&lt;/code&gt;を消します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;(define-key markdown-mode-map (kbd &lt;span style="color:#e6db74"&gt;&amp;#34;M-p&amp;#34;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この方法今更知ったけどもっと早く知ってればいろいろ回避できたのに。&lt;/p&gt;</description></item><item><title>Mac OS XでWiFiの強度を調べるコマンド</title><link>https://blog.piyo.tech/posts/2013-11-21-203842/</link><pubDate>Thu, 21 Nov 2013 20:38:42 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-11-21-203842/</guid><description>&lt;p&gt;Mac OS Xのプライベートフレームワークにairportというコマンドが含まれていて、このコマンドを使うとWiFiの強度をRSSIという数値で取ることができます。スクリプト言語なんかと組み合わせると多少遊べるかもしれません。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://osxdaily.com/2007/01/18/airport-the-little-known-command-line-wireless-utility/"&gt;airport – the Little Known Command Line Wireless Utility&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[http://osxdaily.com/2007/01/18/airport-the-little-known-command-line-wireless-utility/:image:large]&lt;/p&gt;
&lt;h2 id="rssiとは"&gt;RSSIとは&lt;/h2&gt;
&lt;p&gt;RSSIは受信信号強度のことで携帯の電波何本みたいなもん。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://maoccoy.tumblr.com/post/970746982"&gt;Lifelog (屋内編（1） 置き場所やアンテナ角度で感度アップ！：無線LANの新常識)&lt;/a&gt;からの引用ですが、RSSIの数値を体感に直すとこんなもんらしいです。&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;&lt;th&gt;RSSI&lt;/th&gt;&lt;th&gt;電波の強さ&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;-39dBm以上&lt;/td&gt;&lt;td&gt;かなり強い&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;-49〜-40dBm&lt;/td&gt;&lt;td&gt;強い&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;-59〜-50dBm&lt;/td&gt;&lt;td&gt;普通&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;-79〜-60dBm&lt;/td&gt;&lt;td&gt;弱い&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;-80dBm以下&lt;/td&gt;&lt;td&gt;接続しにくい&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;h2 id="定期的にwifi強度を出力するrubyプログラム"&gt;定期的にWiFi強度を出力するRubyプログラム&lt;/h2&gt;
&lt;p&gt;受信している全てのWiFiの電波のRSSIとSSID、BSSIDを電波が強い順に書き出すプログラムを作ってみました。Macを持って移動しながら電波の強い場所を探したりするのに少しは役に立つと思います。&lt;/p&gt;
&lt;script src="https://gist.github.com/pi-chan/7579979.js"&gt;&lt;/script&gt;</description></item><item><title>Rubyで数字の桁数が揃っていない文字列を数字順にソートする</title><link>https://blog.piyo.tech/posts/2013-11-19-122745/</link><pubDate>Tue, 19 Nov 2013 12:27:45 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-11-19-122745/</guid><description>&lt;p&gt;数字部分の桁数が揃っていないこういうファイル群があるとします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;image1.jpg&lt;/li&gt;
&lt;li&gt;image2.jpg&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;li&gt;image10.jpg&lt;/li&gt;
&lt;li&gt;image11.jpg&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;多くの言語ではこれらを文字列として持っているArrayをソートすると普通は辞書順になるので次のような順になってしまいます。Rubyもそうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;image1.jpg&lt;/li&gt;
&lt;li&gt;image10.jpg&lt;/li&gt;
&lt;li&gt;image11.jpg&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;li&gt;image2.jpg&lt;/li&gt;
&lt;li&gt;image20.jpg&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;番号の若い順に処理したい場合はこれだと困るのでちょっと細工をします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# このままだと辞書順&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;images &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Dir&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;glob(&lt;span style="color:#e6db74"&gt;&amp;#34;image*.jpg&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# これで数字の昇順になる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;image &lt;span style="color:#f92672"&gt;=&lt;/span&gt; images&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sort_by{&lt;span style="color:#f92672"&gt;|&lt;/span&gt;file&lt;span style="color:#f92672"&gt;|&lt;/span&gt; file&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/\d+/&lt;/span&gt;&lt;span style="color:#f92672"&gt;].&lt;/span&gt;to_i}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>結局わからずじまいだけどMySQLのJOINが遅い気がしたので調べた</title><link>https://blog.piyo.tech/posts/2013-11-07-164659/</link><pubDate>Thu, 07 Nov 2013 16:46:59 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-11-07-164659/</guid><description>&lt;p&gt;開発費をいただいて開発したRSSリーダー&amp;amp;情報収集サービス&lt;a href="http://u.throttleapp.me/"&gt;throttle&lt;/a&gt;、の内部で使っているSQLの中に異様に遅いものがあったので、似たような環境をローカルに再現して確認することにしました。&lt;/p&gt;
&lt;p&gt;SQLの確認なので生のSQLクエリを書いて検証すればいいのですが、いろいろと条件を揃えるためにRSSリーダーと同じくRailsを使用しました。データベースはMySQL5.5系で、エンジンはInnoDBです。&lt;/p&gt;
&lt;h1 id="準備編"&gt;準備編&lt;/h1&gt;
&lt;h2 id="モデル"&gt;モデル&lt;/h2&gt;
&lt;p&gt;実際のRSSリーダーで使っているモデルの一部を抜き出したような形でモデルを用意しました。&lt;/p&gt;
&lt;p&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/x/xoyip/20131107/20131107162831.png" alt="f:id:xoyip:20131107162831p:plain" title="f:id:xoyip:20131107162831p:plain" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;それぞれ、次のような関連を持っています。UserとEntryはRelationshipを介して、多対多の関連になっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;User&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; has_many &lt;span style="color:#e6db74"&gt;:relationships&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; has_many &lt;span style="color:#e6db74"&gt;:entries&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;through&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:relationships&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Entry&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; has_many &lt;span style="color:#e6db74"&gt;:relationships&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;dependet&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:destroy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; has_many &lt;span style="color:#e6db74"&gt;:users&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;through&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;:relationships&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Relationship&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; belongs_to &lt;span style="color:#e6db74"&gt;:user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; belongs_to &lt;span style="color:#e6db74"&gt;:entry&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;本当はここにRSSフィードというモデルが必要になってくるのですが簡略化のために省略しています。UserとEntryが多対多になっているのは同一Entryを複数ユーザーがSubscribeする可能性があるからです。複数ユーザーが同じ記事を購読していること表現するために関連テーブルRelationを用いています。&lt;/p&gt;
&lt;h2 id="大量のデータを突っ込む"&gt;大量のデータを突っ込む&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;db/seeds.rb&lt;/code&gt;にデータ挿入用のコードを書いて、&lt;code&gt;$ rake db:seed&lt;/code&gt;コマンドを実行します。&lt;/p&gt;
&lt;p&gt;ソースコードは&lt;a href="https://github.com/pi-chan/jointest"&gt;github:xoyip/jointest&lt;/a&gt;に置いてあります。&lt;/p&gt;
&lt;p&gt;これによりUserが500件、Entryが100万件、Relationshipが約3000万件という検証用データができあがります。1Entryあたり10人〜50人のユーザーが関連付けられる、つまり平均30人なので100万×30で3000万件というわけです。&lt;/p&gt;
&lt;p&gt;Entryにはpublished_atというフィールドがあります。Railsがデフォルトで用意するタイムスタンプ2つ（created_at,updated_at）とは異なり、記事が投稿された日を意味します。本来このフィールドはRSSフィード内に書かれています。&lt;/p&gt;
&lt;h1 id="検証編"&gt;検証編&lt;/h1&gt;
&lt;p&gt;データの用意が済みました（ローカルマシンで5時間ぐらいかかったと思います。寝てたので詳細はわかりませんが。）。これでRSSリーダーthrottleのプロダクション環境と同じような環境を用意できたと言えます。&lt;/p&gt;
&lt;p&gt;ちなみにプロダクション環境で問題となっているSQLは次のActiveRecordが生成するものです。
あるuserが購読している記事のうち、published_atが直近1日以内のもの、という意味です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;entries&lt;span style="color:#f92672"&gt;.&lt;/span&gt;where(&lt;span style="color:#e6db74"&gt;&amp;#34;published_at &amp;gt; ?&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;day&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ago)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;SQL自体はこう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#f92672"&gt;`&lt;/span&gt;entries&lt;span style="color:#f92672"&gt;`&lt;/span&gt;.&lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; &lt;span style="color:#f92672"&gt;`&lt;/span&gt;entries&lt;span style="color:#f92672"&gt;`&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;INNER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;JOIN&lt;/span&gt; &lt;span style="color:#f92672"&gt;`&lt;/span&gt;relationships&lt;span style="color:#f92672"&gt;`&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ON&lt;/span&gt; &lt;span style="color:#f92672"&gt;`&lt;/span&gt;entries&lt;span style="color:#f92672"&gt;`&lt;/span&gt;.&lt;span style="color:#f92672"&gt;`&lt;/span&gt;id&lt;span style="color:#f92672"&gt;`&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;`&lt;/span&gt;relationships&lt;span style="color:#f92672"&gt;`&lt;/span&gt;.&lt;span style="color:#f92672"&gt;`&lt;/span&gt;entry_id&lt;span style="color:#f92672"&gt;`&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; &lt;span style="color:#f92672"&gt;`&lt;/span&gt;relationships&lt;span style="color:#f92672"&gt;`&lt;/span&gt;.&lt;span style="color:#f92672"&gt;`&lt;/span&gt;user_id&lt;span style="color:#f92672"&gt;`&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; (published_at &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2013-11-06 06:29:20&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;ORDER&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BY&lt;/span&gt; entries.published_at &lt;span style="color:#66d9ef"&gt;DESC&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今回のテストプログラムでもこれと同じコードを測定します。&lt;/p&gt;
&lt;h2 id="既存のやり方"&gt;既存のやり方&lt;/h2&gt;
&lt;p&gt;まずプロダクションと同じやり方を実行しました。複数のユーザーで複数回、同様の処理を実行したところ、実行時間は平均的にみて約0.1秒。だいたいこの前後でした。&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #ff2600"&gt;&lt;strong&gt;あれ？全然遅くない！&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;プロダクション環境では大量の購読がある人だとこのSQLの実行に1分以上かかってしまうようなことが起こっていたのですが、このテストアプリではそんなことは無いようです。&lt;/p&gt;
&lt;p&gt;本当はこのテストアプリでもある程度遅い状態を再現した上で、いろいろ弄って早くなるパターンを探したかったんですが…ｗｗ&lt;/p&gt;
&lt;p&gt;残念です。&lt;/p&gt;
&lt;h1 id="プロダクション環境がなぜ遅いのか"&gt;プロダクション環境がなぜ遅いのか&lt;/h1&gt;
&lt;p&gt;近い条件にはしたつもりですが、データ件数や各レコードのデータ量はプロダクション環境と異なっています。また、DBのパラメータなども違う可能性が高いので一概に比較はできないのでしょうね。&lt;/p&gt;
&lt;p&gt;可能性がありそうな要因を挙げておきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;データ量が大幅に多い&lt;/li&gt;
&lt;li&gt;なんらかのボトルネックが生じている（IOなど）&lt;/li&gt;
&lt;li&gt;パラメータがイマイチ&lt;/li&gt;
&lt;li&gt;ストレージアクセスが遅い&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などなど。&lt;/p&gt;
&lt;p&gt;結論はでませんでした〜。&lt;/p&gt;</description></item><item><title>Xcode5でcommand line toolsをダウンロードする</title><link>https://blog.piyo.tech/posts/2013-10-29-165207/</link><pubDate>Tue, 29 Oct 2013 16:52:08 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-10-29-165207/</guid><description>&lt;p&gt;今まではPreferences→Downloads→Componentsから行っていたcommand line toolsのインストールですが、Xcode5から（もしくはMavericksから？）はその場所に見当たらなくなっていました。&lt;/p&gt;
&lt;p&gt;代わりにターミナルでxcode-selectというコマンドを叩くとインストールが済んでいない場合には確認メッセージが出てインストールできるようになります。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ xcode-select --install
xcode-select: note: install requested for command line developer tools
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;だいぶはまったのでメモしておきます。&lt;/p&gt;</description></item><item><title>【追記有】Unityの開発環境がひどい！脱MonoDevelop。SublimeTextおすすめ</title><link>https://blog.piyo.tech/posts/2013-10-18-215707/</link><pubDate>Fri, 18 Oct 2013 21:57:07 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-10-18-215707/</guid><description>&lt;p&gt;&lt;strong&gt;追記ここから&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2014/06/23現在、少しまともになっています→&lt;a href="https://blog.piyo.tech/posts/2014-06-21-193000"&gt;MonoDevelopがバージョン4になって割とまともになった…！ - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;追記おわり&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Unity使い始めました。なんなんですかこれ。
MonoDevelopは重いし日本語周りが全然まともに使えない上、右クリックメニューに至っては何も文字がない…！ｗｗ&lt;/p&gt;
&lt;p&gt;エンジンはすごいんでしょうけど。&lt;/p&gt;
&lt;p&gt;このままだとまともに触る気も起きなくなりそうなので早いタイミングでSublimeText2のエコシステムになんとかしてもらうことにしました。&lt;/p&gt;
&lt;h1 id="インストールしたプラグイン"&gt;インストールしたプラグイン&lt;/h1&gt;
&lt;h2 id="unity関係"&gt;Unity関係&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Unity3D&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;シンタックスハイライト&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unity3D Build System&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ビルド（後述）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unity3D Script Referenece Search&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ソースからリファレンスに飛べます。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unity3D Snippets and Completes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Unityのスニペットと補完&lt;/p&gt;
&lt;h2 id="それ以外"&gt;それ以外&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;CompleteSharp&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;前述の補完のために必要（のはず）です。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AutoRunner&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ソースコードを自動的にフォーマットする拡張です。詳細は次のリンク。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qiita.com/mikamikuh@github/items/bfa1c8067fa3bb71e52d"&gt;c# - Sublime Text2にフォーマッタを導入する - Qiita [キータ]&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="各種設定"&gt;各種設定&lt;/h1&gt;
&lt;h2 id="unityの外部editorをsublimeにする"&gt;Unityの外部EditorをSublimeにする&lt;/h2&gt;
&lt;p&gt;Unity Preferences -&amp;gt; External Tools -&amp;gt; External Script Editor をSublime Text2にします。&lt;/p&gt;
&lt;h2 id="補完のためにプロジェクト作成"&gt;補完のためにプロジェクト作成&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://qiita.com/kyusyukeigo/items/a33388572990932bba87"&gt;c# - CompleteSharpでUnityスクリプトの補完方法 - Qiita [キータ]&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="unity3d-build-systemを使うには"&gt;Unity3D Build Systemを使うには&lt;/h2&gt;
&lt;p&gt;MonoDevelopを一切使わない場合コマンドキー+Bで動くビルドコマンドが失敗します。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;#39;xxxxx-csharp.sln&amp;#39; not found.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sublimeのコンソールにこんなエラーが表示されます。MonoDevelopで開いたときに作られるslnファイルがないって言われてるんですね。External Script Editorの設定を戻してMonoDevelopでファイルを開いたりしなくても、slnファイルを生成できます。&lt;/p&gt;
&lt;p&gt;Unityをアクティブにし、Assets -&amp;gt; Sync MonoDevelop Projectを実行するだけ。これでSublimeからUnityプロジェクトをビルドできます。&lt;/p&gt;
&lt;h2 id="sublimeとは関係ないけど保存形式を変更する"&gt;(Sublimeとは関係ないけど)保存形式を変更する&lt;/h2&gt;
&lt;p&gt;Unityのデフォルトではいろいろなファイルがバイナリで保存されてしまいます。バイナリだと差分をとったりマージしたりという複数人体制での開発で絶対に必要なプロセスがまったく効かないのですぐに困ります。&lt;/p&gt;
&lt;p&gt;幸いテキストベース（YAML）で保存できるようなのでそちら変更しておきましょう。&lt;/p&gt;
&lt;p&gt;UnityのメニューでEdit-&amp;gt;Project Settings-&amp;gt;Editor-&amp;gt;Asset Serializationを&lt;strong&gt;Force Text&lt;/strong&gt;にしましょう。&lt;/p&gt;
&lt;h1 id="さあunityチュートリアル"&gt;さあUnityチュートリアル&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://japan.unity3d.com/developer/document/tutorial/my-first-unity/01.html"&gt;UNITY - Developer - はじめての Unity - 第1回 世界の「骨格」をつくろう&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>サッカー日本代表の試合を見ていてわかった仕事のコツ</title><link>https://blog.piyo.tech/posts/2013-10-17-222758/</link><pubDate>Thu, 17 Oct 2013 22:27:58 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-10-17-222758/</guid><description>&lt;p&gt;[f:id:xoyip:20131017222557j:image:w250]&lt;/p&gt;
&lt;p&gt;サッカー日本代表の試合を観ることが好きで2010年のワールドカップあたりからは1試合も見逃すことなく観戦してますが、最近勝ててないですよね。メンバーのコンディション不良とかザッケローニの采配とかいろいろあると思うんですが、今日はそんなことどうでもよくて。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;日本代表の試合を見ていて気になるのは攻撃に手数をかけすぎることかなと。日本と戦う相手はボール奪ったあとは大抵シンプルに速い攻撃を仕掛けてきてゴールに迫ってくるという印象があるけど、日本の場合はゴール近くに行く時にはディフェンスのブロックができているっていう。まあ、サッカーはプレーできないんで素人な考えですが、そう見えます。で、出しどころがなくて横パス、バックパス、ディフェンスラインでパス回し、キーパーに戻す。みたいな展開になるなあと。&lt;/p&gt;
&lt;p&gt;この状況を見て「いや、もっとシンプルに前に出せよとか」「さっさとクロス上げろよ（ハーフナー投入後）」「前向いてシュート打てよ」みたいな感想をもつわけです。先日のセルビア戦、ベラルーシ戦ともに同じようなことをグチグチ言いながら見てたんですが、あるとき気づいたんですよ。これって自分に似てるんじゃないか？って。&lt;/p&gt;
&lt;h1 id="横パスしてちゃダメなんだよ"&gt;横パスしてちゃダメなんだよ&lt;/h1&gt;
&lt;p&gt;僕はエディタいじりとかWebサービスとかカスタマイズとかが好きで、仕事効率化なアプリもたくさん使ってます。◯◯をやるにはどのアプリ/サービスがいいのかな、なんてことをずっと考えてて全然本題が進まない。タスク管理とかまさにそうで、OmniFocus((&lt;a href="http://www.omnigroup.com/omnifocus"&gt;OmniFocus&lt;/a&gt;))を入れたり、Wunlderlist((&lt;a href="https://www.wunderlist.com/en/"&gt;Wunlderlist&lt;/a&gt;))にしたり、いやいややっぱEmacsでhowm((&lt;a href="http://howm.sourceforge.jp/index-j.html"&gt;howm&lt;/a&gt;))っしょみたいになったり。で、結局タスク管理ややりたいことを考えられなくなってる。最近はそこにマインドマップも追加でｗｗ&lt;/p&gt;
&lt;p&gt;サッカーみながら気づきました。これって横パスばっかり出してるのと一緒だよね？タスク管理ってゴールに仕掛けてシュート打たなきゃダメでしょ。&lt;/p&gt;
&lt;p&gt;そのときのショックと来たら。いつもしょぼいなーと思ってみてる日本のサッカーと同じことを自分がしていたとは！&lt;/p&gt;
&lt;h1 id="仕掛けてシュートを打つことの大切さ"&gt;仕掛けてシュートを打つことの大切さ&lt;/h1&gt;
&lt;p&gt;タスク管理は一例ですが、それ以外のこと全般にもこのパターンが当てはまることって多いのかなと思います。&lt;/p&gt;
&lt;p&gt;僕は比較的自由業なので、「ああいうことやりたい」とか「こういうのに興味がある」とか考える余裕があるときもたまにあるんですが、いろいろやりたいと考えてるのが楽しくて実際に何もできていなかったりすることがよくあるように思います。お金になってないじゃんみたいな感じです。&lt;/p&gt;
&lt;p&gt;そういう自分に気づいて、こりゃいかんなーと思って気を引き締めるものの、気がついたらまた妄想をこねくり回してたりとか。&lt;/p&gt;
&lt;p&gt;で、さっきのやつです。シュート打とうよ。&lt;/p&gt;
&lt;p&gt;もっというと、仕掛けてシュート打とうよ。&lt;/p&gt;
&lt;p&gt;仕掛けるというのが大切だと思います。なんとなくやろうと思ってたことができてることはあるけど、そうではなくて、設定したゴールを意識しながら行動するということが大事だと思います。&lt;/p&gt;
&lt;p&gt;QBKでシュートを打ったとしてそれが入ればいいんだけど、入らないことのほうが多いですよね。ゴール設定、そこへの意識、行動。&lt;/p&gt;
&lt;p&gt;この3つを揃って初めて良いプロセスと良い結果が得られるのかなと思います。&lt;/p&gt;</description></item><item><title>ソニックガーデンの納品のない受託開発における約束事についてゆる考</title><link>https://blog.piyo.tech/posts/2013-10-15-142636/</link><pubDate>Tue, 15 Oct 2013 14:26:37 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-10-15-142636/</guid><description>&lt;p&gt;先日のブログでソニックガーデンの受託開発について書いたのですが、その続きです。納品のない受託開発における決まり事にはどのような理由があるのかを考えてみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-10-12-205240"&gt;ソニックガーデンの納品しない受託開発がおもしろい - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[https://blog.piyo.tech/posts/2013-10-12-205240:image:large]&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h1 id="約束すること"&gt;約束すること&lt;/h1&gt;
&lt;p&gt;##「価値に見合うパフォーマンスを出すために全力で働くこと」&lt;/p&gt;
&lt;p&gt;クライアントから毎月もらう金額に見合ったパフォーマンスを出さなければこのビジネスは続けられません。クライアントが納得するパフォーマンス（＝無料お試し期間での仕事の結果で判断してもらっている）を出すというのが、納品のない受託開発で提供しているサービス、肝でしょう。&lt;/p&gt;
&lt;p&gt;##「お客さまのビジネス価値に繋がらないことには意見すること」&lt;/p&gt;
&lt;p&gt;メインの売り物が価値に見合うパフォーマンスだとすると、この約束事は付加価値になっています。プロダクトの成長に積極的に関与しますよという意思表示です。プロダクトの方向性が定まっていない場合でもソニックガーデンに依頼すれば方向を修正しつつプロダクトを育てていける、という価値に繋がっています。&lt;/p&gt;
&lt;p&gt;##「お客さまには出来ることと出来ないことを正直に話すこと」&lt;/p&gt;
&lt;p&gt;こちらも付加価値といえば付加価値になるのかな…。自分たちで出来ない可能性があることを「できるから任せてくれ」なんて姿勢で失敗なんてしたらクライアントに迷惑をかけます。自分たちの信頼も失うことになります。&lt;/p&gt;
&lt;h1 id="約束しないことやらないと約束すること"&gt;約束しないこと(やらない、と約束すること)&lt;/h1&gt;
&lt;p&gt;##「納品や提供のためのドキュメントは作らないこと」&lt;/p&gt;
&lt;p&gt;ドキュメントと言ってもいろいろあると思いますが、要件定義書やテスト関係の書類などプロダクト自体に何の価値も付与しないものもあります。例えば要件定義書や設計書なんかは最初に作るものを決め、あとから言った言わないにならないために用意しておくものです。設計書に従って作るには◯◯万円です、設計書にないからできません、仕様変更するには追加で◯万円です、みたいな。&lt;/p&gt;
&lt;p&gt;そんなの意味ないのでやめませんか、ということなんだと思います。&lt;/p&gt;
&lt;p&gt;##「お客さまの会社にプログラマは訪問しないこと」&lt;/p&gt;
&lt;p&gt;これは記事中に記載がありました。自社に訪問してもらえればかからない費用が発生させることになってしまうからとのことです。&lt;/p&gt;
&lt;p&gt;##「見積もりと調整のための営業担当がいないこと」&lt;/p&gt;
&lt;p&gt;見積もりや調整はクライアントになんの価値も提供しません。クライアントに価値を提供しないのだったら、その分の人件費はかけずに本来の開発業務にあてたほうがコストもかからないでしょう。&lt;/p&gt;
&lt;p&gt;##「納期を絶対に死守するという約束はできないこと」&lt;/p&gt;
&lt;p&gt;納期を死守するという約束をすることは、変更に柔軟ではなくなるということになります。前回の記事で書きましたが納期を守ることが第一目的となってしまい、本当に必要な意見を抑えこむことになります。それだったら「納期は守れません、でもいいものにするための努力はしますよ」といった約束をしたほうがクライアントにとっても自分達にとっても健全です。&lt;/p&gt;
&lt;h1 id="まとめではないけど"&gt;まとめではないけど&lt;/h1&gt;
&lt;p&gt;やることとやらないことが合理的で、ある意味対になっていますね。やらないことをやろうとしていると、おかしなところで足を引っ張られて「価値に見合うパフォーマンス」が出せなくなるので。&lt;/p&gt;</description></item><item><title>ソニックガーデンの納品しない受託開発がおもしろい</title><link>https://blog.piyo.tech/posts/2013-10-12-205240/</link><pubDate>Sat, 12 Oct 2013 20:52:41 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-10-12-205240/</guid><description>&lt;p&gt;ソニックガーデンという会社が納品のない受託開発という変わった開発スタイルで受託開発を行っているらしいです。社長のインタビュー記事が参考になりますっていうか、すごく興味深かったです。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://careerhack.en-japan.com/report/detail/203"&gt;“納品のない受託開発”とは何か？―ソニックガーデン代表 倉貫義人氏が全貌を語り尽くす。│CAREER HACK&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[http://careerhack.en-japan.com/report/detail/203:image:large]&lt;/p&gt;
&lt;p&gt;&lt;a href="http://careerhack.en-japan.com/report/detail/204"&gt;プログラマは職人、力なければ淘汰されて然るべき―ソニックガーデン倉貫氏が問う、プログラマの覚悟。│CAREER HACK&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[http://careerhack.en-japan.com/report/detail/204:image:large]&lt;/p&gt;
&lt;h1 id="納品がないってどういうこと"&gt;納品がないってどういうこと！？&lt;/h1&gt;
&lt;p&gt;納品のない受託開発には次のような特徴があるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;開発から運用まですべてを担当する&lt;/li&gt;
&lt;li&gt;月々定額で引き受ける&lt;/li&gt;
&lt;li&gt;倒産or事業をやめるまで続く&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;お客さんにはスタートアップや新規事業が多いらしいですね。そのフェーズの人は作りたいものがはっきりと定まっていることはありません。従来型の見積もり方法である期間と予算を決めるというやり方では必ず破綻します。&lt;/p&gt;
&lt;p&gt;これはなるほどと思えるというか、ちょうど僕も個人的に良いやり方ないかなと思っていた所で、まさにそれを解決するための方法なのかなという気がしました。&lt;/p&gt;
&lt;h1 id="納品してハイ終わりのデメリット"&gt;納品してハイ終わり！のデメリット&lt;/h1&gt;
&lt;p&gt;ソニックガーデンさんの記事にもありますが、ひとことで言えばリスクが大きすぎることです。&lt;/p&gt;
&lt;p&gt;僕の実体験でもあるのですが、見積もりなんて不可能です。ある程度作りたいものが見えているものでも絶対に予期しない変更が入るので、それを見越した見積もりをします。言ってしまえば盛るわけですね。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1ヶ月ぐらいかかりそうだから80万ぐらいで見積だしておこうかな？でもきっと何か起こるだろうし、1.4倍の115万円ぐらいにしとこう&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;こういう盛り方をします((1.4倍という数字はこの記事を参考にしています。実体験と照らしあわせてもなかなか良い線いってるパラメータですね。&lt;a href="http://president.jp/articles/-/7538"&gt;時間の見積もりをどうするか？　－「仕事が忙しい！」の9割は思い込みだった【2】：PRESIDENT Online - プレジデント&lt;/a&gt;))
。&lt;/p&gt;
&lt;p&gt;スタートアップの場合は更に厄介です。作るものの方向性を柔軟に変えるというのはスタートアップの定理みたいなものなので正確な見積もりなんて出せるわけがないんですよね。もはや山勘、あてずっぽう。&lt;/p&gt;
&lt;p&gt;そうするともういろいろやばいですよね。&lt;/p&gt;
&lt;p&gt;開発側はできるだけやることを減らしたい。減らさずになんでも引き受けていると金銭的にも精神的にもつらくなってきます。プロジェクトにポジティブな意見・提案があっても結局自分に振りかかるので黙るようになります。
発注側は発注側で作りたいものがなかなかつくれないし、開発側が建設的な意見を言わなくなるし、追加の予算もかかるしで結局誰も必要としないものができたり。&lt;/p&gt;
&lt;h2 id="インセンティブがない"&gt;インセンティブがない&lt;/h2&gt;
&lt;p&gt;つまるところどちらにとってもプロジェクトを適切に成長させる動機づけがないんですよね。
開発にとっては仕事を増やしたくないし、発注側にとっては金払うんだからちゃんとやってくれっていうところに意識が行ってしまう。&lt;/p&gt;
&lt;p&gt;ほんと、デメリット。先の記事でも誰も幸せにならないとありますが、まさにその通りです。&lt;/p&gt;
&lt;h1 id="どんなやり方なんだろう"&gt;どんなやり方なんだろう？&lt;/h1&gt;
&lt;p&gt;理屈はわかりましたがどんな風に働くか全然想像できなかったのでさらに記事を読み進めて具体的な働き方を見てみます。&lt;/p&gt;
&lt;h2 id="やること"&gt;やること&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;「価値に見合うパフォーマンスを出すために全力で働くこと」&lt;/li&gt;
&lt;li&gt;「お客さまのビジネス価値に繋がらないことには意見すること」&lt;/li&gt;
&lt;li&gt;「お客さまには出来ることと出来ないことを正直に話すこと」&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2 id="やらないこと"&gt;やらないこと&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;「納品や提供のためのドキュメントは作らないこと」&lt;/li&gt;
&lt;li&gt;「お客さまの会社にプログラマは訪問しないこと」&lt;/li&gt;
&lt;li&gt;「見積もりと調整のための営業担当がいないこと」&lt;/li&gt;
&lt;li&gt;「納期を絶対に死守するという約束はできないこと」&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;ビジネスの価値にならないことは意見する、これすごい。要はそんなの無駄ですよやめましょうって言うわけですよね。これが従来型の開発だと「いやいや、仕事増やしたくないから言ってんじゃないの？」と思われてしまう。それが言えるようになるわけですね。逆にもっとこうしたほうがいいと思うと言ってもいいわけです。予算が決まっているわけではないので期間が伸びるのさえ了承してもらえばOKでしょう。&lt;/p&gt;
&lt;p&gt;「ドキュメントを作らない」「訪問しない」「納期は守るとは言えません」、このへんもすごいですね。これで納得しくれるお客さんがいるというのだから驚きました。価値を評価してくれているからなんですかね。&lt;/p&gt;
&lt;h1 id="真似できる"&gt;真似できる？&lt;/h1&gt;
&lt;p&gt;ソニックガーデンさんのやり方はまさに理想的です。このやり方ができるのであれば僕としては同じやり方でやっていきたいと思います。ですが、果たしてそんなにうまくいくんでしょうか。僕が疑問に思った点と、どのように対応しているのかを想像してみようと思います。&lt;/p&gt;
&lt;h2 id="どうやって週の半分で納得してもらうのか"&gt;どうやって週の半分で納得してもらうのか&lt;/h2&gt;
&lt;p&gt;ソニックガーデンさんでは月々定額でのビジネスをされているようですが、個々のエンジニアは受託開発と自社ビジネスで半々の時間配分で仕事をしているようです。これでどちらの仕事もうまく回っているというので驚きです。&lt;/p&gt;
&lt;p&gt;まず納品のない受託開発のほうですが、お客さんはスピードを重視していると思うんです。なんせスタートアップだから。なので、できる限りのスピードで進めて欲しいという要望は必ずあると思います。仮に技術力が高くて週の半分で並のエンジニアが週5日で働いた分のパフォーマンスを出せるとしても、それだったらそのパフォーマンスでがっつりやってくれればもっとスピードアップできるでしょ、と僕だったら思ってしまいます。&lt;/p&gt;
&lt;p&gt;ソニックガーデンさんではトライアル期間を設けているようですね。これは依頼側にとってはいいですよね。おそらくトライアルの期間で「普通のエンジニア探すのも大変なのにこの値段でこれだけやってくれるなら」と思ってもらうことができているんでしょう。&lt;/p&gt;
&lt;p&gt;週半分で並以上のパフォーマンスを出してくれる目の前のエンジニアに依頼するか、フルコミットでそこそこの成果は出せるけどまだ見ぬエンジニア。これだったら前者でもいいかなと思いそうです。&lt;/p&gt;
&lt;p&gt;それでもフルで手伝って欲しいと言われたらきっと断るんでしょうね。全ての依頼を受けきれていないということらしいから、ポリシーに反してたらお断りすればいいだけですしね。&lt;/p&gt;
&lt;h2 id="とはいえそんなにパフォーマンス出せるの"&gt;とはいえそんなにパフォーマンス出せるの？&lt;/h2&gt;
&lt;p&gt;開発の仕事の中でも、経験があればさくっと終わる部分とそうでない部分とがあると僕は思っています。システムの構成やデータベースを設計することは経験の有無により大きな差がでるでしょう。経験豊富の人のほうが勘所がわかっていたりするので。ところがその大まかな方針に基いて作っていくこと、画面レイアウトを決めたりすることは経験によって差はあれど、ある程度時間がかかるはずです。というか、この部分はどうしても時間食う部分ではないかと。
エンジニアのいないスタートアップからの依頼であればそういう雑多で細かい部分も含むのではないかと想像できますので、そういった範疇の仕事もありそうです。&lt;/p&gt;
&lt;p&gt;この点はすごく難しいです。細かい部分の開発は技術力が高くても生産性が何倍もに開くものではないと思っていましたので。でも何かしら秘密があるんじゃないかと思います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;過去の資産を再利用しやすいように整備している&lt;/li&gt;
&lt;li&gt;手戻りが少ないようにテストファーストで効率UP&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;てか、秘密でもなんでもなくただの正攻法でした。そういった正攻法の積み重ねがパフォーマンスに繋がっているのかもしれません。&lt;/p&gt;
&lt;h1 id="プログラマを一生の仕事にする"&gt;プログラマを一生の仕事にする&lt;/h1&gt;
&lt;p&gt;ソニックガーデンさんの掲げるこのビジョンはいいですね。よくある35歳定年説は日本式の開発様式が産んだものでしょうし、従来型の受託開発が減っていけば変わっていくのでしょう。プログラマの報酬が不適切に低い状況も改善できれば本当に一生の仕事にできるものになるかもしれません。&lt;/p&gt;
&lt;p&gt;それっていいですよねー。&lt;/p&gt;</description></item><item><title>記事をFacebookやTwitterなどの各種サービスでシェアする方法まとめ</title><link>https://blog.piyo.tech/posts/2013-09-04-110000/</link><pubDate>Thu, 10 Oct 2013 11:34:54 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-09-04-110000/</guid><description>&lt;p&gt;SNSやサービスにシェアするためのボタンやリンクは自分でも作ることができます。&lt;/p&gt;
&lt;p&gt;このブログのトップページをシェアする場合を例に書いてみます。&lt;/p&gt;
&lt;h2 id="メール"&gt;メール&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;a href=&amp;#34;mailto:?subject=ぴよログ&amp;amp;body=https://blog.piyo.tech/&amp;#34; &amp;gt;メール&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="mailto:?subject=ぴよログ&amp;body=https://blog.piyo.tech/" target="_blank"&gt;メール&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="facebook"&gt;Facebook&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;a href=&amp;#34;http://www.facebook.com/sharer.php?u=https://blog.piyo.tech/&amp;amp;t=ぴよログ&amp;#34; target=&amp;#34;_blank&amp;#34;&amp;gt;Facebook&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://www.facebook.com/sharer.php?u=https://blog.piyo.tech/&amp;t=ぴよログ" target="_blank"&gt;Facebook&lt;/a&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="twitter"&gt;Twitter&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;a href=&amp;#34;https://twitter.com/intent/tweet?url=https://blog.piyo.tech/&amp;amp;text=ぴよログ&amp;#34; target=&amp;#34;_blank&amp;#34;&amp;gt;Twitter&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="https://twitter.com/intent/tweet?url=https://blog.piyo.tech/&amp;text=ぴよログ" target="_blank"&gt;Twitter&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="evernote"&gt;Evernote&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;a href=&amp;#34;https://www.evernote.com/clip.action?url=https://blog.piyo.tech/&amp;amp;title=ぴよログ&amp;#34; target=&amp;#34;_blank&amp;#34;&amp;gt;Evernote&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="https://www.evernote.com/clip.action?url=https://blog.piyo.tech/&amp;title=ぴよログ" target="_blank"&gt;Evernote&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="はてなブックマーク"&gt;はてなブックマーク&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;a href=&amp;#34;http://b.hatena.ne.jp/add?mode=confirm&amp;amp;is_bm=1&amp;amp;title=ぴよログ&amp;amp;url=https://blog.piyo.tech/&amp;#34; target=&amp;#34;_blank&amp;#34;&amp;gt;はてなブックマーク&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://b.hatena.ne.jp/add?mode=confirm&amp;is_bm=1&amp;title=ぴよログ&amp;url=https://blog.piyo.tech/" target="_blank"&gt;はてなブックマーク&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="line"&gt;LINE&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;a href=&amp;#34;http://line.naver.jp/R/msg/text/?ぴよログ%0D%0Ahttps://blog.piyo.tech/&amp;#34; target=&amp;#34;_blank&amp;#34;&amp;gt;LINE&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://line.naver.jp/R/msg/text/?ぴよログ%0D%0Ahttps://blog.piyo.tech/" target="_blank"&gt;LINE&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;少しわかりづらいですが、%0D%0Aは改行を意味しています。&lt;/p&gt;
&lt;h2 id="pocket"&gt;Pocket&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;a href=&amp;#34;https://getpocket.com/save?url=https://blog.piyo.tech/&amp;amp;title=ぴよログ&amp;#34; target=&amp;#34;_blank&amp;#34;&amp;gt;Pocket&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="https://getpocket.com/save?url=https://blog.piyo.tech/&amp;title=ぴよログ" target="_blank"&gt;Pocket&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="kindle"&gt;Kindle&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;a href=&amp;#34;http://fivefilters.org/kindle-it/send.php?url=https://blog.piyo.tech/&amp;#34; target=&amp;#34;_blank&amp;#34;&amp;gt;Kindle&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://fivefilters.org/kindle-it/send.php?url=https://blog.piyo.tech/" target="_blank"&gt;Kindle&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Kindle連携は公式サービスではありません。サードパーティ製の連携サービスを使うことでKindleに文書を送ることができます。&lt;/p&gt;
&lt;h1 id="facebookでアプリ名を表示したい"&gt;Facebookでアプリ名を表示したい&lt;/h1&gt;
&lt;p&gt;Facebookアプリケーションとして登録済みであれば、「◯◯より」というようなアプリ名を表示させることもできます。前述のURLではなく別のURLを使います。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;a href=&amp;#34;https://www.facebook.com/dialog/feed?display=popup&amp;amp;app_id=xxxxxxxxxxxxxx&amp;amp;link=https://blog.piyo.tech/&amp;amp;redirect_uri=http://facebook.com/&amp;#34;
target=&amp;#34;_blank&amp;#34;&amp;gt;Facebook App&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="https://www.facebook.com/dialog/feed?display=popup&amp;app_id=xxxxxxxxxxxxxx&amp;link=https://blog.piyo.tech/&amp;redirect_uri=http://facebook.com/"
target="_blank"&gt;Facebook App&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;コード中、xxxxxxxxxxxxxxxxの部分にはアプリIDを入れます。&lt;/p&gt;</description></item><item><title>デプロイ先のサーバーでrails consoleできないときの対応とCapistranoからの使い方</title><link>https://blog.piyo.tech/posts/2013-08-28-100000/</link><pubDate>Thu, 10 Oct 2013 11:32:01 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-08-28-100000/</guid><description>&lt;p&gt;RailsアプリケーションをCapistranoでデプロイするのはよくあるやり方です。僕もその方法でサービスをデプロイしています。
ところがこの方法でデプロイしたサーバーではrails consoleがうまく動かないという問題（もしくは僕の設定不備）があることがわかりました。&lt;/p&gt;
&lt;p&gt;Railsのルートに居るにも関わらずUsageがプリントされるだけで終わってしまうのです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ cd /home/deploy/app/app_name/current
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ bin/rails console
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;Usage:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; rails new APP_PATH &lt;span style="color:#f92672"&gt;[&lt;/span&gt;options&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;Options:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; -r, &lt;span style="color:#f92672"&gt;[&lt;/span&gt;--ruby&lt;span style="color:#f92672"&gt;=&lt;/span&gt;PATH&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Path to the Ruby binary of your choice&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 以下略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;staging環境にしろproduction環境にしろ、ちょっとデータを見たかったりadmin権限をこっそり付与したりといったことはわりと多いので、rails consoleが使えないのはとても困ります。&lt;/p&gt;
&lt;p&gt;そこでいつもお世話になっているQA@ITさんに質問を投げさせてもらいました。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;a href="http://qa.atmarkit.co.jp/q/2925"&gt;AWSにデプロイしたRailsアプリケーションのコンソールを起動したいがUsageが出てしまう - QA@IT&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[http://qa.atmarkit.co.jp/q/2925:image:large]&lt;/p&gt;
&lt;p&gt;ですが、これといった回答は得られませんでした。仕方なくごまかしながら開発を進めていたのですが、ある時気がつきました。irbなりpryでRailsの環境をロードしてしまえばいいんだ！&lt;/p&gt;
&lt;h1 id="rails-console-が動かない効かない"&gt;rails console が動かない、効かない&lt;/h1&gt;
&lt;p&gt;そこでこんなスクリプトを書きましたよ。
必要なgemをrequireしてからRailsをロードし、最後にpryを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/usr/bin/env ruby&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;pathname&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;BUNDLE_GEMFILE&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;||=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;expand_path(&lt;span style="color:#e6db74"&gt;&amp;#34;../../Gemfile&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Pathname&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(__FILE__)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;realpath)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;bundler/setup&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;require &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;expand_path(&lt;span style="color:#e6db74"&gt;&amp;#39;../application&amp;#39;&lt;/span&gt;, __FILE__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Rails&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;application&lt;span style="color:#f92672"&gt;.&lt;/span&gt;require_environment!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;load &lt;span style="color:#66d9ef"&gt;Gem&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;bin_path(&lt;span style="color:#e6db74"&gt;&amp;#39;pry&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;pry&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そうしたらこんなふうに実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ cd /home/deploy/app/app_name/current
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ RAILS_ENV&lt;span style="color:#f92672"&gt;=&lt;/span&gt;production config/rails_console.rb &lt;span style="color:#75715e"&gt;# configに置くのはどうよと思いますが、まあいいんです。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;WARN&lt;span style="color:#f92672"&gt;]&lt;/span&gt; cannot load Rails console commands &lt;span style="color:#f92672"&gt;(&lt;/span&gt;Not on Rails2 or Rails3?&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt; pry&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;なんか警告が出ましたが、特に問題なく使えるので細かいことは気にしなくていいでしょう。&lt;/p&gt;
&lt;p&gt;rails consoleコマンドが動かない理由をちゃんと解明していない気持ち悪さは残りますが、本番用サーバーでもrails console相当のことを実行できるようになってストレスを軽減できるようになりました。&lt;/p&gt;
&lt;h1 id="capistranoのタスクでリモートのconsoleを立ち上げる"&gt;Capistranoのタスクでリモートのconsoleを立ち上げる&lt;/h1&gt;
&lt;p&gt;先の方法ではSSHログイン後Railsのルートへ移動し、rails_console.rbスクリプトを叩いていました。大した手順じゃないですが面倒なのでCapistranoを使ってローカルのターミナルからダイレクトに接続してしまいましょう。&lt;/p&gt;
&lt;p&gt;リモートのrails consoleを起動するためのタスクがこちらで紹介されているのでそれを流用しました。rails consoleのところをconfig/rails_console.rbにするだけですね。
&lt;a href="https://gist.github.com/benedikt/1115513"&gt;Capistrano task to open a rails console on a remote server. Require this file in your deploy.rb and run &amp;ldquo;cap rails:console&amp;rdquo;&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;namespace &lt;span style="color:#e6db74"&gt;:rails&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; task &lt;span style="color:#e6db74"&gt;:console&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:roles&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;:app&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; run_interactively &lt;span style="color:#e6db74"&gt;&amp;#34;RAILS_ENV=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;rails_env&lt;span style="color:#f92672"&gt;.&lt;/span&gt;to_s&lt;span style="color:#f92672"&gt;.&lt;/span&gt;shellescape&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;latest_release&lt;span style="color:#f92672"&gt;.&lt;/span&gt;shellescape&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/config/rails_console.rb&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;run_interactively&lt;/span&gt;(command, server&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; server &lt;span style="color:#f92672"&gt;||=&lt;/span&gt; find_servers_for_task(current_task)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;first
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; exec &lt;span style="color:#e6db74"&gt;%Q(ssh &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;server&lt;span style="color:#f92672"&gt;.&lt;/span&gt;host&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; -t &amp;#39;sudo su - &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;application&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; -c &amp;#34;cd &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;current_path&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &amp;amp;&amp;amp; &lt;/span&gt;&lt;span style="color:#e6db74"&gt;#{&lt;/span&gt;command&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#39;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;run_interactivelyではsshでリモートのコマンドを実行するために実行したいコマンドに-tオプションを付与して実行しています。&lt;/p&gt;
&lt;p&gt;これで、次のようなコマンドでconsoleにダイレクトに接続できストレスフリーです！&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ cap rails:console
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ cap production rails:console &lt;span style="color:#75715e"&gt;# multistageを使っている場合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>MySQLマスタースレーブ構成のいい加減セットアップメモ</title><link>https://blog.piyo.tech/posts/2013-07-11-100000/</link><pubDate>Thu, 10 Oct 2013 11:29:40 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-07-11-100000/</guid><description>&lt;p&gt;空のデータベースでレプリケーション構成を作るまでのプロセス案が外簡単にできたのでメモっておきます。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="設定ファイルに追記する"&gt;設定ファイルに追記する&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;log-bin = mysql-bin
server-id = 101 # 1と2を避け、1023までならOKらしい
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;server-id = 102
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="masterの情報をメモっておく"&gt;masterの情報をメモっておく&lt;/h2&gt;
&lt;p&gt;slave側で設定するために必要な情報をmasterからもらっておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-mysql" data-lang="mysql"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;mysql &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;SHOW&lt;/span&gt; MASTER STATUS;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+------------------+----------+--------------+------------------+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; File &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Position &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Binlog_Do_DB &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Binlog_Ignore_DB &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+------------------+----------+--------------+------------------+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; mysql&lt;span style="color:#f92672"&gt;-&lt;/span&gt;bin.&lt;span style="color:#ae81ff"&gt;000006&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;107&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+------------------+----------+--------------+------------------+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; row &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; sec)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここではFileとPositionが必要となります。&lt;/p&gt;
&lt;h2 id="slaveでの設定"&gt;slaveでの設定&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-mysql" data-lang="mysql"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;mysql &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;CHANGE&lt;/span&gt; MASTER &lt;span style="color:#66d9ef"&gt;TO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; MASTER_HOST&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;master-server.example.com&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; MASTER_USER&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;repl&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; MASTER_PASSWORD&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;repl_password&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; MASTER_LOG_FILE&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;mysql-bin.000006&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;# 先ほど調べたFile
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; MASTER_LOG_POS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;107&lt;/span&gt;; &lt;span style="color:#75715e"&gt;# 先ほど調べたPosition
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="同期開始"&gt;同期開始&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-mysql" data-lang="mysql"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;SLAVE START;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでレプリケーションが開始されます。
データベースやテーブルを作成して確認してみると、ちゃんと同期されていることがわかります。&lt;/p&gt;</description></item><item><title>WindowsAzureCentOSのyumで激ハマリ</title><link>https://blog.piyo.tech/posts/2013-07-05-100000/</link><pubDate>Thu, 10 Oct 2013 11:26:56 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-07-05-100000/</guid><description>&lt;p&gt;Windows Azureで提供されているOpenLogicのCentOS6.3では、VirtualBoxやAWSで動いたChefのCookbook達が全然動かなくてとても困りました。&lt;/p&gt;
&lt;h2 id="gccをインストールできない"&gt;gccをインストールできない&lt;/h2&gt;
&lt;p&gt;yumでgccをインストールするためには&lt;code&gt;kernel-headers&lt;/code&gt;が必要となります。通常のCentOSでは何も問題なくいけるのですが、設定でkernel-* が除外されているせいで依存関係を解消できず失敗します。&lt;/p&gt;
&lt;p&gt;そこで /etc/yum.confを開き、次のように変えてしまいます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;exclude=kernel* # &amp;lt;- ここを
# exclude=kernel* # &amp;lt;- このようにコメントアウトしてしまう
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これでkernel系の依存関係のせいで失敗することはなくなるはずです。&lt;/p&gt;
&lt;h2 id="依存するzlibのせいでmysql55をyumでインストールできない"&gt;依存するzlibのせいでMySQL5.5をyumでインストールできない&lt;/h2&gt;
&lt;p&gt;CentOS6.3のyumでMySQLをインストールすると5.1系がインストールされますが、yumにremiリポジトリを追加することで同様のコマンドで5.5系をインストールできるようになります。&lt;/p&gt;
&lt;p&gt;ところが、AzureのCentOS6.3では依存関係を解消できずに次のようなエラーとなってしまいます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Requires: libz.so.1(ZLIB_1.2.0)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;このOpenLogicのCent6.3に入っているzlibは1.2.3-27というバージョンなのですが、どうもこれがよくないらしいです。
というわけで、ここ&lt;a href="http://rpm.pbone.net/index.php3/stat/4/idpl/20349064/dir/centos_6/com/zlib-1.2.3-29.el6.x86_64.rpm.html"&gt;RPM CentOS 6 zlib 1.2.3 x86_64 rpm&lt;/a&gt;あたりでより新しいバージョンを探して入れてみることにしました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ sudo rpm -Uvh --force &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;ftp://ftp.muug.mb.ca/mirror/centos/6.4/os/x86_64/Packages/zlib-devel-1.2.3-29.el6.x86_64.rpm &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;ftp://ftp.muug.mb.ca/mirror/centos/6.4/os/x86_64/Packages/zlib-1.2.3-29.el6.x86_64.rpm
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こうすることでzlibが更新されremiのMySQL5.5をインストールできるようになります。&lt;/p&gt;
&lt;p&gt;これらの変更点をazureという名前でChefのクックブックを作り、再度空の環境で流して成功することを確認できました。&lt;/p&gt;</description></item><item><title>RailsでtimeとdatetimeとSQLiteとMySQLではまる</title><link>https://blog.piyo.tech/posts/2013-05-10-110000/</link><pubDate>Thu, 10 Oct 2013 11:24:17 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-05-10-110000/</guid><description>&lt;p&gt;RSSフィードを例にとって、僕がRailsを触っているときにはまったことを書いておきます。初歩かもしれんけどハマったもんは仕方ないし、Stackoverflow見てたら他にも同じような人がいるっぽかったんでちょっとまとめておきます。&lt;/p&gt;
&lt;h2 id="前置き"&gt;前置き&lt;/h2&gt;
&lt;p&gt;RSSフィードは書く記事に更新日時が入っています。新しい順に並べるのが一般的なので更新日時のカラムで並べ替えて記事を並べてあげたいとします。&lt;/p&gt;
&lt;p&gt;Entryモデルはこんな感じになっています。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# マイグレーション&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CreateEntries&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Migration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;change&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; create_table &lt;span style="color:#e6db74"&gt;:entries&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;t&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; t&lt;span style="color:#f92672"&gt;.&lt;/span&gt;string &lt;span style="color:#e6db74"&gt;:title&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; t&lt;span style="color:#f92672"&gt;.&lt;/span&gt;time &lt;span style="color:#e6db74"&gt;:published&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; t&lt;span style="color:#f92672"&gt;.&lt;/span&gt;timestamps
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# モデル&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Entry&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; default_scope {order(&lt;span style="color:#e6db74"&gt;&amp;#39;entries.published DESC&amp;#39;&lt;/span&gt;)} &lt;span style="color:#75715e"&gt;# 新しい順に&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このブログの場合はこうなって欲しいです。&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;Chef Solo 再チャレンジ まとめ&lt;/td&gt;
&lt;td&gt;2013-04-16 02:15:19 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chefでnginxを導入してみる&lt;/td&gt;
&lt;td&gt;2013-04-16 02:10:39 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chefを使ってiptablesの設定を変える&lt;/td&gt;
&lt;td&gt;2013-04-16 01:19:33 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;knifeでOPSCODEのCookbookを使う&lt;/td&gt;
&lt;td&gt;2013-04-16 01:01:07 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vagrantとchef-soloを体験してみる&lt;/td&gt;
&lt;td&gt;2013-04-15 07:52:24 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;正規表現でテキストの置換ができるwebアプリ&lt;/td&gt;
&lt;td&gt;2013-04-07 01:18:51 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NewRelicでherokuのRailsアプリケーションのパフォーマンスを測定する&lt;/td&gt;
&lt;td&gt;2013-04-04 06:26:10 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WordPressでMarkdown記法を使う&lt;/td&gt;
&lt;td&gt;2013-04-03 05:10:09 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RSpec+Spork+Guardの環境で :js =&amp;gt; trueのテストを無視する&lt;/td&gt;
&lt;td&gt;2013-03-28 13:23:04 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;カラースキームからTwitter Bootstrapのテーマを作成する&lt;/td&gt;
&lt;td&gt;2013-03-19 04:46:33 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;br /&gt;ところが、MySQLを使うproduction環境では次のようになってしまいました。&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;RSpec+Spork+Guardの環境で :js =&amp;gt; trueのテストを無視する&lt;/td&gt;
&lt;td&gt;2000-01-01 13:23:04 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vagrantとchef-soloを体験してみる&lt;/td&gt;
&lt;td&gt;2000-01-01 07:52:24 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NewRelicでherokuのRailsアプリケーションのパフォーマンスを測定する&lt;/td&gt;
&lt;td&gt;2000-01-01 06:26:10 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WordPressでMarkdown記法を使う&lt;/td&gt;
&lt;td&gt;2000-01-01 05:10:09 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;カラースキームからTwitter Bootstrapのテーマを作成する&lt;/td&gt;
&lt;td&gt;2000-01-01 04:46:33 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chef Solo 再チャレンジ まとめ&lt;/td&gt;
&lt;td&gt;2000-01-01 02:15:19 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chefでnginxを導入してみる&lt;/td&gt;
&lt;td&gt;2000-01-01 02:10:39 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chefを使ってiptablesの設定を変える&lt;/td&gt;
&lt;td&gt;2000-01-01 01:19:33 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;正規表現でテキストの置換ができるwebアプリ&lt;/td&gt;
&lt;td&gt;2000-01-01 01:18:51 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;knifeでOPSCODEのCookbookを使う&lt;/td&gt;
&lt;td&gt;2000-01-01 01:01:07 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;br /&gt;更新日時がめちゃくちゃになっているのがわかります。そのせいか並び順もおかしくなっています。&lt;/p&gt;
&lt;h2 id="確認その1-更新日時がおかしい"&gt;確認その1 更新日時がおかしい&lt;/h2&gt;
&lt;p&gt;フィードを解析して得られる日時は正しい日付が入っていることはデバッグして確認できています。データベースに入れるときにおかしくなっているのだと考えました。&lt;/p&gt;
&lt;p&gt;Rails consoleを使って次のように試してみると、、、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;entry_data &lt;span style="color:#f92672"&gt;=&lt;/span&gt; feeddata&lt;span style="color:#f92672"&gt;.&lt;/span&gt;entries&lt;span style="color:#f92672"&gt;.&lt;/span&gt;first
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;e &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Entry&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#e6db74"&gt;title&lt;/span&gt;:entry_data&lt;span style="color:#f92672"&gt;.&lt;/span&gt;title, &lt;span style="color:#e6db74"&gt;published&lt;/span&gt;:entry_data&lt;span style="color:#f92672"&gt;.&lt;/span&gt;published)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;p e&lt;span style="color:#f92672"&gt;.&lt;/span&gt;published &lt;span style="color:#75715e"&gt;# =&amp;gt; 2013-05-10 23:35:07 +0900&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;e&lt;span style="color:#f92672"&gt;.&lt;/span&gt;save
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;p e&lt;span style="color:#f92672"&gt;.&lt;/span&gt;reload&lt;span style="color:#f92672"&gt;.&lt;/span&gt;published &lt;span style="color:#75715e"&gt;# =&amp;gt; 2000-01-01 14:35:07 UTC !!! &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こんな風になってしまうのでした。
ここではそもそもtimeを使おうとしていたのが間違いでした。timeでは日付部分は保存されないのでdatetimeを使わないといけません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CreateEntries&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ActiveRecord&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Migration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;change&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; create_table &lt;span style="color:#e6db74"&gt;:entries&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;t&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; t&lt;span style="color:#f92672"&gt;.&lt;/span&gt;string &lt;span style="color:#e6db74"&gt;:title&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; t&lt;span style="color:#f92672"&gt;.&lt;/span&gt;datetime &lt;span style="color:#e6db74"&gt;:published&lt;/span&gt; &lt;span style="color:#75715e"&gt;# &amp;lt;= ここを直す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; t&lt;span style="color:#f92672"&gt;.&lt;/span&gt;timestamps
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで日付は直ります。&lt;/p&gt;
&lt;h2 id="確認その2-並び順がおかしい"&gt;確認その2 並び順がおかしい&lt;/h2&gt;
&lt;p&gt;前述のtimeを使用すると日付がおかしくなる（丸められると言ってもいいでしょう）ことは実はSQLite、MySQLともに起こります。問題というか、仕様ですかね。&lt;/p&gt;
&lt;p&gt;ところが、sqliteを使っているdevelopment環境では順番がおかしくならなかったため気がつくのが遅れました。日付がおかしくてもたまたまうまいこと欲しい順番で結果が返ってきていたというわけです。&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;Chef Solo 再チャレンジ まとめ&lt;/td&gt;
&lt;td&gt;2000-01-01 02:15:19 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chefでnginxを導入してみる&lt;/td&gt;
&lt;td&gt;2000-01-01 02:10:39 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chefを使ってiptablesの設定を変える&lt;/td&gt;
&lt;td&gt;2000-01-01 01:19:33 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;knifeでOPSCODEのCookbookを使う&lt;/td&gt;
&lt;td&gt;2000-01-01 01:01:07 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vagrantとchef-soloを体験してみる&lt;/td&gt;
&lt;td&gt;2000-01-01 07:52:24 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;正規表現でテキストの置換ができるwebアプリ&lt;/td&gt;
&lt;td&gt;2000-01-01 01:18:51 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NewRelicでherokuのRailsアプリケーションのパフォーマンスを測定する&lt;/td&gt;
&lt;td&gt;2000-01-01 06:26:10 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WordPressでMarkdown記法を使う&lt;/td&gt;
&lt;td&gt;2000-01-01 05:10:09 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RSpec+Spork+Guardの環境で :js =&amp;gt; trueのテストを無視する&lt;/td&gt;
&lt;td&gt;2000-01-01 13:23:04 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;カラースキームからTwitter Bootstrapのテーマを作成する&lt;/td&gt;
&lt;td&gt;2000-01-01 04:46:33 UTC&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;br /&gt;こんなふうに、日付はおかしいんだけど新しい順にならんでいるという。&lt;/p&gt;
&lt;p&gt;これはおそらくSQLiteの際にorderが効いていないのだと考えられます。
MySQLになったときに初めてorderが有効になった、けれどそのときに使っていたカラムの値がおかしかったので順番がめちゃくちゃに見えてしまった、というのが今回ハマったところでした。&lt;/p&gt;
&lt;p&gt;developmentとproductionのDBを揃えば住むことなので、初めからそうしたほうがいいです。身を持って経験。&lt;/p&gt;</description></item><item><title>Chef Solo入門のまとめ</title><link>https://blog.piyo.tech/posts/2013-04-16-150000/</link><pubDate>Thu, 10 Oct 2013 11:18:08 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-04-16-150000/</guid><description>&lt;p&gt;伊藤直也さんの本を購入しひと通り読みました。再チャレンジしたのでまとめてみます。&lt;/p&gt;
&lt;div class="my-4 border border-orange-300 rounded overflow-hidden hover:shadow-md"&gt;
&lt;a href="https://www.amazon.co.jp/dp/B00BSPH158/?tag=piyox-22" target="_blank" rel="noopener noreferrer" class="flex flex-row no-underline text-gray-800"&gt;
&lt;div class="flex-shrink-0 w-32 bg-white p-2 flex items-center justify-center"&gt;
&lt;img src="https://m.media-amazon.com/images/I/61kDOROXwbL._SL1500_.jpg" alt="" class="max-w-full max-h-32 object-contain" loading="lazy"&gt;
&lt;/div&gt;
&lt;div class="flex-1 p-3 overflow-hidden"&gt;
&lt;div class="font-bold text-sm mb-2"&gt;入門Chef Solo - Infrastructure as Code&lt;/div&gt;
&lt;div class="inline-block bg-orange-500 text-white text-xs py-1 px-3 rounded"&gt;
Amazonで見る
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="vagrantとchef-soloを体験してみる---ぴよログ"&gt;&lt;a href="https://blog.piyo.tech/posts/2013-04-15-100000"&gt;vagrantとchef-soloを体験してみる - ぴよログ&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;[https://blog.piyo.tech/posts/2013-04-15-100000:image:large]&lt;/p&gt;
&lt;h2 id="knifeでopscodeのcookbookを使う---ぴよログ"&gt;&lt;a href="https://blog.piyo.tech/posts/2013-04-16-120000"&gt;knifeでOPSCODEのCookbookを使う - ぴよログ&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;[https://blog.piyo.tech/posts/2013-04-16-120000:image:large]&lt;/p&gt;
&lt;h2 id="chefを使ってiptablesの設定を変える---ぴよログ"&gt;&lt;a href="https://blog.piyo.tech/posts/2013-04-16-130000"&gt;Chefを使ってiptablesの設定を変える - ぴよログ&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;[https://blog.piyo.tech/posts/2013-04-16-130000:image:large]&lt;/p&gt;
&lt;h2 id="chefでnginxを導入してみる---ぴよログ"&gt;&lt;a href="https://blog.piyo.tech/posts/2013-04-16-140000"&gt;Chefでnginxを導入してみる - ぴよログ&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;[https://blog.piyo.tech/posts/2013-04-16-140000:image:large]&lt;/p&gt;</description></item><item><title>Chefでnginxを導入してみる</title><link>https://blog.piyo.tech/posts/2013-04-16-140000/</link><pubDate>Thu, 10 Oct 2013 11:13:28 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-04-16-140000/</guid><description>&lt;p&gt;ウェブサーバーnginxをChefで入れてみました。&lt;/p&gt;
&lt;h2 id="cookbookを用意する"&gt;cookbookを用意する&lt;/h2&gt;
&lt;p&gt;knifeでcookbookを生成します。自分で管理するcookbookはsite_cookbooksに置くのが慣例のようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ cd chef-repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ knife cookbook create nginx -o site_cookbooks
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;インストールや起動、設定ファイルについてレシピに追記します。説明はコード内のコメントで。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# パッケージ管理ツールを使ってnginxをインストールします。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;package &lt;span style="color:#e6db74"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; action &lt;span style="color:#e6db74"&gt;:install&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;service &lt;span style="color:#e6db74"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# nginx がサポートしている機能を教えてあげます。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# restartとかできるよーという意味らしい。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; supports &lt;span style="color:#e6db74"&gt;status&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;restart&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;reload&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# サーバーを有効にした上で、スタートします。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 有効にしておけばマシン再起動時にも勝手にサーバーが起動します。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; action &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;:enable&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:start&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ./site_cookbooks/templates/default/nginx.conf.erbを元にして&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# nginxの設定ファイルを決まったところに置くよという指示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Chefの規約にのおかげで置き場所のパスやテンプレートファイルは省略できている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;template &lt;span style="color:#e6db74"&gt;&amp;#34;nginx.conf&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ownerとgroupはrootユーザーでパーミッションは644&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; owner &lt;span style="color:#e6db74"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; group &lt;span style="color:#e6db74"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; mode &lt;span style="color:#ae81ff"&gt;0644&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# この動作のあとでnginxを再起動してねという指示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; notifies &lt;span style="color:#e6db74"&gt;:reload&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;service[nginx]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、設定ファイルの元となるテンプレートはこちらで用意してあげないといけません。内容は入門Chef Soloを参考にしています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;user nginx;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;worker_process &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;error_log &lt;span style="color:#e6db74"&gt;/var/&lt;/span&gt;log&lt;span style="color:#f92672"&gt;/&lt;/span&gt;nginx&lt;span style="color:#f92672"&gt;/&lt;/span&gt;error&lt;span style="color:#f92672"&gt;.&lt;/span&gt;log;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;pid &lt;span style="color:#e6db74"&gt;/var/&lt;/span&gt;run&lt;span style="color:#f92672"&gt;/&lt;/span&gt;nginx&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pid;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;events {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; worker_connections &lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;http {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;include&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/etc/n&lt;/span&gt;ginx&lt;span style="color:#f92672"&gt;/&lt;/span&gt;mim&lt;span style="color:#f92672"&gt;.&lt;/span&gt;types;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; default_type application&lt;span style="color:#f92672"&gt;/&lt;/span&gt;octet&lt;span style="color:#f92672"&gt;-&lt;/span&gt;stream;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; server {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; listen &lt;span style="color:#f92672"&gt;&amp;lt;%=&lt;/span&gt; node&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;][&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;port&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;%&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; server_name centos&lt;span style="color:#f92672"&gt;-&lt;/span&gt;one;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; location &lt;span style="color:#f92672"&gt;/&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; root &lt;span style="color:#e6db74"&gt;/usr/s&lt;/span&gt;hare&lt;span style="color:#f92672"&gt;/&lt;/span&gt;nginx&lt;span style="color:#f92672"&gt;/&lt;/span&gt;html;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; index index&lt;span style="color:#f92672"&gt;.&lt;/span&gt;html index&lt;span style="color:#f92672"&gt;.&lt;/span&gt;htm;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;設定ファイル内部に一箇所だけ変数のようなものがあります。確かChefではAttributeというはず、、、&lt;/p&gt;
&lt;p&gt;これはjsonファイルで設定してあげないといけません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;port&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;run_list&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;iptables&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このファイルのjsonがハッシュとなってerbファイルで使うことができるようですね。なので上のように書いておけば、さきほどの設定ファイルテンプレートでnode[&amp;ldquo;nginx&amp;rdquo;][&amp;ldquo;port&amp;rdquo;]のようにして使うことができる、というわけ。今回はポートを80番にしています。&lt;/p&gt;
&lt;p&gt;そのぐらいならAttributeを使うまでもないですが、IPやホスト名を環境によってに変更したいときなどに使えそうです。&lt;/p&gt;
&lt;h2 id="chefを実行"&gt;Chefを実行&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ cd chef-repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ knife solo cook vagrant@192.168.33.10
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ところが失敗するはずです。これはcookbookに問題があったわけではなく、CentOSで使われているパッケージ管理yumのリポジトリの設定不足が原因です。nginxは初期設定に入っているリポジトリには含まれないです。&lt;/p&gt;
&lt;h2 id="yumの設定"&gt;yumの設定&lt;/h2&gt;
&lt;p&gt;yumのリポジトリを追加するのもChefを使ってやります。手動設定はダメです。yumのcookbookはOPSCODEのものを使うことにします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ cd chef-repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ knife cookbook site vendor yum
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これによりいくつかのレシピが導入されます。あとはjsonファイルを次のように変更して…&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;post&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;run_list&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;yum::epel&amp;#34;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// ←追加
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;iptables&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;さきほどと同じようにChefを流してみるとnginxのインストールが無事完了すると思います。&lt;/p&gt;
&lt;h2 id="nginxの動作確認"&gt;nginxの動作確認&lt;/h2&gt;
&lt;p&gt;動作確認のためホストOS側のブラウザでアクセスしてみましょう。http://192.168.33.10/ にアクセスしてnginxのデモページが表示されていれば完了です。&lt;/p&gt;</description></item><item><title>Chefを使ってiptablesの設定を変える</title><link>https://blog.piyo.tech/posts/2013-04-16-130000/</link><pubDate>Thu, 10 Oct 2013 11:10:53 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-04-16-130000/</guid><description>&lt;p&gt;CentOS6.3の初期状態ではiptablesによりlocalhost以外からのアクセスを弾くような設定になっています。Chefを使ってVMにWebサーバーを入れてもホストOSから確認できなくて困りました。&lt;/p&gt;
&lt;p&gt;入門Chef Soloでは「VMだからiptables切っちゃえばいいよ」と書いてありましたが、せっかくだからChefでやる方法を探しました。&lt;/p&gt;
&lt;h2 id="opscodeのcookbookを使う"&gt;OPSCODEのcookbookを使う&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://community.opscode.com/cookbooks"&gt;Opscode Community&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[http://community.opscode.com/cookbooks:image:large]&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;OPSCODEのコミュニティで色々なcookbookが公開されています。よくあるサーバーの設定はほとんど見つかります。とは言ってもブラックボックスすぎてわけわからなくなるので、Chefに慣れるまではなるべく自分で書いたほうがよさそうです。naoya氏がそう言ってます。&lt;/p&gt;
&lt;p&gt;でもiptableぐらいはいいよね？ファイル書き換えるだけだし。と判断し、公開されているcookbookを使いました。&lt;/p&gt;
&lt;p&gt;使うための準備はこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.piyo.tech/posts/2013-04-16-120000"&gt;knifeでOPSCODEのCookbookを使う - ぴよログ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[https://blog.piyo.tech/posts/2013-04-16-120000:image:large]&lt;/p&gt;
&lt;h2 id="手順"&gt;手順&lt;/h2&gt;
&lt;p&gt;とにかくダウンロード。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ cd chef-repo
$ knife cookbook site vendor iptables
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;./cookbooks/iptables として配置されます。&lt;/p&gt;
&lt;p&gt;HTTPとSSHを許可するため、次のような設定が必要です。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# HTTP
-A FWR -m tcp -p tcp --dport 80 -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;# SSH
-A FWR -m tcp -p tcp --dport 22 -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;iptables_rule &lt;span style="color:#e6db74"&gt;&amp;#34;all_established&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;iptables_rule &lt;span style="color:#e6db74"&gt;&amp;#34;all_icmp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;iptables_rule &lt;span style="color:#e6db74"&gt;&amp;#34;http&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# これと&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;iptables_rule &lt;span style="color:#e6db74"&gt;&amp;#34;ssh&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# この2行を追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;対象のノード（今回はvagrantのVM）のjsonファイルを書き換え。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;run_list&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;iptables&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでChefを流せばiptablesの設定が変わり、ウェブサーバーの動作確認などができるようになります！&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ knife solo cook vagrant@192.168.33.10
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>knifeでOPSCODEのCookbookを使う</title><link>https://blog.piyo.tech/posts/2013-04-16-120000/</link><pubDate>Thu, 10 Oct 2013 11:08:32 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-04-16-120000/</guid><description>&lt;p&gt;OPSCODEのCookbookはknifeで自動取得して使うことができます。自分でダウンロードしてChefリポジトリに配置してもいいみたいですが、せっかくなので自動でやってみます。&lt;/p&gt;
&lt;h2 id="private_keyを取得"&gt;private_keyを取得&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://community.opscode.com/cookbooks" target="_blank"&gt;Opscode Community&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このリンクからOPSCODEに飛んで、右上のSing Upから登録できます。有料版の案内が出てビビリますがちょっとだけ下にFree Trialがあるのでそちらを。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/x/xoyip/20131010/20131010110700.png" alt=""&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;アカウントが完了したら自身のユーザーページからプライベートキーをダウンロードできます。username.pemというような名前のファイルです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/x/xoyip/20131010/20131010110706.png" alt=""&gt;
&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/x/xoyip/20131010/20131010110711.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="kniferbの設定"&gt;knife.rbの設定&lt;/h2&gt;
&lt;p&gt;さきほどダウンロードしたファイルを任意の場所に置きます。わかりやすさのために ~/.chef/に置くのがよさそうです。&lt;/p&gt;
&lt;p&gt;パーミッションも変更します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ chmod &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt; ~/.chef/username.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;続いて~/.chef/knife.rbを編集します。このファイルはknife configureしたときにできるもので、各種設定が書かれています。&lt;/p&gt;
&lt;p&gt;このファイルを編集してこんなふうにします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;client_key &lt;span style="color:#e6db74"&gt;&amp;#39;/Users/username/.chef/username.pem&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;cookbook_path &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;./cookbooks&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;knifeによる自動取得はChefリポジトリのルートディレクトリで行います。2行目のcookbook_pathはそのときに取ってきたCookbookをどこに配置するかを指示していて、./cookbooksとしておくことでいい感じの場所に配置されるようにしてあげています。&lt;/p&gt;
&lt;h2 id="自動取得のやりかた"&gt;自動取得のやりかた&lt;/h2&gt;
&lt;p&gt;Chefリポジトリでコマンドを実行します。&lt;/p&gt;
&lt;p&gt;が、knifeによる自動取得ではgitにコミットするところまでを自動で行うらしいので、そもそもChefリポジトリがgitで管理されていないといけないみたいです。またワーキングツリーに変更がある状態だと何もしてくれないらしい。&lt;/p&gt;
&lt;p&gt;まだgit管理していなければ、git init → add → commitします。&lt;/p&gt;
&lt;p&gt;あとはこんな風に実行すればいいです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ knife cookbook site vendor apache2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;git log してみると勝手にコミットまで済んでいるのがわかります。あとは必要に応じて設定すればおーけー。でも設定がブラックボックスすぎてよくわからない。&lt;/p&gt;</description></item><item><title>VagrantとChef Soloの超入門</title><link>https://blog.piyo.tech/posts/2013-04-15-100000/</link><pubDate>Thu, 10 Oct 2013 11:04:02 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-04-15-100000/</guid><description>&lt;p&gt;Vagrant、Chefあたりが気になったので初めて使ってみました。どういうことができるのかわかりませんが使いながら探ってみたいと思います。そんな程度の知識しかないので書いている内容や解釈に間違いがある可能性があります。&lt;/p&gt;
&lt;h2 id="vagrant"&gt;vagrant&lt;/h2&gt;
&lt;p&gt;vagrant、多分読みはベイグラント。VirtualBoxの仮想マシンをコマンドラインから作成・起動したり、ログインしたりすることできるツールのようです。naoya氏のエントリーで存在を知りました。&lt;/p&gt;
&lt;h3 id="インストール"&gt;インストール&lt;/h3&gt;
&lt;p&gt;1.1系からはgemで管理できなくなったらしいので、ここからdmgを拾ってきてインストールしました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://downloads.vagrantup.com/tags/v1.1.5"&gt;Vagrant - Downloads&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="初期化から起動まで"&gt;初期化から起動まで&lt;/h3&gt;
&lt;p&gt;仮想マシンを生成するためのテンプレートのようなものを指定することで仮想マシンをサクっと作ることができるみたいですね。ここでいろいろ選ぶことができます。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.vagrantbox.es/"&gt;A list of base boxes for Vagrant - Vagrantbox.es&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ vagrant box add タイトル 選んだBoxのURL
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ vagrant init 上で指定したタイトル
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ vagrant up
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;$ vagrant ssh &lt;span style="color:#75715e"&gt;# ログイン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="普通にsshできるようにしてみる"&gt;普通にSSHできるようにしてみる&lt;/h3&gt;
&lt;p&gt;このあとchef関係のセットアップのところでsshを使った処理が走るので、vagrant sshではなく、sshコマンドでログインできるようにしておくといいです。&lt;/p&gt;
&lt;p&gt;Vagrantfileに次の一行を追加してブリッジ接続を有効にします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;network &lt;span style="color:#e6db74"&gt;:private_network&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;ip&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;192.168.33.10&amp;#34;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;←コメントをはずす&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こうすることでVMにLANのIPが振られます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ vagrant reload
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ vagrant ssh
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;vagrant@localhost ~&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ ifconfig
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;192.168.xxx.yyyというIPがあるはずなので控えておきます。&lt;/p&gt;
&lt;p&gt;ログインのためのキーファイルが~/.vagrand.d/insecure_private_keyにあるのでそれを指定すればsshログインができます。毎回ファイルを指定するのは面倒なので~/.ssh/configに設定を書いておくと楽。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;Host 192.168.xxx.*
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; IdentityFile ~/.vagrand.d/insecure_private_key
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで次のコマンドを叩けばログインできるようになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ ssh vagrant@192.168.xxx.yyy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="その他"&gt;その他&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ vagrant halt &lt;span style="color:#75715e"&gt;# 仮想マシン停止&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ vagrant destroy &lt;span style="color:#75715e"&gt;# 仮想マシンを削除？&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;$ vagrant status &lt;span style="color:#75715e"&gt;# 仮想マシンの状態を見る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;他にもサンドボックスモードや複製などいろいろできるみたいですね。
強力だわ。&lt;/p&gt;
&lt;h2 id="chef"&gt;Chef&lt;/h2&gt;
&lt;p&gt;環境構築とかを自動で流せるものだという認識です。&lt;/p&gt;
&lt;h3 id="インストール-1"&gt;インストール&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ gem install chef
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ruby-200での注意"&gt;Ruby 2.0.0での注意&lt;/h3&gt;
&lt;p&gt;Ruby2ではchef-soloが動きません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ chef-solo -v
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;Users/hiromasa/.rbenv/versions/2.0.0-p0/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;require&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;: cannot load such file -- rubygems/format &lt;span style="color:#f92672"&gt;(&lt;/span&gt;LoadError&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ruby 2.0.0系からrubygemsディレクトリの中にformat.rbがなくなったみたいです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;~/.rbenv/versions/2.0.0-p0&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;$ find . -name format.rb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;./lib/ruby/2.0.0/date/format.rb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;./lib/ruby/gems/2.0.0/gems/activemodel-3.2.13/lib/active_model/validations/format.rb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;./lib/ruby/gems/2.0.0/gems/activemodel-4.0.0.beta1/lib/active_model/validations/format.rb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;~/.rbenv/versions/1.9.3-p374&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;$ find . -name format.rb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;./lib/ruby/1.9.1/date/format.rb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;./lib/ruby/1.9.1/rubygems/format.rb &lt;span style="color:#75715e"&gt;# ← こいつがない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;./lib/ruby/gems/1.9.1/gems/activemodel-3.2.1/lib/active_model/validations/format.rb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;./lib/ruby/gems/1.9.1/gems/activemodel-3.2.11/lib/active_model/validations/format.rb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;./lib/ruby/gems/1.9.1/gems/activemodel-3.2.12/lib/active_model/validations/format.rb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;./lib/ruby/gems/1.9.1/gems/activemodel-3.2.13/lib/active_model/validations/format.rb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;./lib/ruby/gems/1.9.1/gems/activemodel-3.2.8/lib/active_model/validations/format.rb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;~/.rbenv/versions/2.0.0-p0/lib/ruby/2.0.0/rubygems/format.rb という空のダミーファイルを作ることでchef-soloのエラーを回避できます。&lt;/p&gt;
&lt;h3 id="vm上でchef-soloが動くようにする"&gt;VM上でchef-soloが動くようにする&lt;/h3&gt;
&lt;p&gt;knife-soloというものを使うらしい。&lt;/p&gt;
&lt;p&gt;knife-soloをインストールし、初期化しておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ gem install knife-solo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ knife configure &lt;span style="color:#75715e"&gt;# 質問にはデフォルトで答えておけば大丈夫&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;対象のVMを起動しておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ vagrant up
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;VMのアドレスをしてknifeによるセットアップを行います。これでVM上でchef-soloを実行できるようになるらしいです。まじかよ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;$ knife solo init chef-repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;$ cd chef-repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;$ knife solo prepare vagrant@192.168.33.10
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;Bootstrapping Chef...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; % Total % Received % Xferd Average Speed Time Time Time Current
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; Dload Upload Total Spent Left Speed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;101&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6471&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;101&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6471&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6483&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; --:--:-- --:--:-- --:--:-- &lt;span style="color:#ae81ff"&gt;38289&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;Downloading Chef &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; el...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;Installing Chef
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;warning: /tmp/tmp.zYlbwTed/chef-.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;Preparing... &lt;span style="color:#75715e"&gt;########################################### [100%]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; 1:chef &lt;span style="color:#75715e"&gt;########################################### [100%]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;Thank you &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; installing Chef!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;Generating node config &lt;span style="color:#e6db74"&gt;&amp;#39;nodes/192.168.24.71.json&amp;#39;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="vmにrecipeを適用"&gt;VMにRecipeを適用！&lt;/h3&gt;
&lt;p&gt;helloという名前でレシピを新規作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# さっき作ったchef-repoにいるとする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;$ knife cookbook create hello -o cookbooks
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;cookbooks/hello/recipes/default.rbを編集します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;package &lt;span style="color:#e6db74"&gt;&amp;#34;apache2&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt; action &lt;span style="color:#e6db74"&gt;:install&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;package &lt;span style="color:#e6db74"&gt;&amp;#34;apache2&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt; action &lt;span style="color:#e6db74"&gt;:start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;さらにnodes/192.168.33.10.jsonを編集します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;run_list&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;recipe[hello]&amp;#34;&lt;/span&gt;]}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとは実行！&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ knife solo cook vagrant@192.168.33.10
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;VMに入ってみるとどうやらapacheが入ったっぽいですね。早速ブラウザで192.168.33.10にアクセスしてみると……あれ？表示されません。&lt;/p&gt;
&lt;h3 id="諦める"&gt;諦める&lt;/h3&gt;
&lt;p&gt;どうやらiptablesで弾かれているみたいでした。
このあといろいろ試しましたがなかなかhtmlを表示させるところまでいけない。疲れたからとりあえず断念。多分chefのせいではなさそうなんだけど。&lt;/p&gt;
&lt;p&gt;とはいえ、いろいろ良くわからないのでnaoyaさんのchef本は購入しておきました。&lt;/p&gt;
&lt;h2 id="参考"&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://d.hatena.ne.jp/naoya/20130205/1360062070"&gt;Vagrant - naoyaのはてなダイアリー&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://kray.jp/blog/learning-chef/"&gt;Vagrantとchef-soloでお気楽環境構築 | KRAY Inc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://st63jun.hatenablog.jp/entry/2012/10/11/003011"&gt;chef-solo と knife-solo を使う - ああああ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Rubyの正規表現でテキストの置換ができるWebサイト</title><link>https://blog.piyo.tech/posts/2013-04-07-100000/</link><pubDate>Thu, 10 Oct 2013 10:57:11 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-04-07-100000/</guid><description>&lt;p&gt;自分用にテキストの置換ができるwebサービスを作りました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://regex-replace.herokuapp.com/"&gt;Regex Replace&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="背景"&gt;背景&lt;/h2&gt;
&lt;p&gt;正規表現による文字列置換なんかはエディタを使うべきところなのですが、普段からつかっているEmacsの正規表現が使い勝手がとても悪いというのがそもそもの原因です。 Emacsの正規表現はバックスラッシュのせいでかなり複雑になります。すごくがんばっても置換したい文字列にマッチしないということが多々あるんですが、この間もそのようなことがあってついに爆発しました。そして、もう自分で作るわーとおもいました。&lt;/p&gt;
&lt;h2 id="仕様"&gt;仕様&lt;/h2&gt;
&lt;p&gt;画面左のフォームに正規表現と置換に使う文字列、置換をかけたい文字列を入力するとリアルタイムに置換を実行しマッチ箇所と置換後の文字列を右側に表示します。マッチ箇所や置換箇所は強調表示されるようになっており、結果を見ながら正規表現を組み立てていくことが可能です。&lt;/p&gt;
&lt;p&gt;実装はRails3で行なっています→&lt;a href="https://github.com/pi-chan/regex-replace"&gt;pi-chan/regex-replace&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この程度のアプリにRailsを使うのはオーバースペックとは思いますが、、まあ、細かいことを気にしないためですね。&lt;/p&gt;
&lt;h2 id="jqueryjavascriptわからん"&gt;jQuery（javascript）わからん&lt;/h2&gt;
&lt;p&gt;置換結果をリアルタイムに更新するためにテキストフィールドへの入力イベントなどを受け取ってRailsとやり取りするようにしています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-coffee" data-lang="coffee"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;Request_waiting = &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;#form&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;ajax:success&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;(e, data, status, xhr)-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; request_waiting = &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;#match-result&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;#input-text-preview&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;match&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;update = &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;request_waiting&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;#form&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;submit&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; request_waiting = &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;#regex_form&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;keyup change&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;update&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;#replace_form&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;keyup change&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;update&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;#input_text_form&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;keyup chagne&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;update&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;テキストフィールドのkeyup、changeのたびにupdate関数を呼び出し、update関数ではformのsubmitを呼んでいます。 そしてformのsubmitでRailsのControllerにAjaxリクエストを投げるという感じにしました。&lt;/p&gt;
&lt;p&gt;このやり方だけだとAjaxのリクエストが頻繁に走りすぎてちょっと重いです。 これを1秒に何回までとかそういうふうに制御できたらいいなと思うんですがどのように実装すればいいのかわかりませんでしたので適当なフラグを使ってやってみました。効果があるのかどうかはわかりません。&lt;/p&gt;
&lt;p&gt;こういう場合のベストプラクティスはどんな感じなんでしょうかね。。。&lt;/p&gt;</description></item><item><title>RSpecでjavascriptのテストを除外する設定</title><link>https://blog.piyo.tech/posts/2013-03-28-100000/</link><pubDate>Thu, 10 Oct 2013 10:52:00 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-03-28-100000/</guid><description>&lt;p&gt;実験的にRailsの開発をしています。railstutorialをひと通りやったこともあってRSpecを使った画面遷移のテストを書いたりもしてみています。&lt;/p&gt;
&lt;p&gt;railstutorialをやりながら思ったのはテストおせえええってことです。なのでSporkを使います。&lt;/p&gt;
&lt;p&gt;Sporkを使うとテストサーバーみたいなのが立ち上がってテストの実行がめちゃくちゃ早くなります。雰囲気5倍から10倍ぐらい。&lt;/p&gt;
&lt;p&gt;でも、テスト書き換えたりロジック書き換えたりしたらSporkの再起動が必要だったりします。それじゃあいくらテストが早くても意味ないですよね。（もしかしたら設定が悪かっただけかも…？）&lt;/p&gt;
&lt;p&gt;そこでGuardを使います。Guardではファイルの変更を監視していて、変更があったファイルのテストだけをしてくれます。Sporkのときと同じぐらい早いですし、変更分だけテストが走るのでさらに楽です。RSpecでもオプションで選べますけどね。。。&lt;/p&gt;
&lt;p&gt;そういったもろもろの設定はこちらから丸々いただきました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qiita.com/bojovs/items/6c6e00691be247e6fcd2"&gt;RSpec, Capybara, factory_girl, Spork, GuardでGrowlなRailsテスト環境を作る - Qiita [キータ]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[http://qiita.com/bojovs/items/6c6e00691be247e6fcd2:image:large]&lt;/p&gt;
&lt;p&gt;Growlなんかも使ったりして、通知が来て便利です。最近Growl有料化したんだよね…&lt;/p&gt;
&lt;h2 id="javascriptを使ったテストを除外する"&gt;Javascriptを使ったテストを除外する&lt;/h2&gt;
&lt;p&gt;やっと本題です。HTMLのformを使わずにPOSTする、みたいなことをJavascriptを使って実現しているのですが、テストに使っているCapybaraではそういったテストは普通はできません。なので、:js =&amp;gt; true なるオプションをつけてJavascriptのことも考えてテストしてねと教えてあげるわけです。&lt;/p&gt;
&lt;p&gt;そうするとブラウザ（デフォルトではFirefox）が立ち上がって、操作したまんまをテストしてくれます。そしてその分遅い。&lt;/p&gt;
&lt;p&gt;Guardが監視してくれてるおかげでテストが捗るのはいいんですが、jsのテストを含むファイルを頻繁に編集→保存するたびに立ち上がるFirefoxはとても邪魔です。Guard落とそうかと思うぐらいです。&lt;/p&gt;
&lt;p&gt;と思ったらjsのテストを除外する方法がありました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;$ rspec -t ‘~js’
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;だけどこれだとSpork使ったとき（つまり通常の運用中）には有効にならないっぽいんです。&lt;/p&gt;
&lt;p&gt;困りましたが、なんとかしました。&lt;/p&gt;
&lt;p&gt;先ほどのQiitaの記事でGuardfileなるものを作ったと思います。そこにRSpecに渡している –drbオプションがありました。そこにjsを除外するオプションもつけてしまえ！と変更したらまんまとうまくいきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ここを&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;guard &lt;span style="color:#e6db74"&gt;&amp;#39;rspec&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:version&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:cli&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;--drb&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:all_after_pass&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:all_on_start&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# こうした&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;guard &lt;span style="color:#e6db74"&gt;&amp;#39;rspec&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:version&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:cli&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;--drb -t &amp;#39;~js&amp;#39;&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:all_after_pass&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:all_on_start&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでGuard監視による自動テストではjs無視、手動テストではjsもテストという環境ができました。&lt;/p&gt;</description></item><item><title>Bootstrapのテンプレートを作れるサービス</title><link>https://blog.piyo.tech/posts/2013-03-19-100000/</link><pubDate>Thu, 10 Oct 2013 10:41:46 +0900</pubDate><guid>https://blog.piyo.tech/posts/2013-03-19-100000/</guid><description>&lt;p&gt;エンジニアの僕にとってアプリやWebサイトなどの配色は悩みのタネです。とはいえ多少見た目を良くしたいと思って適当な色を選んでました。こんな感じにしたらかっこいいんじゃね？みたいな。それで、確かに自分ではかっこいいと思ったりするけど、一般的にはイマイチだったり。&lt;/p&gt;
&lt;p&gt;今日もそんなことを考えていたら、以前こんな記事を見たのを思い出しました。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://takahashifumiki.com/web/design/2312/"&gt;色彩センスのない人がそれなりのWebサイトを作るための秘訣3つ | 高橋文樹.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[http://takahashifumiki.com/web/design/2312/:image:large]&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;くれぐれも自分で工夫して「B2Bのサイトだから真面目で洗練した雰囲気を出すために青とグレーを基調にして〜」とか考えないでください。それが間違いの元です。「どんなにしょぼくてもプロがいいといっているんだから自分がやるよりはマシだろう」ぐらいの感覚で選んでください。自由が一番苦しいのです。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;耳が痛いよ。&lt;/p&gt;
&lt;p&gt;Kulerというサービスでカラースキームを選んでその色だけを使えってことらしいです。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://kuler.adobe.com/explore/newest/"&gt;Explore | All Themes - Adobe Kuler&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;話は戻って、RailsでTwitter Bootstrapを使っていて、もう少し配色を変えたいと考えていたところでした。
KulerのカラースキームでBootstrapのテーマを作りたいなー、でも面倒かなーなんて思っていたら、そういうサービスがありました。ありがたいです。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://paintstrap.com/ja/"&gt;PaintStrap - Twitter Bootstrapテーマをカラースキームから生成&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[http://paintstrap.com/ja/:image:large]&lt;/p&gt;
&lt;p&gt;カラースキームのIDを入れると、カラースキームに含まれる色からテーマを作ることができます。
色をどのように使うか、多少のカスタムができるのでいくつか試せばちょうどいいのが見つかるはずです。&lt;/p&gt;
&lt;p&gt;Kulerだけではなく、COLOURloversというのにも対応しています。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.colourlovers.com/browse"&gt;Browse :: COLOURlovers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[http://www.colourlovers.com/browse:image:large]&lt;/p&gt;</description></item></channel></rss>