おさとの雑記帳

日々の学習のアウトプットに使っていきます!

nvim-web-deviconsがうまく表示できない!!!

解決したいこと

などのnvim-tree/nvim-web-deviconsが表示されないので表示させたい。
lualine:

telescope:

環境

  • Mac
  • iTerm2
  • Neovim

方針

手順

  1. ryanoasis/nerd-fontsより以下を実行。
  brew tap homebrew/cask-fonts
  brew install font-hack-nerd-font
  1. iTerm2のSettings > Profiles > Textを開く。

  2. Fontの Use a different font for non-ASCII text にチェックを入れる

  3. Non-ASCII Fontという項目が現れるので、フォントをNerd Font系に変更する(ここではHack Nerd Font Mono)。

  4. 変更完了!
    lualine: telescope:

まとめ

先にfork元のリポジトリを見るべきでした。。(ブログ書くに当たってやっと見た。)
nvim-web-deviconsをインストールした後にiconを表示させる方法でした。
誰かの参考になれば幸いです 🙌

はじめての自作キーボード ⌨️

やったこと

先日ついに自作キーボードの作成をしました⌨

今回作成したのはCorne Cherry Lightです。自分で用意したのは以下のものです。

キーボード周り

備品

よかったこと

はんだ吸引線を買っていた

ハンダ付けは中学校の技術の授業以来でした。それでもそんなに失敗はしないだろうとたかをくくっていたのですが、念には念をということで、はんだ吸引線を買っておきました。結果的にこれが大成功でした。後述する失敗にあるピンを無理やり押し込んで曲げてしまった際に、吸引線ではんだを取り除き、折れたピンを抜くことができました🙌

失敗したこと

ピンを無理やり押し込んで曲げてしまった

promicro を本体と繋げるためのピン(?)を無理やり押し込んで折って(?)しまいました 😭

ピンが折れた(?)
ただ、後々考えてみると折れたのではなく、しっかり刺さっていなかった穴にはんだが流れ込んでしまったのかもと 👀

うまく動かず焦って折れたと思ってしまっただけかもしれませんね🤔

親指周りをロープロファイルにしなかった

親指周りの6つのキーをロープロファイルにしなかったことで親指周りがかなり高さのある形になってしまいました。
次に作成するキーボードではロープロファイルを採用しようと思います👍

熱してすぐのところにピンセット使ってピンセットを曲げてしまった

これは熱したところにすぐピンセットをあてたためか、無理な方向に動かそうとしたためか定かではないのですが、ピンセットが曲がってしまいました😱
どちらも行わないように気をつたいものです。

対応しているmicro usbケーブルを買ってなかった

唯一持っているmicro usbのケーブルがkindleのもので結構短めなので、もう少し長いケーブルを買っておけばよかったかなと思っています。ドッキングステーションを買う予定はないのですが、パソコンは机の上に置きたくないので💪

まとめ

失敗もたくさんありましたが、楽しく作成できました 🙌
近々’keyball44を作成する予定なので、今回の反省も活かして取り組めたらと思います⌨️

コードレビューで学ぶ Ruby on Rails 感想!!

どんな本?

SonicGarden 株式会社ソニックガーデンプログラマさんたちが書いた本です。

以下冒頭の本書についてからの引用です。

 本書は Ruby on Rails を使った Web アプリケーション開発においてより良い書き方を提案する 技術書です。
 対象読者は Ruby on Rails を使って何となくアプリケーションを書けるようになったけど、まだ自分のコードに自信が持てないというような、これから中級者を目指そうとしている方達です。
 この本では私たちが所属しているソニックガーデンが運営している中級者向けプログラミングコ ミュニティ「ソニックガーデンジム」で実際にあったコードレビューを元に、具体例を交えながらより良いコードを提案します。

以下は各章ごとの感想です。

1章 モデル

1.1 中間テーブルのモデルは関係性を表す命名をする

