前人未踏の領域へ WEB・インフラ・プログラミング全般編

フロントエンド、バックエンド、インフラ、言語など、アプリ開発、IOT以外の記録

CSS:参考記事一覧

CSSで目的の操作をするときに何度もググらずにベストな参考サイトに遷移するための一覧が欲しいなと思ったので 良いなと思ったサイトや記事をまとめておくことにする。 まだ始めたばかりなので何もコンテンツが無いけど、随時更新を予定。

全体

developer.mozilla.org

中央揃え

coliss.com

AWS:IAMユーザーにMFA更新権限を追加する

AWSのドキュメント迷宮すぎてマジ苦手。

課題

AWSにIAMユーザーを追加したがMFA認証の設定権限がないと言われた。どうすればよいか。

対応

既存のポリシー名をMFAで検索しても出てこないのでMFAをサクッと可能にするデフォルトポリシーがないっぽい。 なのでまずポリシーの作成が必要

作成を選んだらJSONタブを選択して以下のURLの内容をコピる

docs.aws.amazon.com

重要

上記URLの内容をコピーしただけだと、アカウント追加後にIAMユーザーがパスワード変更ができなくなる。 なので一番最後の箇所に "iam:IAMUserChangePassword" を追加する

{
            "Sid": "BlockMostAccessUnlessSignedInWithMFA",
            "Effect": "Deny",
            "NotAction": [
                "iam:CreateVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:ListMFADevices",
                "iam:ListUsers",
                "iam:ListVirtualMFADevices",
                "iam:ResyncMFADevice",
                "iam:IAMUserChangePassword"
            ],
            "Resource": "*",
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "false"
                }
            }
        }

内容を吟味し(あるいは無条件に信じて)、ポリシーの確認ボタンを押下。 ポリシーを作成したら任意のアカウントなりグループなりにアタッチすればOK.

Rails: Cronジョブ実行時にExecJSでエラー

課題

RailsのJobを実行する処理をcrontabに記述したがExecJSでJavaScriptの実行環境が見つからないとエラーになる。

