<?xml version="1.0" encoding="utf-8"?><rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Rochefort.dev</title><link>https://www.rochefort.dev/</link><description>MemE is a powerful and highly customizable GoHugo theme for personal blogs.</description><generator>Hugo 0.87.0 https://gohugo.io/</generator><language>en</language><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><lastBuildDate>Tue, 17 Sep 2024 12:10:36 +0000</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://www.rochefort.dev/rss.xml"/><item><title>New RelicをRailsアプリにinstallしてみる</title><link>https://www.rochefort.dev/posts/install_new_relic_to_rails_app/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/install_new_relic_to_rails_app/</guid><pubDate>Sat, 18 Dec 2021 07:00:00 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>&lt;a href="https://newrelic.com/">New Relic&lt;/a> といえば、
Application Performance Management (APM) の代表ツール。&lt;br>
無料でそこそこ使えますし、見た目もかっこよくなっていたので、久しぶりにinstallしてみました。&lt;/p>
&lt;h2 id="installation">Installation&lt;/h2>
&lt;p>sing inして、「add data」ボタンを押せば、入力画面が表示されるので&lt;br>
それに従って操作するだけです。&lt;br>
&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20211217/20211217231506_original.png" width=600/>&lt;/p>
&lt;pre>&lt;code>1. Give your application a name
任意のapplication名入れればok
2. Are you using Bundler
bundler使ってるので、gem指定して、bundle installでok
3. Download your custom configuration
Railsだとconfig以下に`newrelic.yml`が必要ですが、これもdownloadして配置するだけ。
（license_keyの記載があるので、git repositoryには含まないようにしています）
4. Restart your application
deployすればok
5. Check for data
あとは見るだけ
&lt;/code>&lt;/pre>&lt;h3 id="とまぁ簡単でした">と、まぁ簡単でした。&lt;/h3>
&lt;p>冒頭の画像のようになります。&lt;br>
ぱっと見PostgreSQLのところが遅いのでなんとかしようかと検討中。&lt;/p></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/newrelic/">NewRelic</category><category domain="https://www.rochefort.dev/tags/rails/">Rails</category></item><item><title>[Rails便利機能]ActiveSupport::OrderedOptions</title><link>https://www.rochefort.dev/posts/rails_active_support_orderd_options/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/rails_active_support_orderd_options/</guid><pubDate>Fri, 26 Nov 2021 22:00:00 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>Hashの要素をメソッドっぽく取得できるやつです。
ググってソースを見ていたら、改めて発見があったのでメモしておきます。&lt;/p>
&lt;h2 id="activesupportorderedoptions">ActiveSupport::OrderedOptions&lt;/h2>
&lt;p>実装も非常にsimpleです。&lt;/p>
&lt;h3 id="-と-">&lt;code>#[]=&lt;/code> と &lt;code>#[]&lt;/code>&lt;/h3>
&lt;p>&lt;a href="https://github.com/rails/rails/blob/v6.1.4.1/activesupport/lib/active_support/ordered_options.rb">rails/ordered_options.rb&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ruby" data-lang="ruby"> &lt;span style="color:#000;font-weight:bold">class&lt;/span> &lt;span style="color:#458;font-weight:bold">OrderedOptions&lt;/span> &lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span> &lt;span style="color:#008080">Hash&lt;/span>
alias_method &lt;span style="color:#990073">:_get&lt;/span>, &lt;span style="color:#990073">:[]&lt;/span> &lt;span style="color:#998;font-style:italic"># preserve the original #[] method&lt;/span>
&lt;span style="color:#000;font-weight:bold">protected&lt;/span> &lt;span style="color:#990073">:_get&lt;/span> &lt;span style="color:#998;font-style:italic"># make it protected&lt;/span>
&lt;span style="color:#000;font-weight:bold">def&lt;/span> &lt;span style="color:#900;font-weight:bold">[]=&lt;/span>(key, value)
&lt;span style="color:#000;font-weight:bold">super&lt;/span>(key&lt;span style="color:#000;font-weight:bold">.&lt;/span>to_sym, value)
&lt;span style="color:#000;font-weight:bold">end&lt;/span>
&lt;span style="color:#000;font-weight:bold">def&lt;/span> &lt;span style="color:#900;font-weight:bold">[]&lt;/span>(key)
&lt;span style="color:#000;font-weight:bold">super&lt;/span>(key&lt;span style="color:#000;font-weight:bold">.&lt;/span>to_sym)
&lt;span style="color:#000;font-weight:bold">end&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Hashを継承し、&lt;code>#[]=&lt;/code> と &lt;code>#[]&lt;/code> でsymbolを使って値のセットと取得を行うようにしています。
ちなみに、&lt;code>_get&lt;/code> はパフォーマンス面で優位な元のHashの方を残しているようです。&lt;/p>
&lt;h3 id="method_missing">method_missing&lt;/h3>
&lt;p>method_missingを利用して、&lt;code>.&lt;/code>でアクセスできるようにしています。&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ruby" data-lang="ruby"> &lt;span style="color:#000;font-weight:bold">def&lt;/span> &lt;span style="color:#900;font-weight:bold">method_missing&lt;/span>(&lt;span style="color:#0086b3">name&lt;/span>, &lt;span style="color:#000;font-weight:bold">*&lt;/span>args)
name_string &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000;font-weight:bold">+&lt;/span>&lt;span style="color:#0086b3">name&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>to_s
&lt;span style="color:#000;font-weight:bold">if&lt;/span> name_string&lt;span style="color:#000;font-weight:bold">.&lt;/span>chomp!(&lt;span style="color:#d14">&amp;#34;=&amp;#34;&lt;/span>)
&lt;span style="color:#0086b3">self&lt;/span>&lt;span style="color:#000;font-weight:bold">[&lt;/span>name_string&lt;span style="color:#000;font-weight:bold">]&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> args&lt;span style="color:#000;font-weight:bold">.&lt;/span>first
&lt;span style="color:#000;font-weight:bold">else&lt;/span>
bangs &lt;span style="color:#000;font-weight:bold">=&lt;/span> name_string&lt;span style="color:#000;font-weight:bold">.&lt;/span>chomp!(&lt;span style="color:#d14">&amp;#34;!&amp;#34;&lt;/span>)
&lt;span style="color:#000;font-weight:bold">if&lt;/span> bangs
&lt;span style="color:#0086b3">self&lt;/span>&lt;span style="color:#000;font-weight:bold">[&lt;/span>name_string&lt;span style="color:#000;font-weight:bold">].&lt;/span>presence &lt;span style="color:#000;font-weight:bold">||&lt;/span> &lt;span style="color:#000;font-weight:bold">raise&lt;/span>(&lt;span style="color:#008080">KeyError&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>new(&lt;span style="color:#d14">&amp;#34;:&lt;/span>&lt;span style="color:#d14">#{&lt;/span>name_string&lt;span style="color:#d14">}&lt;/span>&lt;span style="color:#d14"> is blank&amp;#34;&lt;/span>))
&lt;span style="color:#000;font-weight:bold">else&lt;/span>
&lt;span style="color:#0086b3">self&lt;/span>&lt;span style="color:#000;font-weight:bold">[&lt;/span>name_string&lt;span style="color:#000;font-weight:bold">]&lt;/span>
&lt;span style="color:#000;font-weight:bold">end&lt;/span>
&lt;span style="color:#000;font-weight:bold">end&lt;/span>
&lt;span style="color:#000;font-weight:bold">end&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;code>=&lt;/code>のロジックはsimpleですが、&lt;code>!&lt;/code>のロジックが一瞬分からなかったので、履歴を見て見ると
&lt;code>!&lt;/code>付きでアクセスした場合、KeyError を発生させたい（そうすることで短くかけるケースがある）
ための実装のようでした。
&lt;a href="https://github.com/rails/rails/commit/e768c519fb6015e00961702a5165c6dab548a954">Add bang version to OrderedOptions · rails/rails@e768c51&lt;/a>&lt;/p>
&lt;p>まぁ、分からんでもないが、この存在に気づいている人は少ないかもしれません。&lt;/p>
&lt;h3 id="string">&lt;code>String#+&lt;/code>&lt;/h3>
&lt;p>もうひとつ、よく分からない実装がありました。&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ruby" data-lang="ruby">name_string &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000;font-weight:bold">+&lt;/span>&lt;span style="color:#0086b3">name&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>to_s
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>この&lt;code>+&lt;/code>は一体なんだろうと調べてみると、以下に記載がありました。&lt;br>
&lt;a href="https://docs.ruby-lang.org/ja/latest/method/String/i/=2b=40.html">String#+@ (Ruby 3.0.0 リファレンスマニュアル)&lt;/a>&lt;/p>
&lt;p>frozen textを考慮した実装のようで、frozen（immutable）な文字列が渡ってきても、&lt;code>chomp!&lt;/code> するためにunfrozenな文字列として処理しているようです。&lt;/p>
&lt;h2 id="activesupportinheritableoptions">ActiveSupport::InheritableOptions&lt;/h2>
&lt;p>もう一つ便利な機能としては、同じファイルに記載されている、既存のhashをOrderedOptionsに変換するクラス。&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ruby" data-lang="ruby">h &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#008080">ActiveSupport&lt;/span>&lt;span style="color:#000;font-weight:bold">::&lt;/span>&lt;span style="color:#008080">InheritableOptions&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>new({ &lt;span style="color:#990073">girl&lt;/span>: &lt;span style="color:#d14">&amp;#39;Mary&amp;#39;&lt;/span>, &lt;span style="color:#990073">boy&lt;/span>: &lt;span style="color:#d14">&amp;#39;John&amp;#39;&lt;/span> })
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>という感じで利用できます。便利。&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ruby" data-lang="ruby"> &lt;span style="color:#000;font-weight:bold">class&lt;/span> &lt;span style="color:#458;font-weight:bold">InheritableOptions&lt;/span> &lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span> &lt;span style="color:#008080">OrderedOptions&lt;/span>
&lt;span style="color:#000;font-weight:bold">def&lt;/span> &lt;span style="color:#900;font-weight:bold">initialize&lt;/span>(parent &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000;font-weight:bold">nil&lt;/span>)
&lt;span style="color:#000;font-weight:bold">if&lt;/span> parent&lt;span style="color:#000;font-weight:bold">.&lt;/span>kind_of?(&lt;span style="color:#008080">OrderedOptions&lt;/span>)
&lt;span style="color:#998;font-style:italic"># use the faster _get when dealing with OrderedOptions&lt;/span>
&lt;span style="color:#000;font-weight:bold">super&lt;/span>() { &lt;span style="color:#000;font-weight:bold">|&lt;/span>h, k&lt;span style="color:#000;font-weight:bold">|&lt;/span> parent&lt;span style="color:#000;font-weight:bold">.&lt;/span>_get(k) }
&lt;span style="color:#000;font-weight:bold">elsif&lt;/span> parent
&lt;span style="color:#000;font-weight:bold">super&lt;/span>() { &lt;span style="color:#000;font-weight:bold">|&lt;/span>h, k&lt;span style="color:#000;font-weight:bold">|&lt;/span> parent&lt;span style="color:#000;font-weight:bold">[&lt;/span>k&lt;span style="color:#000;font-weight:bold">]&lt;/span> }
&lt;span style="color:#000;font-weight:bold">else&lt;/span>
&lt;span style="color:#000;font-weight:bold">super&lt;/span>()
&lt;span style="color:#000;font-weight:bold">end&lt;/span>
&lt;span style="color:#000;font-weight:bold">end&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>ここで先述の、&lt;code>_get&lt;/code>が利用されています。&lt;/p></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/activesupport/">ActiveSupport</category><category domain="https://www.rochefort.dev/tags/rails/">Rails</category></item><item><title>simplecovでbranch coverageを有効にする方法</title><link>https://www.rochefort.dev/posts/enable_branch_coverage_in_simplecov/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/enable_branch_coverage_in_simplecov/</guid><pubDate>Sat, 20 Nov 2021 17:00:00 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>今年に入って3回ぐらい、simplecovでbranch coverage取れるよという話をしていて、意外とみんな知らないのでは？と思ったので、こちらでも記しておきます。&lt;/p>
&lt;h2 id="設定">設定&lt;/h2>
&lt;p>&lt;a href="https://github.com/simplecov-ruby/simplecov#branch-coverage-ruby--25">Branch coverage (ruby &amp;ldquo;~&amp;gt; 2.5&amp;rdquo;)&lt;/a>
こちらに記載されていますが、ruby2.5以降は、&lt;code>enable_coverage :branch&lt;/code> 1行入れるだけで有効になります。&lt;br>
railsだと以下のようになります。&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ruby" data-lang="ruby">&lt;span style="color:#008080">SimpleCov&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>start &lt;span style="color:#d14">&amp;#39;rails&amp;#39;&lt;/span> &lt;span style="color:#000;font-weight:bold">do&lt;/span>
enable_coverage &lt;span style="color:#990073">:branch&lt;/span>
&lt;span style="color:#000;font-weight:bold">end&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="詳細はこんな感じ">詳細はこんな感じ&lt;/h2>
&lt;p>&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20211120/20211120170018_original.png" alt="simplecov_branch_detail">
line coverageとしては満たしていますが、elseのcaseが満たされていないというのが分かります。&lt;/p>
&lt;h2 id="注意事項">注意事項&lt;/h2>
&lt;p>githubのREADMEにも記載されていますが、branch coverage便利なので、これだけ見れば良いと思う人がいるかもしれませんが、
branch coverageはあくまで条件が実行されているかを見るものですので、line coverageと合わせてみる必要があります。&lt;/p></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/rails/">Rails</category><category domain="https://www.rochefort.dev/tags/test/">Test</category></item><item><title>Rails7(alpha2)ではransackの更新が必要</title><link>https://www.rochefort.dev/posts/rails7_alpha2_ransack/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/rails7_alpha2_ransack/</guid><pubDate>Sun, 07 Nov 2021 17:55:00 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>そろそろRails7 alpha2を試そうと思って、bundle update rails した後に、rails app:update したら
エラーになりました。&lt;/p>
&lt;pre>&lt;code>$ rails app:update
rails aborted!
LoadError: cannot load such file -- polyamorous/activerecord_7.0_ruby_2/join_association
/rochefort/rails7/config/application.rb:20:in `&amp;lt;main&amp;gt;'
/rochefort/rails7/Rakefile:4:in `&amp;lt;main&amp;gt;'
/rochefort/rails7/bin/rails:5:in `&amp;lt;top (required)&amp;gt;'
/rochefort/rails7/bin/spring:10:in `require'
/rochefort/rails7/bin/spring:10:in `block in &amp;lt;top (required)&amp;gt;'
&amp;lt;internal:kernel&amp;gt;:90:in `tap'
/rochefort/rails7/bin/spring:7:in `&amp;lt;top (required)&amp;gt;'
bin/rails:2:in `load'
bin/rails:2:in `&amp;lt;main&amp;gt;'
(See full trace by running task with --trace)
&lt;/code>&lt;/pre>&lt;h2 id="どうやら">どうやら&lt;/h2>
&lt;p>file名にactiverecordのversionがついている感じで何とも微妙なエラーメッセージですが、
ransack起因のものでした。&lt;/p>
&lt;p>&lt;a href="https://github.com/activerecord-hackery/ransack/pull/1205">Bump the Rails version to 7 by yahonda · Pull Request #1205 · activerecord-hackery/ransack&lt;/a>&lt;/p>
&lt;p>rails の version間の差異を吸収するために、このような実装になってるかと思います。&lt;/p>
&lt;h2 id="対応">対応&lt;/h2>
&lt;p>すでにrails contributorのyahondaさんが対応PR作成してくれていますが、
Rails自体がalpha版のためリリースはまだです。
そのため、Gemfileに以下を設定して、bundle update ransackすれば良いです。&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ruby" data-lang="ruby">gem &lt;span style="color:#d14">&amp;#34;ransack&amp;#34;&lt;/span>, &lt;span style="color:#990073">git&lt;/span>: &lt;span style="color:#d14">&amp;#34;https://github.com/activerecord-hackery/ransack&amp;#34;&lt;/span>, &lt;span style="color:#990073">ref&lt;/span>: &lt;span style="color:#d14">&amp;#34;81910c238dd4452bbe90541f13abb6e85b3bbfea&amp;#34;&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="ご参考">ご参考&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://github.com/activerecord-hackery/ransack/pull/1205">Bump the Rails version to 7 by yahonda · Pull Request #1205 · activerecord-hackery/ransack&lt;/a>&lt;/li>
&lt;/ul></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/rails/">Rails</category><category domain="https://www.rochefort.dev/tags/rails7/">Rails7</category><category domain="https://www.rochefort.dev/tags/ransack/">ransack</category></item><item><title>dribbbleのようなモーダル兼詳細ページをRailsで作る（後半）</title><link>https://www.rochefort.dev/posts/like-dribble-popup-link2-with-history-api/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/like-dribble-popup-link2-with-history-api/</guid><pubDate>Sat, 18 Sep 2021 04:00:00 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>&lt;a href="https://www.rochefort.dev/posts/like-dribbble-popup-link/">dribbbleのようなモーダル兼詳細ページをRailsで作る（前半）&lt;/a>&lt;/p>
&lt;p>こちらの続きです。&lt;/p>
&lt;h2 id="残りのタスク">残りのタスク&lt;/h2>
&lt;p>&lt;a href="https://www.rochefort.dev/posts/like-dribbble-popup-link/">前回記事&lt;/a> の後半にも書きましたが、
改めておさらいです。&lt;/p>
&lt;p>&lt;a href="https://hugo-theme-gallery.rochefort.dev/">Hugo Theme Gallery&lt;/a> では、
一応モーダルで表示するのと、別タブで表示するというのは実装できましたが、モーダル表示の際にURLの変更がされていない状態でした。&lt;/p>
&lt;p>これは、HTML5のHistory APIを利用することで対応することができます。&lt;br>
&lt;a href="https://developer.mozilla.org/ja/docs/Web/API/History_API">History API - Web API | MDN&lt;/a>&lt;/p>
&lt;p>URLの変更（参照の履歴の追加）と、元の画面に戻る（参照履歴の削除）方法についてそれぞれ説明していきます。&lt;/p>
&lt;h2 id="urlの変更参照の履歴の追加">URLの変更（参照の履歴の追加）&lt;/h2>
&lt;p>モーダルを開いたときにURLをセットする方法です。
&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210918/20210918053824_original.png" alt="pushState">&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-js" data-lang="js">&lt;span style="color:#000;font-weight:bold">const&lt;/span> MODAL_STATE &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#d14">&amp;#34;modal&amp;#34;&lt;/span>;
&lt;span style="color:#0086b3">document&lt;/span>.querySelector(&lt;span style="color:#d14">&amp;#34;body&amp;#34;&lt;/span>).addEventListener(&lt;span style="color:#d14">&amp;#34;click&amp;#34;&lt;/span>, (outerEvent) =&amp;gt; {
&lt;span style="color:#000;font-weight:bold">if&lt;/span> (outerEvent.target.className &lt;span style="color:#000;font-weight:bold">===&lt;/span> &lt;span style="color:#d14">&amp;#34;shot-img shadow-sm&amp;#34;&lt;/span>) {
&lt;span style="color:#000;font-weight:bold">const&lt;/span> link &lt;span style="color:#000;font-weight:bold">=&lt;/span> outerEvent.target.parentNode;
&lt;span style="color:#0086b3">window&lt;/span>.history.pushState(MODAL_STATE, link.getAttribute(&lt;span style="color:#d14">&amp;#34;data-modal-title&amp;#34;&lt;/span>), link.getAttribute(&lt;span style="color:#d14">&amp;#34;href&amp;#34;&lt;/span>));
}
});
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;code>window.history.pushState&lt;/code> を利用します。
ポイントは、第一引数なのですが、ここはブラウザの戻るボタンを押したときの対応として必要なものとなります。
こちらについては、後述しますので、今は気にしなくて良いです。
（addEventListenerは、jQueryでいうところのdelegateをさせるためにbodyに仕込んでいます。）&lt;/p>
&lt;h2 id="元の画面に戻る参照履歴の削除方法">元の画面に戻る（参照履歴の削除）方法&lt;/h2>
&lt;p>こちらは、モーダルを閉じる場合と、ブラウザの戻るボタンを押した場合の2種類のケースを考慮する必要があります。&lt;/p>
&lt;h3 id="1モーダルを閉じる場合">1.モーダルを閉じる場合&lt;/h3>
&lt;p>モーダル右上のxボタンや、モーダルの外をクリックした時に自動でモーダルが閉じられます。
この閉じる機能に &lt;code>history.back()&lt;/code> を追加すれば良いです。&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-js" data-lang="js">&lt;span style="color:#000;font-weight:bold">const&lt;/span> detailModalEl &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#0086b3">document&lt;/span>.getElementById(&lt;span style="color:#d14">&amp;#34;js-detail-modal&amp;#34;&lt;/span>);
detailModalEl.addEventListener(&lt;span style="color:#d14">&amp;#34;hide.bs.modal&amp;#34;&lt;/span>, () =&amp;gt; {
&lt;span style="color:#000;font-weight:bold">if&lt;/span> (&lt;span style="color:#0086b3">window&lt;/span>.history.state &lt;span style="color:#000;font-weight:bold">===&lt;/span> MODAL_STATE) {
&lt;span style="color:#0086b3">window&lt;/span>.history.back();
}
});
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>具体的には、&lt;a href="https://getbootstrap.jp/docs/5.0/components/modal/#events">Modal (モーダル) · Bootstrap v5.0&lt;/a> に記載されている、 &lt;code>hide.bs.modal&lt;/code> を利用します。
（&lt;code>hidden.bs.modal&lt;/code> も用意されていますが、こちらはモーダルが非表示になるのを待つので、ワンテンポ遅くなります。）&lt;/p>
&lt;p>ここで、 &lt;code>history.state&lt;/code> が出てきますが、後述のため一旦説明は省きます。&lt;/p>
&lt;h3 id="2ブラウザの戻るボタンを押した場合">2.ブラウザの戻るボタンを押した場合&lt;/h3>
&lt;p>ブラウザの戻るボタンを押すと、&lt;code>history.back()&lt;/code> が実行されるため、URLは正しく戻りますが、
モーダルは残ったままです。&lt;/p>
&lt;p>ですので、このモーダルを消せば良さそうです。&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-js" data-lang="js">&lt;span style="color:#0086b3">window&lt;/span>.addEventListener(&lt;span style="color:#d14">&amp;#34;popstate&amp;#34;&lt;/span>, () =&amp;gt; {
&lt;span style="color:#000;font-weight:bold">const&lt;/span> detailModal &lt;span style="color:#000;font-weight:bold">=&lt;/span> bootstrap.Modal.getInstance(detailModalEl);
&lt;span style="color:#000;font-weight:bold">if&lt;/span> (detailModal &lt;span style="color:#000;font-weight:bold">&amp;amp;&amp;amp;&lt;/span> detailModal.&lt;span style="color:#099">_&lt;/span>isShown) {
detailModal.hide();
}
});
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>ここで登場するのが &lt;code>popstate&lt;/code> です。これは、&lt;code>history.back()&lt;/code> が呼び出された時にトリガーされます。
ですので、ブラウザが開いている時だけ、モーダルを閉じる処理を入れます。&lt;br>
（&lt;a href="https://getbootstrap.jp/docs/5.0/components/modal/#events">Modal (モーダル) · Bootstrap v5.0&lt;/a>）&lt;/p>
&lt;h3 id="stateについて">stateについて&lt;/h3>
&lt;p>この &lt;code>detailModal.hide()&lt;/code> によって、モーダルを閉じると、&lt;br>
「1.モーダルを閉じる場合」で説明した、&lt;code>hide.bs.modal&lt;/code> のイベントが再び実行されてしまいます。&lt;/p>
&lt;p>そうすると、 &lt;code>history.back()&lt;/code> が実行されてしまい、2つ前のURLに戻ってしまいます。&lt;/p>
&lt;p>これを避けるために、 &lt;code>pushState&lt;/code> の第一引数にモーダル表示の際に追加したことを明示する情報をセットしていました。&lt;br>
この第一引数であるstateは、 &lt;code>popstate&lt;/code> 時に &lt;code>history.state&lt;/code> にて参照することができます。
つまり、「1.モーダルを閉じる場合」にこの情報を見て、&lt;code>history.back()&lt;/code> を実行するということができます。&lt;/p>
&lt;p>（以下のifのところ）&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-js" data-lang="js"> &lt;span style="color:#000;font-weight:bold">if&lt;/span> (&lt;span style="color:#0086b3">window&lt;/span>.history.state &lt;span style="color:#000;font-weight:bold">===&lt;/span> MODAL_STATE) {
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="ということで">ということで&lt;/h2>
&lt;p>stateを適切に扱うことで、モーダルを閉じた場合と、ブラウザの戻るボタンを押した場合の判断を行なうことができました。&lt;/p>
&lt;p>これにて完成です。&lt;/p>
&lt;hr>
&lt;h2 id="see-also">See Also&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://dribbble.com/">Dribbble - Discover the World’s Top Designers &amp;amp; Creative Professionals&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.rochefort.dev/posts/launched-hugo-theme-gallery/">Hugoのテーマ一覧を参照できるWebアプリを作成した&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://hugo-theme-gallery.rochefort.dev/">Hugo Theme Gallery&lt;/a>&lt;/li>
&lt;/ul></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/blog/">Blog</category><category domain="https://www.rochefort.dev/tags/bootstrap/">Bootstrap</category><category domain="https://www.rochefort.dev/tags/dribbble/">Dribbble</category><category domain="https://www.rochefort.dev/tags/hugo/">Hugo</category><category domain="https://www.rochefort.dev/tags/html5/">HTML5</category><category domain="https://www.rochefort.dev/tags/javascript/">JavaScript</category><category domain="https://www.rochefort.dev/tags/rails/">Rails</category></item><item><title>dribbbleのようなモーダル兼詳細ページをRailsで作る（前半）</title><link>https://www.rochefort.dev/posts/like-dribbble-popup-link/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/like-dribbble-popup-link/</guid><pubDate>Thu, 16 Sep 2021 23:00:00 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>先日 &lt;a href="https://www.rochefort.dev/posts/launched-hugo-theme-gallery/">Hugoのテーマ一覧を参照できるWebアプリを作成した&lt;/a> のですが、この時に参考にしたサイトがあります。&lt;/p>
&lt;h2 id="dribbble">Dribbble&lt;/h2>
&lt;p>言わずと知れた &lt;a href="https://dribbble.com/">Dribbble&lt;/a> です。
このサイト、画像をクリックするとmodalっぽく開く実装なのですが、リンクを別タブで開いても表示されます。
&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210917/20210917025716.png" alt="モーダル" title="モーダル">
&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210917/20210917025617.png" alt="別タブ" title="別タブ">&lt;/p>
&lt;p>これをRailsアプリで実装したくなってきました。&lt;/p>
&lt;h2 id="やり方ざっくり">やり方ざっくり&lt;/h2>
&lt;p>&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210918/20210918051855_original.png" alt="実装イメージ">
モーダルで表示する部分のデータをクライアント側（HTML or JS）に持たせても良いのですが、一覧ページの画像は結構な数があるので、このデータの取得をAjaxで都度取得する実装とすることにしました。&lt;br>
あと、UIはBootstrap使っているので、モーダルの操作は&lt;a href="https://getbootstrap.jp/docs/5.0/components/modal/#methods">こちらのAPI&lt;/a>を利用しています。&lt;br>
　&lt;/p>
&lt;h3 id="もう少し詳しく">もう少し詳しく&lt;/h3>
&lt;ol>
&lt;li>空のモーダルを用意する（HTML）&lt;br>
以下、slimの例。ここは、まぁ公式ドキュメントを元に空のモーダルを1つ作っておくだけです。&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">#js-detail-modal.modal.fade aria-hidden=&amp;#34;true&amp;#34; style=&amp;#34;display: none;&amp;#34; tabindex=&amp;#34;-1&amp;#34;
.modal-dialog.modal-xl
.d-flex.justify-content-end
button.btn-close.btn-close-white aria-label=&amp;#34;Close&amp;#34; data-bs-dismiss=&amp;#34;modal&amp;#34; type=&amp;#34;button&amp;#34;
.modal-content
#js-modal-body.modal-body
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="2">
&lt;li>一覧ページの画像に詳細ページのリンクをAjaxで追加（Rails）&lt;br>
link_toのオプションに &lt;code>remote: true&lt;/code> を設定しておきます。&lt;br>
　&lt;/li>
&lt;li>詳細ページのviewは丸々partial化（Rails）&lt;br>
これは、モーダル表示でのAjaxのための実装です。次の工程で利用します。（ここがポイントかな）&lt;br>
　&lt;/li>
&lt;li>partial化したviewをjs.erbにて、モーダルの中身を差し替え、モーダルの表示を行います。（Rails）&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-js" data-lang="js">&lt;span style="color:#0086b3">document&lt;/span>.getElementById(&lt;span style="color:#d14">&amp;#34;js-modal-body&amp;#34;&lt;/span>).innerHTML &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#d14">&amp;#34;&amp;lt;%= j(render &amp;#39;theme&amp;#39;)%&amp;gt;&amp;#34;&lt;/span>;
&lt;span style="color:#000;font-weight:bold">new&lt;/span> Modal(&lt;span style="color:#0086b3">document&lt;/span>.getElementById(&lt;span style="color:#d14">&amp;#39;js-detail-modal&amp;#39;&lt;/span>)).show();
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>この &lt;code>Modal&lt;/code>は、&lt;code>bootstrap.Modal&lt;/code> です。webpackerのエントリーファイルで
windowオブジェクトに突っ込んでいます。&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-js" data-lang="js">&lt;span style="color:#998;font-style:italic">// app/javascript/packs/application.js
&lt;/span>&lt;span style="color:#998;font-style:italic">&lt;/span>&lt;span style="color:#000;font-weight:bold">import&lt;/span> &lt;span style="color:#000;font-weight:bold">*&lt;/span> as bootstrap from &lt;span style="color:#d14">&amp;#34;bootstrap&amp;#34;&lt;/span>
&lt;span style="color:#0086b3">window&lt;/span>.Modal &lt;span style="color:#000;font-weight:bold">=&lt;/span> bootstrap.Modal;
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="残タスク">残タスク&lt;/h2>
&lt;p>ここまでで、一応モーダルで表示するのと、別タブで表示するのは実装できました。&lt;/p>
&lt;p>一見完了してそうなのですが、実はDribbbleではモーダル表示の際にURLを変更しています。
ここは、HTML5のHistory APIであるpushStateを利用しています。
いわゆるpjaxと呼ばれる実装ですね。
ここは実装してみて、少しハマったので、別記事で詳細記載したいと思います。&lt;/p>
&lt;hr>
&lt;h2 id="see-also">See Also&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://dribbble.com/">Dribbble - Discover the World’s Top Designers &amp;amp; Creative Professionals&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.rochefort.dev/posts/launched-hugo-theme-gallery/">Hugoのテーマ一覧を参照できるWebアプリを作成した&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://hugo-theme-gallery.rochefort.dev/">Hugo Theme Gallery&lt;/a>&lt;/li>
&lt;/ul></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/blog/">Blog</category><category domain="https://www.rochefort.dev/tags/bootstrap/">Bootstrap</category><category domain="https://www.rochefort.dev/tags/dribbble/">Dribbble</category><category domain="https://www.rochefort.dev/tags/hugo/">Hugo</category><category domain="https://www.rochefort.dev/tags/rails/">Rails</category></item><item><title>Hugoのテーマ一覧を参照できるWebアプリを作成した</title><link>https://www.rochefort.dev/posts/launched-hugo-theme-gallery/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/launched-hugo-theme-gallery/</guid><pubDate>Tue, 14 Sep 2021 23:00:00 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>&lt;a href="https://gohugo.io/">Hugo&lt;/a> 早くて、使いやすくて気に入っています。&lt;/p>
&lt;p>ただ、最初始めるにあたり、テーマ選びが難しいです。
公式にも&lt;a href="https://themes.gohugo.io/">テーマ一覧&lt;/a> があるのですが、
結構な量あって、選びにくいという問題があります。&lt;/p>
&lt;p>公式の詳細ページには、Githubのスター数が表示されているので、
これを使ってソートすると割と人気なテーマが分かって良さそうということで
ちゃちゃっとRailsで作ってみました。&lt;/p>
&lt;p>ここはHugoで作るべきな気がしましたが、バックエンドでDB更新となるとRuby/Railsを使うと
サクッとできるので、何も考えずに作ってしまいました。&lt;/p>
&lt;p>一見公式のテーマ一覧と変わらないように見えますが、タグ選択時にもGithub Starsでソートして
人気そうなやつが上位に来るようにしています。&lt;/p>
&lt;hr>
&lt;h2 id="構成">構成&lt;/h2>
&lt;p>Frontend: Bootstrap&lt;br>
Backend: Rails&lt;br>
Deploy: Linode&lt;/p>
&lt;hr>
&lt;h2 id="ちょっと後悔している点">ちょっと後悔している点&lt;/h2>
&lt;p>勢いでscrapeして作ってしまいましたが、よくよく考えると公式のテーマ一覧の方もリスト管理されているはずで、
そっちのデータを確認してそれを元に作るのが良いなと、出来上がってから思いました。&lt;/p>
&lt;p>調べると、案の定以下にありました。&lt;br>
&lt;a href="https://github.com/gohugoio/hugoThemesSiteBuilder/blob/main/themes.txt">hugoThemesSiteBuilder/themes.txt at main · gohugoio/hugoThemesSiteBuilder&lt;/a>&lt;/p>
&lt;p>なので、ここは後で直すかもしれません。&lt;/p>
&lt;hr>
&lt;h2 id="see-also">See Also&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://hugo-theme-gallery.rochefort.dev/">Hugo Theme Gallery&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://gohugo.io/">The world’s fastest framework for building websites | Hugo&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://themes.gohugo.io/">Complete List | Hugo Themes&lt;/a>&lt;/li>
&lt;/ul></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/blog/">Blog</category><category domain="https://www.rochefort.dev/tags/hugo/">Hugo</category><category domain="https://www.rochefort.dev/tags/rails/">Rails</category></item><item><title>cat cloneのbatを使ってみる</title><link>https://www.rochefort.dev/posts/bat_as_cat_clone/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/bat_as_cat_clone/</guid><pubDate>Thu, 09 Sep 2021 23:00:00 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>本日は RubyKaigi Takeout 2021 が開催されていました。
感想はまとめて書こうかと思っていますが、デモ中に &lt;code>bat&lt;/code> コマンドを実行している発表者が2人いました。
catの改良版で便利そう！だったので、早速入れてみました。&lt;/p>
&lt;h2 id="概要">概要&lt;/h2>
&lt;pre>&lt;code>A cat(1) clone with syntax highlighting and Git integration.
&lt;/code>&lt;/pre>&lt;p>と記載されているように、見やすいシンタックスハイライトと、git（だけでなく色んなツール）連携が可能です。&lt;/p>
&lt;p>色んなOSに対応しています。macはbrewで入れるだけです。&lt;br>
また、themeの設定や表示項目、拡張子とハイライトする言語の組み合わせを設定できたりします。
見た目もきれいで、とても良いです。&lt;/p>
&lt;h3 id="bat-readmemd">bat ./README.md&lt;/h3>
&lt;p>&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210909/20210909235454_original.png" alt="bat">&lt;/p>
&lt;h3 id="git-show-v060srcmainrs--bat--l-rs">git show v0.6.0:src/main.rs | bat -l rs&lt;/h3>
&lt;p>&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210909/20210909235450_original.png" alt="bat with git">&lt;/p>
&lt;h3 id="bat---list-themes">bat &amp;ndash;list-themes&lt;/h3>
&lt;p>&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210909/20210909235446_original.png" alt="bat themes">&lt;/p>
&lt;hr>
&lt;h2 id="link">Link&lt;/h2>
&lt;p>&lt;a href="https://github.com/sharkdp/bat">sharkdp/bat&lt;/a>&lt;/p></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/linux/">Linux</category><category domain="https://www.rochefort.dev/tags/mac/">Mac</category></item><item><title>HerokuのRails App（Advent Calender Ranking）をlinodeに移行</title><link>https://www.rochefort.dev/posts/migrate-linode-from-heroku/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/migrate-linode-from-heroku/</guid><pubDate>Wed, 08 Sep 2021 22:00:00 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>勢いで作って放置していた &lt;a href="https://advent-ranking.rochefort.dev/">Advent Calender Ranking&lt;/a> ですが、
Herokuにデプロイしており、カスタムドメインでのSSL利用料に毎月 $7 かかっていました。&lt;br>
これをなんとかしたいという思いがあり、ついでに遊び場として &lt;a href="http://localhost:1313/posts/linode-vpc/">Linodeを契約(VPC)&lt;/a> していました。&lt;/p>
&lt;h2 id="実施したこと">実施したこと&lt;/h2>
&lt;ul>
&lt;li>Rubyのversion up&lt;/li>
&lt;li>ついでに脆弱性対応（gem/npmのupgrade）&lt;/li>
&lt;li>capistranoでのデプロイ設定、環境変数設定&lt;/li>
&lt;/ul>
&lt;p>DBは &lt;a href="https://www.elephantsql.com/">ElephantSQL&lt;/a> を利用していたこともあり、
特に大きな作業もなく、すんなり移行できました。&lt;/p>
&lt;h2 id="今後">今後&lt;/h2>
&lt;p>&lt;a href="https://ink.sapo.pt/">Ink Interface Kit&lt;/a> を利用しているのですが、UIが寂しい感もあるので、手が空いたら少し手を入れようと思っています。&lt;/p>
&lt;hr>
&lt;h2 id="see-also">See Also&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://rochefort.hatenablog.com/entry/advent-ranking">Advent Calender Rankingを作ってみた - rochefort&amp;rsquo;s blog&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.elephantsql.com/">ElephantSQL&lt;/a>&lt;/li>
&lt;/ul></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/rails/">Rails</category><category domain="https://www.rochefort.dev/tags/linode/">Linode</category></item><item><title>Hugoのコメント機能としてDisqusを利用する</title><link>https://www.rochefort.dev/posts/hugo-disqus/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/hugo-disqus/</guid><pubDate>Wed, 01 Sep 2021 22:00:00 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>Hugoでコメント機能を導入するには、外部のサービスを利用するのが簡単です。
今回は、広く利用されている &lt;a href="https://disqus.com/">Disqus&lt;/a> を入れてみました。&lt;/p>
&lt;h2 id="気になるお値段">気になるお値段&lt;/h2>
&lt;p>&lt;a href="https://disqus.com/pricing/">Disqus Plans and Pricing&lt;/a>&lt;/p>
&lt;p>50,000 pv/日 から有料となります。&lt;/p>
&lt;p>また、通常ではコメント非表示にしておいて、ボタンクリックで表示させる仕組みを入れれば、pv数は下げられます。&lt;br>
私が利用している &lt;a href="https://github.com/reuixiy/hugo-theme-meme">hugo-theme-meme&lt;/a> もこの機能があります。&lt;/p>
&lt;h2 id="disqusの導入方法">Disqusの導入方法&lt;/h2>
&lt;p>迷いそうなとこだけpickup。&lt;/p>
&lt;h3 id="disqusの登録">Disqusの登録&lt;/h3>
&lt;p>1.sign up&lt;br>
&lt;a href="https://disqus.com/">Disqus&lt;/a> の GET STARTED からsign upします。&lt;/p>
&lt;p>2.install on my site を選択
&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210901/20210901215737_original.png" width=200/>&lt;/p>
&lt;p>名称やURLを入力します。&lt;/p>
&lt;p>3.platform選択
一番下のmanualを選択します。
&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210901/20210901215743_original.png" width=400/>&lt;/p>
&lt;p>コードが生成されます。&lt;br>
これを突っ込めば利用できます。&lt;/p>
&lt;p>Themeによっては、より簡単に設定できるようにしているものもあります。&lt;br>
私が利用している &lt;a href="https://github.com/reuixiy/hugo-theme-meme">hugo-theme-meme&lt;/a> もかなり簡単で、以下3箇所修正すれば利用できました。&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-diff" data-lang="diff"># config.toml
&lt;span style="color:#999">diff --git a/config.toml b/config.toml
&lt;/span>&lt;span style="color:#999">index c63c193..c5a32e6 100644
&lt;/span>&lt;span style="color:#999">&lt;/span>&lt;span style="color:#000;background-color:#fdd">--- a/config.toml
&lt;/span>&lt;span style="color:#000;background-color:#fdd">&lt;/span>&lt;span style="color:#000;background-color:#dfd">+++ b/config.toml
&lt;/span>&lt;span style="color:#000;background-color:#dfd">&lt;/span>&lt;span style="color:#aaa">@@ -648,7 +648,7 @@ uglyURLs = false
&lt;/span>&lt;span style="color:#aaa">&lt;/span> # Note: render only in production
# environment
&lt;span style="color:#000;background-color:#fdd">- enableComments = false
&lt;/span>&lt;span style="color:#000;background-color:#fdd">&lt;/span>&lt;span style="color:#000;background-color:#dfd">+ enableComments = true
&lt;/span>&lt;span style="color:#000;background-color:#dfd">&lt;/span> # Note: *global settings*
# `comments` in post’s Front Matter
# has a higher priority than here
&lt;span style="color:#aaa">@@ -657,8 +657,8 @@ uglyURLs = false
&lt;/span>&lt;span style="color:#aaa">&lt;/span> autoLoadComments = false
## Disqus
&lt;span style="color:#000;background-color:#fdd">- enableDisqus = false
&lt;/span>&lt;span style="color:#000;background-color:#fdd">- disqusShortname = &amp;#34;&amp;#34;
&lt;/span>&lt;span style="color:#000;background-color:#fdd">&lt;/span>&lt;span style="color:#000;background-color:#dfd">+ enableDisqus = true
&lt;/span>&lt;span style="color:#000;background-color:#dfd">+ disqusShortname = &amp;#34;rochefort-dev&amp;#34;
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="こんな感じ">こんな感じ&lt;/h2>
&lt;p>1.記事の最後に以下リンクが表示されます。
&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210901/20210901215749_original.png" width="300"/>&lt;/p>
&lt;p>これをクリックすると&lt;/p>
&lt;p>2.コメント欄が表示されます。
&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210901/20210901215805_original.png" width="500" />&lt;/p>
&lt;hr>
&lt;h2 id="関連リンク">関連リンク&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://github.com/reuixiy/hugo-theme-meme">hugo-theme-meme&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://disqus.com/">Disqus&lt;/a>&lt;/li>
&lt;/ul></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/blog/">Blog</category><category domain="https://www.rochefort.dev/tags/hugo/">Hugo</category><category domain="https://www.rochefort.dev/tags/disqus/">Disqus</category></item><item><title>Puma(Rails6)をsystemdで起動させる</title><link>https://www.rochefort.dev/posts/puma-systemd/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/puma-systemd/</guid><pubDate>Mon, 30 Aug 2021 22:00:00 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>以前のPumaではdaemonizeオプションが用意されていましたが、Puma5.1で無くなりました。
Issueを見てみたところ、daemonizeはsystemd（やrunit）などのOSが提供しているものを利用してくれというスタンスのようです。&lt;/p>
&lt;h2 id="puma公式のsystemdの書き方">Puma公式のsystemdの書き方&lt;/h2>
&lt;p>こちらに記載されています（↓はv5.4.0のもの）。&lt;br>
&lt;a href="https://github.com/puma/puma/blob/v5.4.0/docs/systemd.md">puma/systemd.md at v5.4.0 · puma/puma&lt;/a>&lt;/p>
&lt;p>こんな感じに修正して利用しています。&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&lt;span style="color:#998;font-style:italic"># /etc/systemd/system/puma.service&lt;/span>
&lt;span style="color:#000;font-weight:bold">[&lt;/span>Unit&lt;span style="color:#000;font-weight:bold">]&lt;/span>
&lt;span style="color:#008080">Description&lt;/span>&lt;span style="color:#000;font-weight:bold">=&lt;/span>Puma HTTP Server
&lt;span style="color:#008080">After&lt;/span>&lt;span style="color:#000;font-weight:bold">=&lt;/span>network.target
&lt;span style="color:#000;font-weight:bold">[&lt;/span>Service&lt;span style="color:#000;font-weight:bold">]&lt;/span>
&lt;span style="color:#998;font-style:italic"># Puma supports systemd&amp;#39;s `Type=notify` and watchdog service&lt;/span>
&lt;span style="color:#998;font-style:italic"># monitoring, if the [sd_notify](https://github.com/agis/ruby-sdnotify) gem is installed,&lt;/span>
&lt;span style="color:#998;font-style:italic"># as of Puma 5.1 or later.&lt;/span>
&lt;span style="color:#998;font-style:italic"># On earlier versions of Puma or JRuby, change this to `Type=simple` and remove&lt;/span>
&lt;span style="color:#998;font-style:italic"># the `WatchdogSec` line.&lt;/span>
&lt;span style="color:#008080">Type&lt;/span>&lt;span style="color:#000;font-weight:bold">=&lt;/span>notify
&lt;span style="color:#998;font-style:italic"># If your Puma process locks up, systemd&amp;#39;s watchdog will restart it within seconds.&lt;/span>
&lt;span style="color:#008080">WatchdogSec&lt;/span>&lt;span style="color:#000;font-weight:bold">=&lt;/span>&lt;span style="color:#099">10&lt;/span>
&lt;span style="color:#008080">User&lt;/span>&lt;span style="color:#000;font-weight:bold">=&lt;/span>rochefort
&lt;span style="color:#008080">WorkingDirectory&lt;/span>&lt;span style="color:#000;font-weight:bold">=&lt;/span>/var/app/my_app/current
&lt;span style="color:#998;font-style:italic"># Helpful for debugging socket activation, etc.&lt;/span>
&lt;span style="color:#998;font-style:italic">#Environment=PUMA_DEBUG=1&lt;/span>
&lt;span style="color:#008080">Environment&lt;/span>&lt;span style="color:#000;font-weight:bold">=&lt;/span>&lt;span style="color:#008080">RAILS_ENV&lt;/span>&lt;span style="color:#000;font-weight:bold">=&lt;/span>production
&lt;span style="color:#008080">Environment&lt;/span>&lt;span style="color:#000;font-weight:bold">=&lt;/span>&lt;span style="color:#008080">RAILS_SERVE_STATIC_FILES&lt;/span>&lt;span style="color:#000;font-weight:bold">=&lt;/span>&lt;span style="color:#099">1&lt;/span>
&lt;span style="color:#008080">ExecStart&lt;/span>&lt;span style="color:#000;font-weight:bold">=&lt;/span>/bin/bash -lc &lt;span style="color:#d14">&amp;#39;bundle exec puma -C config/puma.rb&amp;#39;&lt;/span>
&lt;span style="color:#008080">Restart&lt;/span>&lt;span style="color:#000;font-weight:bold">=&lt;/span>always
&lt;span style="color:#000;font-weight:bold">[&lt;/span>Install&lt;span style="color:#000;font-weight:bold">]&lt;/span>
&lt;span style="color:#008080">WantedBy&lt;/span>&lt;span style="color:#000;font-weight:bold">=&lt;/span>multi-user.target
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>以下、ポイントについて補足します。&lt;/p>
&lt;h3 id="type">Type&lt;/h3>
&lt;p>Puma5.1以上で &lt;a href="https://github.com/agis/ruby-sdnotify">sd_notify&lt;/a> をinstallしている場合は、
&lt;code>notify&lt;/code> を指定することでsystemdでシステム起動の異常を検知することが可能です。&lt;/p>
&lt;p>それ以前は、 &lt;code>simple&lt;/code> を指定します。（simpleだとコマンド実行で起動完了と判断されます。）
この場合は、 &lt;code>WatchdogSec&lt;/code> は不要です。&lt;/p>
&lt;p>5.1以上にして、Gemfile に以下追加してinstallしておくのが良いでしょう。&lt;/p>
&lt;pre>&lt;code># Gemfile
gem 'sd_notify'
&lt;/code>&lt;/pre>&lt;h3 id="environment">Environment&lt;/h3>
&lt;p>環境変数ですが、この例では個別に指定していますが、
プロジェクト固有の環境変数が別ファイルで管理されているなどすれば（例えば .env や .envrc など）、&lt;code>EnvironmentFile&lt;/code> が利用できます。&lt;/p>
&lt;h3 id="execstart">ExecStart&lt;/h3>
&lt;p>公式の例では以下のように記載されています。&lt;/p>
&lt;pre>&lt;code>ExecStart=/&amp;lt;FULLPATH&amp;gt;/bin/puma -C &amp;lt;YOUR_APP_PATH&amp;gt;/puma.rb
&lt;/code>&lt;/pre>&lt;p>anyenv(rbenv) 利用時に、パスが長くなってしまいます。
（これでも良いのですが、プロジェクト毎に書き換える箇所が増えてしまいます。）&lt;/p>
&lt;pre>&lt;code>例）
ExecStart=//home/rochefort/.anyenv/envs/rbenv/shims/bundle exec puma -C /var/app/my_app/current/config/puma.rb
&lt;/code>&lt;/pre>&lt;p>bash -lc を経由させることで、 &lt;code>.bash_profile&lt;/code> を読み込ませた上で実行でき流ので、以下のようにsimpleに書けます。&lt;/p>
&lt;pre>&lt;code>ExecStart=/bin/bash -lc 'bundle exec puma -C config/puma.rb'
&lt;/code>&lt;/pre>&lt;hr>
&lt;h3 id="systemctlコマンド">systemctlコマンド&lt;/h3>
&lt;p>公式ドキュメントには以下が記載されています。&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
&lt;/span>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-sh" data-lang="sh">&lt;span style="color:#998;font-style:italic"># After installing or making changes to puma.service&lt;/span>
systemctl daemon-reload
&lt;span style="color:#998;font-style:italic"># Enable so it starts on boot&lt;/span>
systemctl &lt;span style="color:#0086b3">enable&lt;/span> puma.service
&lt;span style="color:#998;font-style:italic"># Initial start up.&lt;/span>
systemctl start puma.service
&lt;span style="color:#998;font-style:italic"># Check status&lt;/span>
systemctl status puma.service
&lt;span style="color:#998;font-style:italic"># A normal restart. Warning: listeners sockets will be closed&lt;/span>
&lt;span style="color:#998;font-style:italic"># while a new puma process initializes.&lt;/span>
systemctl restart puma.service
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>これに加えて、エラー発生時は以下で確認していました。&lt;/p>
&lt;div class="highlight">&lt;div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code>&lt;span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-sh" data-lang="sh">sudo journalctl -fp err
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/puma/">Puma</category><category domain="https://www.rochefort.dev/tags/rails/">Rails</category><category domain="https://www.rochefort.dev/tags/linux/">Linux</category></item><item><title>不動産価格指数をチャートで見れるサイトを作りました</title><link>https://www.rochefort.dev/posts/house-price-index-chart/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/house-price-index-chart/</guid><pubDate>Sat, 28 Aug 2021 17:00:00 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>最近、エンジニアが書いている不動産関係のブログ記事を見る機会があり、そこに出てきた「不動産価格指数」に興味が湧いたので、データを眺めていました。
見ているうちにチャート化して、見たいときに見れるようにしておくと、需要がありそうだなと思って、勢いでWebアプリを作りました。&lt;/p>
&lt;p>結構データとしても面白いです。マンションの値上がり率は全体的に高いのですが、中でも地方の方が高いというのは全く知りませんでした。てっきり関東都市部の方が高いと思っていました。&lt;/p>
&lt;h2 id="テーマ">テーマ&lt;/h2>
&lt;p>脈略全くないですが、クリームソーダです。
無駄にグラデーションさせてます。&lt;/p>
&lt;h2 id="データ">データ&lt;/h2>
&lt;p>&lt;a href="https://www.mlit.go.jp/totikensangyo/totikensangyo_tk5_000085.html">こちら&lt;/a>
で国土交通省によって公開されています。
これ自体はありがたいのですが、ファイル形式はEXCELです。JSONかCSVで欲しいところですが、贅沢は言ってられないので、Parseして利用しています。&lt;/p>
&lt;h2 id="技術スタック">技術スタック&lt;/h2>
&lt;ul>
&lt;li>Server side: Rails6&lt;/li>
&lt;li>Frontend: Bootstrap5、NVD3&lt;/li>
&lt;li>Deployment: VPC Linode&lt;/li>
&lt;/ul>
&lt;h3 id="補足">補足&lt;/h3>
&lt;h4 id="excel-parser">Excel Parser&lt;/h4>
&lt;p>&lt;a href="https://github.com/roo-rb/roo">roo&lt;/a>
というgemを使っています。
公式に記載のやり方で、サクッとparseできました。ありがとうございます。&lt;/p>
&lt;h4 id="chart">chart&lt;/h4>
&lt;p>&lt;a href="https://nvd3.org/">NVD3&lt;/a> を利用。
どうしても期間を変更できるslider付きのchartを使用したかったのでライセンス上利用可能なこちらを採用しています。
D3.jsのwrapperなんですが、使用しているversionが3系でかなり低いです。&lt;/p>
&lt;h4 id="bootstrap5">Bootstrap5&lt;/h4>
&lt;p>Bootstrap久しぶりに利用しましたが、jQuery依存が無くなったんですね。すごい。&lt;/p>
&lt;h4 id="deployment">deployment&lt;/h4>
&lt;p>&lt;a href="https://github.com/capistrano/capistrano">capistrano&lt;/a> を利用。
10年ぶりぐらいに使ったのですが、大分変わっていて今回一番苦労しました。周辺機能がgem化されているのですが、anyenvでの利用に手間取りました。
この辺は後ほど詳細書きたいと思います。&lt;/p>
&lt;h2 id="見ていた不動産関連のブログはこちら">見ていた不動産関連のブログはこちら&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://kumagi.hatenablog.com/entry/kodate-katta">ソフトウェアエンジニア、建売を買う - Software Transactional Memo&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://hichihara.hatenablog.com/entry/2021/07/26/070000">ソフトウェアエンジニア、家を買う - hichihara note&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://anond.hatelabo.jp/20210825234710">独身アラフォーwebエンジニアが中古マンションを買ってリノベした（追記）&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="リンク">リンク&lt;/h2>
&lt;p>&lt;a href="https://house-price.rochefort.dev/">不動産価格指数チャート&lt;/a>&lt;/p></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/realestate/">RealEstate</category><category domain="https://www.rochefort.dev/tags/rails/">Rails</category><category domain="https://www.rochefort.dev/tags/nvd3/">NVD3</category><category domain="https://www.rochefort.dev/tags/d3/">D3</category><category domain="https://www.rochefort.dev/tags/bootstrap/">Bootstrap</category><category domain="https://www.rochefort.dev/tags/linode/">Linode</category></item><item><title>Linodeを契約(VPC)</title><link>https://www.rochefort.dev/posts/linode-vpc/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/linode-vpc/</guid><pubDate>Wed, 25 Aug 2021 20:05:26 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>Linodeの契約をしました。
2〜3年ぶりぐらいのVPCです。
herokuで運用しているアプリがあったので、久しぶりに使ってみています。&lt;/p>
&lt;p>&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210825/20210825200314_original.png" alt="Linode">&lt;/p>
&lt;h2 id="linodeを選んだ理由">Linodeを選んだ理由&lt;/h2>
&lt;p>DigitalOcean使ったことなかったので、使ってみようと思っていたのですが、
以下の2点からLinodeを利用することを決めました。
しばらく使ってみたいと思います。&lt;/p>
&lt;h3 id="tokyo-region">Tokyo Region&lt;/h3>
&lt;p>まぁ、DigitalOceanもシンガポールにあるので、それほど大差ない気はしますが、
一応、近いに越したことはないということでプラスポイント。&lt;/p>
&lt;h3 id="100ドル-キャンペーン">100ドル キャンペーン&lt;/h3>
&lt;p>&lt;a href="https://www.linode.com/lp/free-credit-100/">Try Linode for Free with $100 Credit | Linode&lt;/a>&lt;/p>
&lt;p>60日間で100ドルのクレジットがもらえます。
&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210825/20210825202344.png" alt="Linode">&lt;/p>
&lt;p>ググってみると、DigitalOceanも同様に、誰かのリファラルリンク付きのやつがありました。
気にならなければ、どちらも同じですね。
キャンペーンは恒常的にどちらもやってるイメージ。&lt;/p>
&lt;h2 id="でも">でも、、、&lt;/h2>
&lt;p>Cost的にはほぼ変わらないので、どっち選んでも良さそうだとは思ってます。
DigitalOceanの方がユーザーが多そうなので、また次契約する機会があれば、再度検討してみたいと思います。&lt;/p></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/vpc/">VPC</category><category domain="https://www.rochefort.dev/tags/linode/">Linode</category></item><item><title>HugoのDeploy方法</title><link>https://www.rochefort.dev/posts/hugo-deploy/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/hugo-deploy/</guid><pubDate>Tue, 24 Aug 2021 21:30:36 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>Hugoのデプロイ先については &lt;a href="https://www.netlify.com/">Netlify&lt;/a> にすることは決めていたのですが、デプロイ方法は当初 Github Actionを考えていました。&lt;/p>
&lt;h2 id="公式ドキュメント">公式ドキュメント&lt;/h2>
&lt;p>しかし、&lt;a href="https://gohugo.io/hosting-and-deployment/">デプロイのドキュメント&lt;/a> も公式にしっかりあり、&lt;a href="https://gohugo.io/hosting-and-deployment/hosting-on-netlify/">Netlifyについても&lt;/a> しっかり記載されていました。
そしてめちゃくちゃすんなり、できました。
こういう体験は非常に良いです。Hugo好きになってきました。&lt;/p>
&lt;h3 id="ざっくり概要">ざっくり概要&lt;/h3>
&lt;p>NetlifyでSite作って、リポジトリ連携（Github）して、設定ファイル（netlify.toml）配置するだけです。
利用した設定ファイル（netlify.toml）は、公式記載のままで問題なかったです。&lt;/p>
&lt;p>設定ファイルの注意点としては、HUGO_VERSION がnetlify.tomlと一致しているかぐらいでしょうか。&lt;/p>
&lt;p>あとは、themeをgit cloneで取得している場合は、利用できないらしいので、git submodule を利用して追加しておくのが良いという記述があります。（もともと submoduleを利用していたので特に対応なし。）&lt;/p>
&lt;hr>
&lt;h2 id="参考">参考&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://gohugo.io/hosting-and-deployment/">Hosting &amp;amp; Deployment | Hugo&lt;/a>&lt;/li>
&lt;/ul></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/blog/">Blog</category><category domain="https://www.rochefort.dev/tags/hugo/">Hugo</category></item><item><title>HugoでBlogを作ってみた</title><link>https://www.rochefort.dev/posts/start_a_blog_with_hugo/</link><guid isPermaLink="true">https://www.rochefort.dev/posts/start_a_blog_with_hugo/</guid><pubDate>Mon, 23 Aug 2021 18:30:20 +0900</pubDate><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright><description>&lt;p>Hatenaブログを独自ドメインに移行しようと思い立ったのですが、
毎月700円かかるため、他のブログシステムで良いのないか探していました。&lt;/p>
&lt;p>しかし、希望するものがなく、自前で環境用意するのが
simpleかつコストも安く抑えられそうという気がしたので、少し試してみました。&lt;/p>
&lt;h2 id="ブログに求める機能">ブログに求める機能&lt;/h2>
&lt;p>自分が必要とする機能を整理すると以下。&lt;/p>
&lt;p>&lt;strong>Must&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>独自ドメインが利用できる&lt;/li>
&lt;li>HTTPSが使える&lt;/li>
&lt;li>markdownが使える&lt;/li>
&lt;li>templateが豊富（デザインで悩みたくない）&lt;/li>
&lt;li>Tagging&lt;/li>
&lt;li>記事の検索&lt;/li>
&lt;li>低価格&lt;/li>
&lt;/ol>
&lt;p>今回改めて他のサービスを調べてみたところhatenaブログは結構良いかもしれないと思いました。
個人的には「価格」以外は満たしていそう。&lt;br>
（いろんなscriptがinjectされて重たかったりするのは難点ですが、、、）&lt;/p>
&lt;p>&lt;strong>Better&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>Webの管理機能（webからブログ更新できる手軽さが欲しい）&lt;/li>
&lt;/ol>
&lt;p>こんな感じでしょうか。&lt;/p>
&lt;hr>
&lt;h2 id="hugoとは">Hugoとは&lt;/h2>
&lt;a href="https://gohugo.io/">
&lt;img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rochefort/20210823/20210823225522_original.png" alt="Hugo" />
&lt;/a>
&lt;p>goのframeworkで高速かつ、Themeも豊富（だが探すのが結構大変）で、流行ってるようでしたので
今回試してみました。&lt;/p>
&lt;p>静的なファイルにビルドして、Netlifyにデプロイしちゃえば、お金かからず利用できます。&lt;br>
（デプロイに少し時間がかかってしまうのがネックといえばネック。）&lt;/p>
&lt;h3 id="installation">Installation&lt;/h3>
&lt;p>ご参考：公式ドキュメント（&lt;a href="https://gohugo.io/getting-started/quick-start/">Quick Start | Hugo&lt;/a>）&lt;/p>
&lt;p>ざっくり書くと、以下。&lt;/p>
&lt;ol>
&lt;li>Macの場合はbrew で install&lt;/li>
&lt;li>Themeを &lt;a href="https://themes.gohugo.io/">Complete List | Hugo Themes&lt;/a> から選ぶ&lt;/li>
&lt;li>Themeを &lt;code>git submodule add&lt;/code> or ダウンロードして配置（themes以下）&lt;/li>
&lt;li>Theme毎の設定を実施（だいたいThemeのページ辺りに実施方法が書いています）&lt;/li>
&lt;/ol>
&lt;p>あとは、 &lt;code>hugo serve&lt;/code> すれば動きます。作業自体は難しくありません。&lt;/p>
&lt;h3 id="themeカスタマイズ方法">Themeカスタマイズ方法&lt;/h3>
&lt;p>Themeに手を入れるケースは時々あると思います。
HTML関連は、 &lt;code>layouts&lt;/code> 以下に格納されており、Themeのファイルと同じ構成でプロジェクトルート以下に用意すればokです。&lt;/p>
&lt;p>cssのカスタマイズは、基本的にはcustomize用のcssをstatic以下に配置して上書きを行います。
（Themeによって、customize用のcssを設定ファイルで指定するようなものもあるようです。）&lt;/p>
&lt;hr>
&lt;h2 id="感想">感想&lt;/h2>
&lt;h3 id="良いところ">良いところ&lt;/h3>
&lt;ul>
&lt;li>高速（static以外は、保存時に即時反映されるので、気持ちよくかけます。）&lt;/li>
&lt;li>Themeのカスタマイズもそれなりにできる（&lt;code>layouts&lt;/code> をコピーして修正すれば良いですし、そんなに難しくはないです。）&lt;/li>
&lt;li>Deploy簡単（参考：&lt;a href="https://gohugo.io/hosting-and-deployment/hosting-on-netlify/">Host on Netlify | Hugo&lt;/a>）&lt;/li>
&lt;/ul>
&lt;h3 id="良くないところ">良くないところ&lt;/h3>
&lt;ul>
&lt;li>Webの管理機能が無い&lt;br>
これは仕方がないですが、必要であればgithub上でmarkdown追加すれば、自動でdeployできるのでそこまで困らない気はします。&lt;/li>
&lt;/ul>
&lt;h4 id="theme選びが大変">Theme選びが大変&lt;/h4>
&lt;p>&lt;a href="https://themes.gohugo.io/">Themeはかなりたくさん用意されている&lt;/a>ので、そこから選ぶのも一苦労。
また、ぱっと見どういう機能があるのかというのが分かりにくいです。
デモページは、だいたい用意されているようなので、なんとなくは確認できますが、
デモページに用意されていない機能を確認する場合、（例えば syntax highlight がどういう感じかなど）
実際に手元で起動させる必要があります。
今回3つほど実際に動かしてみましたが、実装や設定内容もそれぞれ違うので、このTheme選びは結構重要です。&lt;/p>
&lt;p>結果選んだのは、こちらの &lt;a href="https://themes.gohugo.io/themes/hugo-theme-meme/">MemE | Hugo Themes&lt;/a> 。
おしゃれなヘッダーとsimpleなブログデザインに惹かれて選んでみました。&lt;br>
light/darkモードに切り替えもできるし、かなり設定項目も多いです。&lt;br>
中国の方が作成されていて、Github Issueとか見るの辛いかと思ったのですが、英語はokそうだったので今回利用してみました。&lt;/p>
&lt;hr>
&lt;h2 id="参考">参考&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://themes.gohugo.io/themes/hugo-theme-meme/">MemE | Hugo Themes&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://themes.gohugo.io/">Complete List | Hugo Themes&lt;/a>&lt;/li>
&lt;/ul></description><category domain="https://www.rochefort.dev/categories/tech/">Tech</category><category domain="https://www.rochefort.dev/tags/blog/">Blog</category><category domain="https://www.rochefort.dev/tags/hugo/">Hugo</category></item></channel></rss>