安直にuser_magazineとかにしがちだなとおもったらまさにそのままのclass名だった。身に覚えしかない。

1.2 一般ユーザーと管理者ユーザーでモデルを分けるべき?

adminカラム作ってtrue or false でもいいと思ったけど、確かにAdminが不要なカラムをもってしまうことが多くなってしまっていたなと。

1.4 デフォルト値の定義にはattributeメソッドを使おう

enumerize便利とおもってたけど、default値の値には注意しないといけないのか。設定してるとnilでもdefault値に上書きされちゃうのか。

1.6 データベースに制約を設定する

Not Null制約をつけて、default値をつける話は

 # userのnameにnot null制約を設定しない場合
 if user.name
   # nameがある時の処理
 else
   # nameがない時の処理
 end
 
 # userのnameにnot null制約を設定し、デフォルト値を空文字にする場合
 if user.name.empty?
   # nameがない時の処理
 else
   # nameがある時の処理
 end

ってかけてシンプルかなと思ったけど、他のコードで user.name&.upcase みたいに書かなきゃいけないの嫌だな。それを気をつけなきゃいけないのも。

2章 View

2.1 ビューに複雑なロジックを書かない

ここが一番刺さった。つい先日レビューもらったところだった。viewにロジック書かない!で理解が終わってて、全部モデルに書いてたけど、その先があったんや。モデルにはサービスの本質的なロジックだけ書く。Decoratorはviewに関連しすぎてる処理をラッピングしてメソッド定義する。ViewComponent(cells)ではビュートそれに関連するロジックをセットで管理する。もらったレビューずばり。

2.4 時間、日付のフォーマットにはI18n.lを使おう

i18nの話してる時、<%= l Time.now %> みたいなコードみると li だと勘違いしちゃうのはあるあるだと思ってる。

3章 Controller

3.1 一覧を取得する際にはorderをつける

一覧を取得するときに順番をつけるっていうのは最近twitterで社内のルール?として決めてるっていうのみたけど、ツイートみつからぬ、、

3.2 安全にオブジェクトを取得する

2回クエリ走っちゃいそうって思ったけど、そもそもcurrent_userがメモ化されてるから関係ないか。全体でfindしないで、user has many posts なら user.posts.find とした方が安全なのか。たしかにそうかも。postならまだよさそうだけど、他の重要な情報を他のuserが取得しうることになるのか。でも権限管理してれば大丈夫では?とも思ったけど、危険性を少しでも下げることが大事だという認識。

3.3 管理者と一般ユーザーのnamespaceは分ける

namespace切って余計な制御減らすって考え方は色々応用できそう。管理しやすいからって理由でnamespace切ることはあったけど、制御減らすためとは考えてなかったかも。

4章 Test

4.1 describe/context/it でテスト対象を表現する

「正しく動作すること」って書いてるのは私です。

4.3 システムテストでは操作後の結果まで確認しよう

view specって全然使ってないけど、割と使うのかな?

4.8 Strong Parameter の設定漏れを検知する

action_on_unpermitted_parametersって設定しらなかったので使っていきたい。

4.10 sleep は使ったら負け?

expect(page)でcapybaraが数秒(デフォルトで2秒)待ってくれるのはしらなかった。

4.11 効率よくテストを書く

システムテスト動線を確認、ユニットテストはロジックの詳細を確認。

5章 その他

5.2 gem バージョンを固定しない

gemを固定してしまうとバージョンアップのインパクトが大きいのは確かに。

5.5 命名について

date型のカラムは 動詞の過去形on で datetime型は 動詞の過去形at, bool型で_flgはさける。というのも、trueが結局どいう状態かわからないため。

5.6 禁止リストよりも許可リストを優先的に使おう

たしかに許可リストにしておけば、追加忘れても機能を使えないだけで、意図しない利用を防げるというのはあるな。安全第一。

5.7 コメントには言い訳を書く

わかりやすくするためのコメントより、わかりやすい命名を目指した方がいいのはたしかにだなぁ。説明的なコードを書くと。コメントは言い訳を書くところっていう表現面白い。