bundler: failed to load command: bin/rails (bin/rails)
ExecJS::RuntimeUnavailable: Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes.
  /var/rails/milestone/shared/bundle/ruby/2.6.0/gems/execjs-2.7.0/lib/execjs/runtimes.rb:58:in `autodetect'
  /var/rails/milestone/shared/bundle/ruby/2.6.0/gems/execjs-2.7.0/lib/execjs.rb:5:in `<module:ExecJS>'
  /var/rails/milestone/shared/bundle/ruby/2.6.0/gems/execjs-2.7.0/lib/execjs.rb:4:in `<main>'

Nodeはインストール済みだし、ExecJSからも見えている。直接consoleからJobを実行することはできる。 なんなら別な環境では普通に動く。

原因

cronのpathに /usr/local/bin が通っていなかった。cronの初期状態のPATHは /usr/bin:/bin となっている(Ubuntuの場合)が、 Nodeを直接インストールすると /usr/local/bin/node が実行パスになる。

ちなみに、 apt経由で8.10系をインストールした場合はパッケージ名が nodejs でコマンドも node ではなくnodejsになり、 こちらの実行パスは /usr/bin/nodejs となるため、cronで発見される。 別な環境で動いたのはたまたまこちらがインストールされていたため。 ExecJSはこのどちらも探しにいくが、node が優先される。

対応

/usr/local/bin をPATHに連結させて解決。

# ~/.bash_profile
export PATH="$PATH:/usr/local/bin"

crontabに /bin/bash -lc くっつけてcronの実行者の.bash_profile を読み込ませる。

# crontab -e
0 9 0 0 0 /bin/bash -lc {command} > /var/log/cron.log 2>&1

この方法より個別にシェル書いた方が安全という記事も見つけたがそれはまた別の話ということで。

参考

GitHub チームアカウントのシート数を4以下にする

GitHubのチームアカウントは5アカウントからの購入となっており、実際に利用するユーザー数がそれに満たない場合でも 最低5ユーザー分の料金がかかる。

......と思っていたが違った。

SettingsBilling から GitHub TeamEditボタンを押下し、Remove Seats を押すと シート数を減らすことができた。

最近の値下げとも相まって月額がわずか$4に。 一人で使ってるならFreeプランでいいじゃんという気もするけど。Wikiとか使えなくなるし。

f:id:takeR:20200504210238p:plain

長いこと無駄に余分なお金払ってきてたな〜。

Rails destroyがdependent: :destroy から呼ばれたかどうかを知るには

課題

あるテーブルがすべて削除されたタイミングで親のテーブルを削除したい。 これを子テーブルのモデル側でやろうとすると、そのモデルの after_destroy で、belongs_to 関連を持つ親テーブルを 削除することになる。

これは普通に上手くいくが、楽観的排他を採用していた場合、親テーブルを直接 destory しようとした際にエラーとなる。 そこで親の dependent: :destroy によって destroy が呼ばれた場合には処理が実行されないようにしたい。どうすればよいか。

対応

destroyed_by_association を使うと削除されようとしている親のオブジェクトが返却されるので、それを利用する。

  after_destroy :destroy_parent

  private

  def destroy_parent
    # dependent: :destory 以外の場合のみ実行
    unless destroyed_by_association
       # 子が空になったら親を削除する
       self.hoge.destroy if self.hoge.children.empty?
    end
  end

参考

stackoverflow.com

apidock.com

Vue.js プロパティの変更をデータに反映する

課題

Vuexでstateを管理していて、stateの変更によって 親コンポーネントで変更した内容を子コンポーネント(state未使用)に 反映したいが変更されたプロパティがデータに反映されなかった。どうすればよいか。 ちなみに親から渡されるプロパティはオブジェクトである。

対応

汎用の子コンポーネントを使いたい場合、stateの値を使うのではなく親からプロパティ渡しで 値をもらいたい事もあるだろう。プロパティをコンポーネントで使う際にデータにセットすることができるが、 初期値として使われるだけである。

props: {
    value: {
      type: Object,
      required: false,
      default: () => ( { code: '', name: '' } )
    },
},
data() {
    return {
        searchText: value.name
    }
}

ここでvalue内のcodeやnameを更新してもstateの内容は変わるが dataは更新されず、表示が切り替わらなかった。 そこで、プロパティの値をwatchで監視してあげることにする。

props: {
    value: {
      type: Object,
      required: false,
      default: () => ( { code: '', name: '' } )
    },
},
data() {
    return {
        searchText: value.name
    }
}
watch: {
    value(v) {
        this.searchText = v.name
    }
}

こうすることでプロパティの変更をデータに伝えることができ、 データの変更を検知してビューが変更される。

Vue.js 強制的に再レンダリングする

課題

vuexのstateオブジェクトを更新したが画面に反映されない。
とりあえず現状のオブジェクトの内容で画面を更新したい。

注意

stateオブジェクトの更新が反映されなくなったら、まず最初にオブジェクトの構成が変わってしまっていることを 疑うべし。最初に生成したstateとAPIのレスポンスをそのまま突っ込んでいる場合、ネストしたオブジェクトのプロパティの数が 違っていたりすると変更を検知してくれない。してくれないどころか、 その構造のずれに気づかないでいると他の処理にまで悪影響が及ぶようになるので注意が必要。

対応

本来はちゃんと再描画されるような更新の仕方が必要なのだけど、
どうにも上手くいかない。工数的にも時間が足りない。というケースでの応急処置。

コードは参考サイトのものをほぼそのまま採用。

コンポーネントのルート要素にkeyを定義する

<template>
  <div :key="componentKey">
  </div>
</template>

再描画したいタイミングで keyを更新する

keyの値が更新された時点で小ビューの再描画が行われるので stateオブジェクトの状態が反映されることになる。

methods: {
    forceRerender() {
      this.componentKey += 1
    }
}

おまけ

完全に諦めて上記方法で実装して終わりにしようと思ったところ、
最後の最後についに問題を解決。助かった...。

参考

michaelnthiessen.com

/* Responsive: yes */