prependでクラスメソッドを拡張する
singleton_classにprependすればOK。
class Hoge def self.hogehoge(*args) puts 'hogehoge' end end Hoge.hogehoge # => hogehoge Hoge.singleton_class.prepend Module.new { def hogehoge(*args) super(*args) puts 'extended hogehoge' end } Hoge.hogehoge # => hogehoge # => extended hogehoge # 継承ツリー Hoge.ancestors # => [Hoge, Object, Kernel, BasicObject] Hoge.singleton_class.ancestors # => [#<Module:0x007fc15e090f70>, #<Class:Hoge>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject] class SomeClass class << self def some_classmethod "Hello" end end end SomeClass.some_classmethod #=> Hello
singleton_class(特異クラス)とは、
すべてのオブジェクトが持つ自分だけの隠しクラスのこと。
インスタンスに独自に定義したメソッド(特異メソッド)は、
この特異クラスに定義しているという扱いらしい。
参考
https://qiita.com/ponoda/items/bfcf5533b532a6d32111
https://allabout.co.jp/gm/gc/453836/#note1
複数のサーバで一度にsshコマンドを実行したい
メモ。
HOSTS="host01 host02 host03" for host in ${HOSTS}; do echo $host ssh -t $host <<EOC hostname sudo service td-agent restart sleep 1 ps aux | grep td-agent EOC echo "--------------------" done
既存RailsアプリにRspecを入れる
インストール
Gemfileに追記
group :development, :test do gem 'rspec-rails' gem 'factory_bot_rails' gem 'database_cleaner' end
RSpecの設定
必要なファイルが作成される。
bundle install
bundle exec rails generate rspec:install
設定をする
config/application.rb
# config/application.rb config.generators do |g| # 不要なファイルを生成しない g.test_framework :rspec, fixtures: true, view_specs: false, helper_specs: false, routing_specs: false, controller_specs: true, request_specs: false # テストデータのパス設定 g.fixture_replacement :factory_bot, dir: "spec/factories" end
spec/rails_helper.rb
# spec/rails_helper.rb RSpec.configure do |config| # 略 # user = FactoryBot.create(:user) -> user = create(:user) とかけるようにする config.include FactoryBot::Syntax::Methods # Time.zone.nowを、スライドできるようにする config.include ActiveSupport::Testing::TimeHelpers end
spec/spec_helper.rb
# spec/spec_helper.rb require 'database_cleaner' # 略 RSpec.configure do |config| # 略 # テスト後にDBのデータを消す設定 config.before(:suite) do DatabaseCleaner[:active_record].strategy = :transaction DatabaseCleaner.clean_with(:truncation) end config.around(:each) do |example| DatabaseCleaner.cleaning do example.run end end # 略 end
テストデータ/テストコードを書く
development環境のDB構造をtest環境へクローンする
bundle exec rake db:test:clone
テストデータを作る
# spec/factories/my_app/subscription.rb FactoryBot.define do # class: でどのクラスのインスタンスを作るか指定できる factory :subscription, class: ::MyApp::Subscription do user_id 1 course_id 1 status nil # 引数で与えられた値で属性を変えることができる trait :trial do status :trial end trait :contracted do status :contracted end # 関連テーブルも一緒に作る場合 trait :with_entitlements do after(:build) do |subscription| subscription.entitlements << FactoryBot.build(:entitlement__svod) end end end end
テストコードを書く
# spec/models/my_app/subscription_spec.rb require 'rails_helper' describe ::MyApp::Subscription do before do # createはDB保存された状態のインスタンスを作る # beforeで定義した変数はインスタンス変数にしないと内部で参照できない @user = create(:user) end describe 'お試し契約する (テスト対象を書く)' do context '契約可能期間のとき (条件を書く)' do before do # 引数つきで属性を変える / buildeだとDB保存はしない @subscription = build(:subscription, :trial, :with_entitlements) end it '保存できる (期待する結果を書く)' do result = @subscription.save expect(result).to be_truthy # expect(result).to eq true でもOK end end context '契約可能でない期間のとき' do before do @subscription = build(:subscription, :trial, :with_entitlements) end # 時間移動はaroundでも書ける # around do |e| # travel_to('2016-2-29 10:00'.to_time){ e.run } # end it '保存できない' do # このブロック内でTime.zone.nowが1年後になる travel 1.year result = @subscription.save expect(result).to be_falsey # travel_back すると Time.zone.nowが戻る end end end end
実行する
# ファイル指定 bundle exec rspec spec/models/my_app/subscription_spec.rb # ディレクトリ以下実行 bundle exec rspec spec/
nslookupメモ
使い方
nslookup www.google.com Server: 192.168.135.1 # 問い合わせたDNSサーバのIP(LAN内のDNSサーバ) Address: 192.168.135.1#53 # 上記 + ポート番号 Non-authoritative answer: # キャッシュDNSサーバがレスしたの意味 Name: www.google.com Address: 216.58.197.196 # ドメインに紐づくIPアドレス # ---------- nslookup www.google.com 8.8.8.8 # 問い合わせるDNSサーバを指定することも可能
オプション
-type タイプ 表示内容をmx(MXレコード、mail exchange)、ns(name server)、soa(start of authority)で指定する -port 番号 使用するポート番号を指定する(デフォルトは53) -timeout 秒数 タイムアウトの値を設定する -debug 問い合わせの内容を表示する
Dockerの基本的な使い方メモ
Dockerを触ることになったので、基本的な使い方をメモしておく。
用語
イメージ: コンテナのベースとなるファイル群
コンテナ: イメージから作成されたインスタンス
pullできるdockerのイメージはここから確認できる
https://hub.docker.com/explore/
基本的なコマンド
# イメージの取得 docker pull keymetrics/pm2 # イメージの確認 docker images # イメージからコンテナを作成 # 末尾のコマンドを指定すると起動時に実行される。 # 指定しないとDockerfileで指定したCMDが実行される。 docker run --name [コンテナ名] -d [イメージID] /sbin/init # コンテナにログイン(exitでログアウト) docker exec -it [コンテナ名] /bin/sh # コンテナの一覧 docker ps -a # コンテナを起動する docker start [コンテナ名] # コンテナを止める docker stop [コンテナ名] # コンテナを削除する(事前にstopしておく必要がある) docker rm [コンテナ名] # イメージの削除 docker rmi [イメージID] docker rmi -f [イメージID] # 強制削除
こちらで勉強させていただきました。
https://qiita.com/butada/items/3e6cd338cb703eef64b4
Dockerfile作る
↓みたいな感じでDockerfileを作る
FROM keymetrics/pm2:8-alpine # 使用するイメージ ARG app_dir=/usr/src/app # 変数の定義 WORKDIR ${app_dir} # 以下のコマンドをこのディレクトリで実行する ENV DEBIAN_FRONTEND noninteractive # 環境変数の設定 入力待ちでブロックしなくなる ENV TZ JST-9 # 環境の設定 タイムゾーンをJSTにする RUN apk add --update perl # perlのインストール(Alpine Linuxのコマンド) # COPYでローカルのファイルをコンテナへコピー # RUNでシェルを実行 COPY ./package.json . COPY ./yarn.lock . COPY ./tools ./tools COPY ./.npmrc . COPY ./public ./public COPY ./ecosystem.config.js ./ecosystem.config.js RUN touch ./public/healthCheck.html RUN yarn install --production --no-progress COPY build/public/assets/ public/assets COPY build/server.js . COPY build/assets.json . # 以降の実行をnodeユーザで行う # CMDはコンテナ実行時のコマンド。Dockerfileの中では1度だけ指定できる。ここではpm2を起動している。 USER node CMD [ "pm2-runtime", "start", "ecosystem.config.js", "--env", "production", "-i", "max"]
Dockerfileのあるディレクトリで実行することで、記載された内容に基づいてイメージを作る。
docker build .
他メモ
## --rmオプションつきで起動して終了するとコンテナ破棄する docker run --rm -t -i ubuntu /bin/bash # ポートフォワード # -pオプションで、外部からアクセスされるポート番号:コンテナ側のポート番号を指定 # -dオプションはバックグラウンドで実行 $ docker run --name some-nginx -d -p 8080:80 nginx
PostgreSQLのEXPLAINについて
PostgreSQLで重たいクエリの調査したときのメモ。
EXPLAINについて
EXPLAINは問い合わせプランを表示するコマンド。
PosgreSQLではSQL実行前に、プランナで問い合わせの実行コストを見積もり、
最小コストの問い合わせプランを算出する(問い合わせの最適化)。
問い合わせプランとは、
・どの方式でテーブルを検索するか
・複数のテーブルがある場合はどの順序や結合方式で検索するか
などを記述したもの。
実行してみる
EXPLAINと先頭につけることでコストが表示される。
cost=初期コスト..トータルコスト の意味。トータルコストの値が重要。
シーケンシャルI/Oで1ページ読み込みコストを1.0とした場合の相対値として表示。
EXPLAIN SELECT * FROM articles ORDER BY articles.id DESC NULLS LAST; QUERY PLAN ------------------------------------------------------------------------------------------------------ Gather Merge (cost=12167.24..13390.38 rows=10636 width=1588) Workers Planned: 1 -> Sort (cost=11167.23..11193.82 rows=10636 width=1588) Sort Key: id DESC NULLS LAST -> Parallel Seq Scan on articles (cost=0.00..3109.36 rows=10636 width=1588)
ANALYZE で 実際の実行時間を表示できる 。
(actual time=158.749..188.486 rows=18081 loops=1)
loopsは処理の繰り返し回数。timeは繰り返し全体の時間を表す。
EXPLAIN ANALYZE SELECT * FROM articles ORDER BY articles.id DESC NULLS LAST; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------- Gather Merge (cost=12167.24..13390.38 rows=10636 width=1588) (actual time=158.749..188.486 rows=18081 loops=1) Workers Planned: 1 Workers Launched: 1 -> Sort (cost=11167.23..11193.82 rows=10636 width=1588) (actual time=144.924..153.350 rows=9040 loops=2) Sort Key: id DESC NULLS LAST Sort Method: external merge Disk: 12256kB -> Parallel Seq Scan on articles (cost=0.00..3109.36 rows=10636 width=1588) (actual time=0.049..40.413 rows=9040 loops=2)
EXPLAIN演算子について
テーブルスキャン
Seq scan
インデックスを使わず。全件検索。
Index scan
インデックスを使用してスキャン。
Bitmap scan
ビットマップを使用してスキャン。
ORのときにに有効。インデックスを使って検索した結果をビットマップとして保持し、ビットマップ同士でOR演算する方式。
結合
Nested Loop
ネステッドループ結合を行う。
外部テーブルを1レコードずつ取り出し、その都度内部テーブルの全レコードとマッチングして結合していく方式。
データが小さい場合に向いている。
Merge join
ソート・マージ結合を行う。
事前に両方のテーブルを結合キーでソートし、両方のテーブルを先頭からマッチングしていく方式。→ テーブルを1回調べればよいので、テーブルの操作回数が減る。
データ量が多い場合に向いている。
Hash Join
ハッシュ結合を行う。
事前に内側テーブルのハッシュ表をメモリに読み込み、外側テーブルとハッシュ表を突き合わせて結合。→ メモリ内のハッシュ表の検索は高速。
ソートメモリが十分にある場合に向いている。
制御
・set enable_hashjoin to off を実行すると、プランナはマージ結合を選択する。
・さらに set enable_mergejoin to off を実行すると、プランナはネスト化ループ結合を選択する。
こちらのスライドで勉強させていただきました。
https://www.slideshare.net/MikiShimogai/postgre-sql-explain
sidekiq-unique-jobsのunique値ごとの挙動
ちょっと古いけど、sidekiq-unique-jobs v4.0.8のunique値ごとの挙動を確認したのでメモしておく。
GitHub - mhenrixon/sidekiq-unique-jobs at v4.0.8
while_executing
同じargsは実行中にならない。
同じargsを実行しようとしたらworkerは待ちになる。後続を処理せずに待つ。
同じargsのキューはされる
until_and_while_executing
同じargsは実行中にならない。
同じargsを実行しようとしたらworkerは待ちになる。後続を処理せずに待つ。
同じargsが待機状態になっているときはキューされない。
until_executed
同じargsは実行中にならない。
同じargsを実行しようとしたらworkerは待ちになる。後続を処理せずに待つ。
同じargsが待機状態、または実行中のときはキューされない。