終わりに

自分も心当たりのあるレビューがたくさん載っていました
この本に書いてあったことを意識しながらより良いコードを書けるように精進していきたいと思います 🙌

RubyKaigi2023に参戦してきました!!

RubyKaigi 初参戦!!!

こんにちは!
2023年1月より合同会社春秋で一兵卒(アルバイト)として日々コードと戦っております、おさとです。
初となるRubyKaigiに参戦してきたのでレポートを書いていきたいと思います 💪

参加前

沖縄からの参戦だったので、松本への直行便がなく、東京 → 松本 or 名古屋 → 松本のどちらのルートにするか悩んでいました(後に福岡 → 松本もあったことをしりました)。結局名古屋ルートに決めたのですが、決めて手となったのがこちらのひつまぶしです🍚

松本駅に着くとRubyKaigiの横断幕が 、、!

素敵な横断幕に歓迎され、Day0からRubyKaigiに向けて気持ちが高ぶっていくのを感じました💪

参加中

セッション

Matz Keynote

RubyKaigi一発目はRubyのパパ、Matzのキーノートでした。
Rubyが自分より早く生まれていることや、プログラミングスクールでRubyを学び始めた2020/6にはすでにRuby 3.0がリリースされていたことなどに驚いてばかりのセッションでした 👀

Power up your REPL life with types

カタカタターン!!
tompng/katakata_irb は型定義の情報を使ってirbの補完機能を強力なものにするためのgemで、irbを触る時はいつもrequire してます 💪
型便利✨

なんといっても ruby/gem_rbs_collectionを利用するデモの中で、僕がruby/gem_rbs_collectionにコミットした gimei というgemが利用されていたことは 「Rubyに貢献したい!」「OSS活動したい!」と強く思わせてくれるものでした 🙌

github.com

Ruby Committers and The World

Rubyコミッターの方々の英語でのセッションでした。各々がどういった考えでそれぞれ注力している機能があるのかなどお話されてました。なによりディスカッションでは皆さん楽しそうに話されてるのが印象的でした 👀

Gradual typing for Ruby: comparing RBS and RBI/Sorbet

TapiocaSorbet といったgemについてSteepなどとの比較を交えながら紹介されてました。Steepとの実行速度の差が気になったので手を動かして確認してみたいと思います🙌

交流

会場ではいままでオンラインでしか認識していなかった方と交流できたり、authorsのみなさんとお話できました 🙏

また、オフィシャルパーティーでは様々な企業のRubyistのみなさんとお話することができて大変モチベーションがあがりました 🙌

お話してくださった皆さんありがとうございました 🙌

食事

とくにお蕎麦がおいしかったです!!
ついてすぐ食べ、ランチ休憩でも食べ、とたくさん美味しいお蕎麦をたべられました 🍻

参加後

次回に活かしたい点は以下のとおりです。

  • もっと写真撮っておけばよかった
  • スーツケースが必要(各ブースやノベリティがたくさん!)
  • Twitterの名前とアイコンがわかるものを用意しておけばよかった 🤔

終わりに

初めての参加でしたが存分に楽しむことができました!
所属や、国境を超えてRubyコミュニティを肌で感じることができ、すごく刺激になったと同時に、もっとRubyが好きになった3日間でした 💪

オーガナイザー、運営や関係者、参加者のみなさま、そして出張扱いで参加費用を負担して頂いた合同会社春秋のおかげで素敵な体験ができました 🙌
みなさまありがとうございました 🙏✨

そして来年は沖縄開催ですね!!🏝️ 沖縄開催に向けて、

などに取り組んでいきます 🏝️

沖縄に来る際や、当日はぜひお声かけください 🙌


合同会社春秋ではエンジニアを募集しています 🙌

Rubyでよく見る(&:)を読み解く

目次

はじめに

