CSSで目的の操作をするときに何度もググらずにベストな参考サイトに遷移するための一覧が欲しいなと思ったので 良いなと思ったサイトや記事をまとめておくことにする。 まだ始めたばかりなので何もコンテンツが無いけど、随時更新を予定。
AWS:IAMユーザーにMFA更新権限を追加する
AWSのドキュメント迷宮すぎてマジ苦手。
課題
AWSにIAMユーザーを追加したがMFA認証の設定権限がないと言われた。どうすればよいか。
対応
既存のポリシー名をMFAで検索しても出てこないのでMFAをサクッと可能にするデフォルトポリシーがないっぽい。 なのでまずポリシーの作成が必要
作成を選んだらJSONタブを選択して以下のURLの内容をコピる
重要
上記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
この方法より個別にシェル書いた方が安全という記事も見つけたがそれはまた別の話ということで。
参考
- rails crontab rake javascript runtime not find - Stack Overflow -> nodeにパスを通せ、というのがヒントに
- Crontab で source ~/.bashrc や bash -l を使うと死を招く - Qiita -> なるほど
- bash - Bashrc, shell script and crontab - Ask Ubuntu
-> Ubuntuはインタラクティブじゃないと
.bashrc
を実行しないぜ、という話が書いてあった。
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
参考
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 } }
おまけ
完全に諦めて上記方法で実装して終わりにしようと思ったところ、
最後の最後についに問題を解決。助かった...。