@ka2n

Technology and beer

デフォルトブランチを変更したらgit gcでエラーが出るようになった

git gcが実行された時に以下のエラーが出るようになってしまった。

fatal: bad object refs/remotes/origin/HEAD
fatal: failed to run repack

特に特別な事はしていないし、順調にリポジトリが成長していっているだけなんだけどなぜだろう。

cat .git/refs/remotes/origin/HEAD
=> ref: refs/remotes/origin/master

数ヶ月前にデフォルトブランチをmasterからmainに変更したんだけどなぜいまさら? 単に自動でgit gcされていなかっただけかな。

echo "refs/remotes/origin/main" > .git/refs/remotes/origin/HEAD

として解決した。まぁ最悪ローカルが壊れても困らないので雑に対処した。

ruby: 全角スペースなども含めてString.trimする

終端の空白や改行を削除するためにString.trimを使うことがあると思いますが、これには全角スペースは含まれません。POSIX文字クラスには便利は[:space:]というものがあるのでこれを使うと良いです。

def strip(input)
  input.gsub(/[[:space:]]+\z/)
end

\zを使わずに$を使うと行末になってしまい、途中に改行が含まれている場合にも置換されてしまうので注意。 あるよね、謎の大量の空白。

Wi-Fi中継器を導入したらうまくDHCPでアドレスが振られない不具合に遭遇したがよくわからないまま解決した

作業部屋からAPまでが遠いせいで受信強度が不安定で、速度にも影響が出ていたのでWi-Fi中継器を導入した。

それなりに使えている気がしたのだけど、たまにiPhoneなどでWi-Fiネットワークには接続できているように見えるが、実際はネットワークに繋らない。といいった現象になっているので調べてみた。 iOSの画面上ではDHCPサーバによって割り当てられるはずのIPアドレスがいつまでたっても降ってこない。そのため通信できない状況になっているようだ。

調べてみると以下のような記事をみつけた。

www.buffalo.jp

superuser.com

A client that cannot receive unicast IP datagrams until its protocol software has been configured with an IP address SHOULD set the BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or DHCPREQUEST messages that client sends. The BROADCAST bit will provide a hint to the DHCP server and BOOTP relay agent to broadcast any messages to the client on the client's subnet. A client that can receive unicast IP datagrams before its protocol software has been configured SHOULD clear the BROADCAST bit to 0. The BOOTP clarifications document discusses the ramifications of the use of the BROADCAST bit [21].

RFC 2131 - Dynamic Host Configuration Protocol

なるほど(わからん)、rfc2131によるとDHCPOFFERはユニキャストで送信されることがあるようだ。 中継器はブロードキャストでないとそのパケットを受け取れないので実際のクライアントまでDHCPOFFERを取り次げない。ということかな...?

使っているルーターを調べてみたが、どのオプションにあたるのか全然わからなかった。

15.1.2 RFC2131 対応動作の設定


とりあえず、中継器のIPアドレスだけでも固定割当にしとくかー。と設定した所で、問題なく動くようになってしまった。これが問題を解決しているのかわかっていない。が、元々固定割り当てにするつもりだったので本来は遭遇しない問題なんだろう。。。今は気にしない事にする。

ReactコンポーネントからRailsのフォームの送信ボタンを無効化する

Railsベースのフォームの中に一部の入力欄でReactコンポーネントを使うことが稀にあるかもしれません。

入力欄がinvalidな状態なのに送信ボタンはReact外で困る。。。

そいういった時は、さくっと送信ボタンのDOMを探して操作しても良いですが、Rails自体(rails-ujs)の仕組みを利用することで再利用性が上がると思います。

以下のコード例のようにhookを作成し、Reactコンポーネントでのバリデーション状態を元に送信ボタンを有効化/無効化しています。(別にhooksじゃなくてnullを返すコンポーネントでももちろん良いです。)

import Rails from "@rails/ujs"
import { useEffect, useRef } from "react"

/** Railsのフォームの送信ボタンを@rails/ujsを使って有効/無効化します
 */
export const useRailsFormValidation = (valid: boolean) => {
  const containerRef = useRef<HTMLInputElement>(null)
  useEffect(() => {
    if (!containerRef.current) return

    const form = containerRef.current.form
    valid ? Rails.enableElement(form) : Rails.disableElement(form)
  }, [valid])

  return {
      containerRef,
  }
}

使用時はこんな感じ

const VeryComplexInput:  React.FC<...> = props => {
  const { valid, onChange, value, ..... } = useSomeForm({...}) // フォームのイベントハンドリングをしていると想定

  const { containerRef } = useRailsFormValidation(valid)
  return (
    <>
      <input type="hidden" ref={containerRef} /> // フォームを探すためのinput
      ....
    </>
  )
}