この記事はCODE BASE OKINAWA Advent Calendar 2022 - Adventarの10日目のエントリーです。
今まで何気なく使っていた(&:method)がどういう挙動をしているのか見ていきます。
↓こんなやつ

%w(urasoe naha ginowan).map(&:upcase)
#=> ["URASOE", "NAHA", "GINOWAN"]

前知識

(&:)を理解するために必要な知識をそれぞれ見ていきます。

Proc

Procとはブロックをオブジェクトにしたものです。
例えば↓のような使い方ができます。

square = Proc.new { |x| x ** 2 }

square.call(3)

#=> 9

&修飾

Procオブジェクトをブロックとして渡す場合には引数の前に&が必要です。

square = Proc.new { |x| x ** 2 }
[1, 2, 3, 4, 5].map(&square) # Procオブジェクトを渡しているので`:`はつかない
#=> [1, 4, 9, 16, 25]

また、メソッドをブロックとして渡す場合は一度to_procでProcオブジェクトに変換する必要があります。

class Integer
  define_method :square do
    self ** 2
  end
end

square = :square.to_proc # ①

[1, 2, 3, 4, 5].map(&square)
#=> [1, 4, 9, 16, 25]

(&:method)を解読する

前知識を踏まえていよいよ(&:)を解読してみます。

例のコードを読んでみる

例に挙げたコードをもう一度貼っておきます。

%w(urasoe naha ginowan).map(&:upcase)
=> ["URASOE", "NAHA", "GINOWAN"]
  1. &に:upcaseが渡されます
  2. &修飾に:methodを渡すと①で見たProcオブジェクトへの変換が行われます。つまり、シンボルのメソッドに対しto_procが呼び出されます
  3. :upcaseが変換されたProcオブジェクトとなります
  4. 3で変換されたProcオブジェクトがブロックとしてmapに渡されます
  5. その後Procの節で見たように、Procオブジェクトとなったupcase.call()引数に配列の各要素を受け取ります
  6. mapメソッドはProcオブジェクトを実行した戻り値を新たな配列に追加します

上記のような流れを経て(&:method)は動いているのですね。

まとめ

メタプログラミングRubyやチェリー本を読んで面白かったので自分なりに(&:method)について整理してみました。
よきRubyライフを💎

参考

【リーダブルコード】第五章 コメントすべきことを知る の要約

コメントすべきでないこと、すべきなこと

コメントの目的とはなんでしょうか?
それは書き手の意図を読み手に知らせることです。
ただし、全ての意図をコメントすればいいわけではありません。
コメントを読むということはその分だけコードを読む時間が減るので、書くならばコードを読むより価値がある必要があります。
以下ではコメントすべきでないこと、すべきことを見ていきます。

コメントすべきでないこと

  • コードからすぐにわかることを書かない
    例えば以下のようなコメントが該当しそうです。
# 引数を二つ与えて、その合計を返す関数
def total(a, b)
   a + b
end

total(2, 5)
#=> 7
  • ひどい名前を補足するようなコメントを書かない
    ひどい名前ならその名前を変えることをまず検討すべきです。
    ひどいコードに優れたコメントをつけるより、優れたコードを目指しましょう💪

コメントすべきこと

  • 自分の考え
    優れたコメントというのは考えを記録するためのものと定義されています。
# a, b, cの3つの手段を試したが、bが最も計算量を抑えることができたので、この実装にしている

みたいなことでしょうか。

  • コードの欠陥
    コードの欠陥にはコメントを残しておきましょう。
    後でプロジェクト内で探しやすいようにprefixをつけておくと便利です。
記法 意味
TODO: 後で手を付ける
FIXME: 不具合がある
HACK: 無理矢理解決している
WARN: 問題あり
MEMO: 実装メモ
# TODO: クエリ減らす

# HACK: N+1発生してる

# WARN: セキュリティホールあり
  • 定数
    定数を定義する時には、おぼろげながらに浮かんでくることはありません。必ず何かしらの意味や背景があるはずです。
    1クラス最大40人であれば以下のようになるでしょうか。
# 1クラスは最大40人
MAX_STUDENT = 40
  • プロジェクトに途中から入る人に説明するようなこと
    他の人にコードがどのように見えるか想像し、その人がどこで疑問を持ちそうか、どこで間違えそうかを考えて全体の要約コメントを残してあげるのが良さそうです。
    ここでいう他の人とは、プロジェクトを熟知していない人のことです。

ライターズブロック

プログラマがコメントを書きたがらないのは、コメントをうまく書くのは大変だと思っているからだそう。
こうした「ライターズブロック(行き詰まってしまって文章が書けないこと)」を解消するための手順が紹介されていた。
(エントリーを書く時にも使えそう🤔)

  1. 頭の中にあるコメントをとにかく書き出す(例:とんでもない数のクエリが飛んどる)
  2. コメントを読んで改善が必要なものを見つける(とんでもない→すごい数の、飛んどる→発行されている)
  3. 改善する(すごい数のクエリが発行されている)

終わりに

上記のことを実践していくことで、適切なコメントによる優れたコード、他の人が読んだ時に理解まで最短であるコードを実現できそうですね💪

【リーダブルコード】第四章 美しさ の要約

優れたソースコードは「目に優しい」

見た目が美しいコードの方が読みやすいはずですよね。
改行やインデントがメチャクチャなコードは大変読みにくいです。
この章では見た目的にコードを読みやすくするための三つの要素と原則が紹介されています。

要素

  • 余白
  • 配置
  • 順序

原則

  • 一貫性のあるレイアウト
  • 似ているコードは似ているように
  • 関連するコードをまとめてブロックに

一貫性のあるレイアウト

以下はscaffoldで生成したuser_controller#create一貫性のないレイアウトにしたものです。

  def create
    @user = User.new(user_params)
    respond_to do |format|
      if @user.save
                format.html { 
                  redirect_to user_url(@user),
                              notice: 
                    "User was successfully created." 
                }
        format.json { render :show,     status: :created, location: @user }
      else
        format.html { render :new, status: :unprocessable_entity }
                  format.json { render        json: @user.errors,       status:                :unprocessable_entity }
      end
    end
  end

んー読みにくい。
このコードを直していきましょう。

まず、一貫性のあるレイアウトにするためにインデントを修正します。

  def create
    @user = User.new(user_params)
    respond_to do |format|
      if @user.save
        format.html {
          redirect_to user_url(@user),
                          notice:
                "User was successfully created."
          }
        format.json { render :show,     status: :created, location: @user }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render        json: @user.errors,       status:                :unprocessable_entity }
      end
    end
  end

formatの位置が揃ったことで見やすくなりました。
次にスペースの位置を揃えましょう。

  def create
    @user = User.new(user_params)
    respond_to do |format|
      if @user.save
        format.html {
          redirect_to user_url(@user),
                          notice:
                "User was successfully created."
          }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

render以下の位置が揃ったことで見やすくなりました。
ただ、if文の中にある一つ目のformat.htmlの改行が不適切で、似ているコードは似ているようにの原則が守られていないので修正しましょう。

  def create
    @user = User.new(user_params)
    respond_to do |format|
      if @user.save
        format.html { redirect_to user_url(@user), notice: "User was successfully created." }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

これで似ているコードが似ている形になりましたね。
最後に意味のある段落分けをしましょう。

  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to user_url(@user), notice: "User was successfully created." }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

変数に値を入れているところと、respondを段落分けすることで処理がみやすくなりました💪

他にもコードを見やすくする方法として

  • 宣言をブロックにまとめる
  • 繰り返し使ってる処理をメソッドにする

などがありました。

最後に重要な考えとして、プロジェクトにアサインしているのであれば、個人の好みよりプロジェクトの規約を大事にすべき(一貫性)というものがありました 👀
仮に規約が一般的でないものだとしても、一貫性が大事ということですね 💪