ひびきの技術メモ帳

駆け出しエンジニアのメモ帳

CDK&AWS Lambda お手軽API作成

こんなもの作れます

https://cgo3wctz6upknfwfyltvlrhsea0mpiyy.lambda-url.ap-northeast-1.on.aws/?text=konkoncha

ここにアクセスするとクエリに渡されたtextの文字をヒエログリフに変換して返してくれます

AWS CLIでアクセスキーなどを設定する

AWS CLIのインストール

brew install awscli

キーの設定

aws configure

アクセスキーなどを入力すると~/.awd/config/に登録されます

CDKのセットアップ

CDKのインストール

npm install -g aws-cdk

CDK用の作業ディレクトリ作成

mkdir ~/適当なディレクトリ/CDK用のディレクトリ && cd ~/適当なディレクトリ/CDK用のディレクトリ

※空のディレクトリじゃないとCDKの初期化コマンドが失敗します

初期化

cdk init app --langage typescript

CDKのデプロイに必要なディレクトリが作られます

.
├── README.md
├── bin
├── cdk.json
├── jest.config.js
├── lib
├── node_modules
├── package-lock.json
├── package.json
├── test
└── tsconfig.json

lambda用の処理を記述

import { Stack, StackProps } from "aws-cdk-lib";
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { FunctionUrlAuthType, HttpMethod } from "aws-cdk-lib/aws-lambda";

export class HieroRubyStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const url = new lambda.Function(this, 'MyFunction', {
      runtime: lambda.Runtime.RUBY_2_7,
      handler: 'main.lambda_handler',
      code: lambda.Code.fromAsset('./app'),
    });

    url.addFunctionUrl({
      authType: lambda.FunctionUrlAuthType.NONE,
    });
  }
}

appディレクトリを作ってrubyの処理を記述

require 'json'

def lambda_handler(event:, context:)
    hash = { A: ["1313F"], B: ["130C0"] , C: ["133A1"], D: ["130A7"], E: ["131CB"], F: ["13191"], G: ["133BC"], H: ["1339B"], I: ["131CB"], J: ["13193"], K: ["133A1"], L: ["130ED"], M: ["13153"], N: ["13216"], O: ["1336F"], P: ["133E4"], Q: ["133D8"], R: ["1308B"], S: ["132F4"], T: ["133CF"], U: ["13171"], V: ["13191"],W: ["13171"], X: ["133A1", "132F4"], Y: ["131CB"], Z: ["13283"] }
    text = get_text(event)
    result = text && text.upcase.split("").map{ |string| hash[string.to_sym] ? hash[string.to_sym].map{ |s| s.hex.chr(Encoding::UTF_8)} : string }.join
    { statusCode: 200, body: result }
end

def get_text(event)
  if event["requestContext"]["http"]["method"] == "POST"
    JSON.parse(event["body"])["text"].to_s
  elsif event["requestContext"]["http"]["method"] == "GET"
    event["rawQueryString"].split("&").map{ |string| string.split("=") }.to_h["text"]
  end
end

クエリの受けとり方

event["rawQueryString"]で受け取れる

bodyの受け取り方

event["body"]で受け取れる

デプロイ

cdk deploy

meishi2のキーマップをQMK Firmwareを使って書き換えるメモ

環境

QMK Firmwareをインストール(brew経由でいけたっぽいからそっち使えばよかった)

git clone https://github.com/qmk/qmk_firmware.git
#下記コマンドでbrewのupgradeが入りました(長かった)
./util/qmk_install.sh

キーマップを書き換えるために設定をコピー

qmk new-keymap
#keymapの名前を入力するように言われます今回はcustom_keymapにしました

キーマップを編集

keyboards/biacco42/meishi2/keymaps/custom_keymap/keymap.cファイルを編集します 今回はデフォルトのやつ(コピペとか)からただの文字を出力するように変えてみます

/* Copyright 2019 Biacco42
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include QMK_KEYBOARD_H

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  [0] = LAYOUT( /* Base */
    KC_Z,  KC_X,  KC_C, KC_V
  )
};

コンパイル

下記コマンドを打ってコンパイル

qmk compile -kb biacco42/meishi2 -km custom_keymap

エラーが出た

Ψ Compiling keymap with gmake --jobs=1 biacco42/meishi2:custom_keymap


QMK Firmware 0.17.9
WARNING: Some git submodules are out of date or modified.
 Please consider running make git-submodule.

Making biacco42/meishi2 with keymap custom_keymap

tmk_core/protocol/lufa.mk:13: lib/lufa/LUFA/makefile: No such file or directory
gmake[1]: *** No rule to make target 'lib/lufa/LUFA/makefile'.  Stop.
gmake: *** [Makefile:413: biacco42/meishi2:custom_keymap] Error 1
Make finished with errors

指示通りに下記コマンドを打つ

make git-submodule

実行結果

❯❯❯make git-submodule                                                                                         [master]
QMK Firmware 0.17.9
Submodule 'lib/chibios' (https://github.com/qmk/ChibiOS) registered for path 'lib/chibios'
Submodule 'lib/chibios-contrib' (https://github.com/qmk/ChibiOS-Contrib) registered for path 'lib/chibios-contrib'
Submodule 'lib/googletest' (https://github.com/qmk/googletest) registered for path 'lib/googletest'
Submodule 'lib/lufa' (https://github.com/qmk/lufa) registered for path 'lib/lufa'
Submodule 'lib/printf' (https://github.com/qmk/printf) registered for path 'lib/printf'
Submodule 'lib/vusb' (https://github.com/qmk/v-usb) registered for path 'lib/vusb'
Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/chibios'...
remote: Enumerating objects: 241811, done.
remote: Counting objects: 100% (555/555), done.
remote: Compressing objects: 100% (259/259), done.
remote: Total 241811 (delta 374), reused 394 (delta 294), pack-reused 241256
Receiving objects: 100% (241811/241811), 157.10 MiB | 24.06 MiB/s, done.
Resolving deltas: 100% (184417/184417), done.
Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/chibios-contrib'...
remote: Enumerating objects: 22528, done.
remote: Counting objects: 100% (2835/2835), done.
remote: Compressing objects: 100% (787/787), done.
remote: Total 22528 (delta 2205), reused 2455 (delta 2007), pack-reused 19693
Receiving objects: 100% (22528/22528), 9.11 MiB | 19.03 MiB/s, done.
Resolving deltas: 100% (14528/14528), done.
Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/googletest'...
remote: Enumerating objects: 22998, done.
remote: Total 22998 (delta 0), reused 0 (delta 0), pack-reused 22998
Receiving objects: 100% (22998/22998), 9.01 MiB | 18.95 MiB/s, done.
Resolving deltas: 100% (16989/16989), done.
Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/lufa'...
remote: Enumerating objects: 76739, done.
remote: Counting objects: 100% (3089/3089), done.
remote: Compressing objects: 100% (73/73), done.
remote: Total 76739 (delta 3041), reused 3020 (delta 3016), pack-reused 73650
Receiving objects: 100% (76739/76739), 18.93 MiB | 14.62 MiB/s, done.
Resolving deltas: 100% (61662/61662), done.
Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/printf'...
remote: Enumerating objects: 1578, done.
remote: Counting objects: 100% (627/627), done.
remote: Compressing objects: 100% (94/94), done.
remote: Total 1578 (delta 566), reused 552 (delta 528), pack-reused 951
Receiving objects: 100% (1578/1578), 794.81 KiB | 6.16 MiB/s, done.
Resolving deltas: 100% (977/977), done.
Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/vusb'...
remote: Enumerating objects: 1372, done.
remote: Counting objects: 100% (73/73), done.
remote: Compressing objects: 100% (50/50), done.
remote: Total 1372 (delta 32), reused 46 (delta 18), pack-reused 1299
Receiving objects: 100% (1372/1372), 476.46 KiB | 15.37 MiB/s, done.
Resolving deltas: 100% (832/832), done.
Submodule path 'lib/chibios': checked out '257302333c31f1f710800c2b97acf3550de043e1'
Submodule path 'lib/chibios-contrib': checked out '2a6b73ff51baf89083a220b6692a04ca2cae8750'
Submodule 'ext/mcux-sdk' (https://github.com/NXPmicro/mcux-sdk) registered for path 'lib/chibios-contrib/ext/mcux-sdk'
Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/chibios-contrib/ext/mcux-sdk'...
remote: Enumerating objects: 38269, done.
remote: Counting objects: 100% (3140/3140), done.
remote: Compressing objects: 100% (1337/1337), done.
remote: Total 38269 (delta 1836), reused 3046 (delta 1796), pack-reused 35129
Receiving objects: 100% (38269/38269), 73.83 MiB | 18.72 MiB/s, done.
Resolving deltas: 100% (26262/26262), done.
Submodule path 'lib/chibios-contrib/ext/mcux-sdk': checked out '102c27d7cc2aaac87c133702e7829a105e0cb433'
Submodule path 'lib/googletest': checked out 'e2239ee6043f73722e7aa812a459f54a28552929'
Submodule path 'lib/lufa': checked out '19a5d533f02a7b46eeadca99cc9699659cef7a60'
Submodule path 'lib/printf': checked out 'd3b984684bb8a8bdc48cc7a1abecb93ce59bbe3e'
Submodule path 'lib/vusb': checked out 'bdb53e4c043d089279d9891b68bea77614cb97ee'

その後再度コンパイルコマンドを打つ

qmk compile -kb biacco42/meishi2 -km custom_keymap

書き込み

avrdudeが大事らしい

make biacco42/meishi2:custom_keymap:avrdude

途中でreset押してって言われるのでmeishi2のリセットボタンを押す

Waiting for USB serial port - reset your controller now (Ctrl+C to cancel)..........

実行結果

❯❯❯make biacco42/meishi2:custom_keymap:avrdude                                                                
QMK Firmware 0.17.9
Making biacco42/meishi2 with keymap custom_keymap and target avrdude

avr-gcc (Homebrew AVR GCC 8.5.0) 8.5.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Size before:
   text    data     bss     dec     hex filename
      0   20726       0   20726    50f6 biacco42_meishi2_custom_keymap.hex

Compiling: quantum/command.c                                                                        [OK]
Linking: .build/biacco42_meishi2_custom_keymap.elf                                                  [OK]
Creating load file for flashing: .build/biacco42_meishi2_custom_keymap.hex                          [OK]
Copying biacco42_meishi2_custom_keymap.hex to qmk_firmware folder                                   [OK]
Checking file size of biacco42_meishi2_custom_keymap.hex                                            [OK]
 * The firmware size is fine - 20726/28672 (72%, 7946 bytes free)
Waiting for USB serial port - reset your controller now (Ctrl+C to cancel)........................................................................................
Device /dev/tty.usbmodem11201 has appeared; assuming it is the controller.
Waiting for /dev/tty.usbmodem11201 to become writable.

Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
    Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.

Programmer supports the following devices:
    Device code: 0x44

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file ".build/biacco42_meishi2_custom_keymap.hex"
avrdude: input file .build/biacco42_meishi2_custom_keymap.hex auto detected as Intel Hex
avrdude: writing flash (20726 bytes):

Writing | ################################################## | 100% 1.53s

avrdude: 20726 bytes of flash written
avrdude: verifying flash memory against .build/biacco42_meishi2_custom_keymap.hex:
avrdude: input file .build/biacco42_meishi2_custom_keymap.hex auto detected as Intel Hex

Reading | ################################################## | 100% 0.15s

avrdude: 20726 bytes of flash verified

avrdude done.  Thank you.

avrdude

  • :avrdude: Checks every 5 seconds until a Caterina device is available (by detecting a new COM port), and then flashes the firmware.

参考

GCPのCloud Natural LanguageのanalyzeSentimentの分析結果をhttp通信で取得するメモ

GCPのCloud Natural Languageの分析結果をVSCodeからHTTP通信で取得してみたのでそのメモ

VSCode拡張機能REST Clientから叩いてみた

POST https://language.googleapis.com/v1beta2/documents:analyzeSentiment?key=自分で発行したAPIキー HTTP/1.1
content-type: application/json

{ 
  "document": {
    "content": "text",
    "type": "PLAIN_TEXT"
  }
}

GCPのコンソールからプロジェクトを作成後APIキーを発行しクエリのkeyに入れる リクエストの中身は上記の通りdocumentの中にcontentとtypeを持たせる感じで多分もっとオプションある gcloud ml language analyze-sentiment  |  Cloud SDK Documentation 詳しくはこの辺を参考に

今回は通信できるかに焦点を当てて分析結果全く気にしてなかったのでtextとかいう適当な文字列持たせてるけどcontentにちゃんとした文字列持たせたらちゃんと分析できるはず

レスポンスは以下の感じ

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Vary: Origin, X-Origin, Referer
Content-Encoding: gzip
Date: Fri, 01 Oct 2021 01:00:45 GMT
Server: ESF
Cache-Control: private
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Connection: close
Transfer-Encoding: chunked

{

  "documentSentiment": {

    "magnitude": 0,
    "score": 0
  },
  "language": "en",
  "sentences": [

    {

      "text": {

        "content": "text",
        "beginOffset": -1
      },
      "sentiment": {

        "magnitude": 0,
        "score": 0
      }
    }
  ]
}

ちゃんと通信できた

Star Ship導入手順メモ

ターミナルの見た目を変えるStarship: Cross-Shell Promptを導入したのでそのメモです

zshのみについて書いてます

環境

  • OS

macOS Big Sur(11.2.3)

  • シェル

zsh(echo $SHELLで確認できます)

  • ターミナル

iTerm2, VSCode

Nerd Fontsから好きなフォントをインストールする

Nerd Fontsで良さげなフォントをダウンロードして自分の普段使うターミナルに設定してください

brewを使う時は下記コマンドの感じでいけます(Fira Codeの例)

brew tap homebrew/cask-fontsこれやんないとフォント見つからなかった

brew install font-fira-code-nerd-font --cask

brew install font-hack-nerd-font --caskVSCode

フォントをターミナルに設定する

Iterm2はここから設定できます

f:id:kenchasonakai:20210424205418p:plain

VSCodeはここから設定できます(Fira Codeは謎にできなかったのでHackを使ってます)

f:id:kenchasonakai:20210424205457p:plain

Starshipをインストールする

brewを使ってインストール

brew install starship

.zshrcに設定を追記する

Starshipがインストールできたら設定をzshに設定をします

~/.zshrcの一番最後にeval "$(starship init zsh)"を追記してください

ちゃんと設定ができていればsource ~/.zshrcを打つとターミナルの見た目が変わると思います

VSCode

f:id:kenchasonakai:20210424205515p:plain

iTerm2

f:id:kenchasonakai:20210424205728p:plain おしゃターミナルは気分が上がりますね

気が向いてカスタマイズしたら記事更新します

GitHubActionsメモ

# 好きな名前をつける
name: RUN Rspec
# どのタイミングで実行するかをここで決める pushとかpullreqestとかを指定するとそのタイミングで実行できる
on: [push]
jobs:
  test:
    # OSを選択するMacとかも選べる
    runs-on: ubuntu-latest
    services:
      # みま神のarrangyのやつコピペしました
      db:
        image: postgres:latest
        ports: ['5432:5432']
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_USER: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    env:
      # masterkeyはcredential読むのにgithubに設定した
      RAILS_ENV: test
      RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
      POSTGRES_PASSWORD: postgres
      POSTGRES_USER: postgres
      POSTGRES_HOST: 127.0.0.1
      POSTGRES_PORT: 5432

    steps:
      - name: check out code
        uses: actions/checkout@v2
      # github actionsに用意されてるruby用の設定使っただけ
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 2.7.2
      # github actionsに用意されてるnode用の設定使っただけ
      - name: setup node.js 15.4.0
        uses: actions/setup-node@v1
        with:
          node-version: 15.4.0
      # gemキャッシュしたい念を送ったけど行けてない感じがする
      - name: chache Gemfile.lock
        uses: actions/cache@v2
        with:
          path: vendor/bundle
          key: bundle-${{ hashFiles('**/Gemfile.lock') }}
      # yarnはなんでもいいから1回build通したらキャッシュ出来た
      - name: chache yarn.lock
        uses: actions/cache@v2
        with:
          path: node_modules
          key: yarn-${{ hashFiles('**/yarn.lock') }}
      - name: yarn install
        run: yarn install
      - name: Build
        run: |
          # postgres関連インストールしてる感ある
          sudo apt-get -yqq install libpq-dev
          # github actions用の設定ファイル作ってdatabase.ymlとして使ってる
          cp config/database.yml.github-actions config/database.yml
          # gemキャッシュできてる感ないから分けないといけないのかも
          gem install bundler
          bundle install --path vendor/bundle --jobs 4
          bundle exec rails db:setup
      - name: RSpec
        run: bundle exec rails spec
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
begin
  ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
  puts e.to_s.strip
  exit 1
end
RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_spec_type_from_file_location!
  config.filter_rails_from_backtrace!

  config.before(:each) do |example|
    if example.metadata[:type] == :system
      driven_by :selenium_chrome_headless, screen_size: [1600, 1600]
    end
  end

end
test:
  adapter: postgresql
  encoding: unicode
  database: hieroglitter_test
  pool: 5
  port: <%= ENV["POSTGRES_PORT"] %>
  username: <%= ENV["POSTGRES_USER"] %>
  password: <%= ENV["POSTGRES_PASSWORD"] %>
  host: <%= ENV["POSTGRES_HOST"] %>

環境変数はどこのやつを呼んでいるのじゃろうか envに設定したやつがPCに環境変数設定したのと同じ扱いになる感はある

  • Google Chromeはデフォルトで入っているから入れる必要がなかった
  • system specはrails_helper.rbにdriven_byの設定を書かないとエラー起きる
RSpec.configure do |config|
  config.before(:each) do |example|
    if example.metadata[:type] == :system
      driven_by :selenium_chrome_headless, screen_size: [1600, 1600]
    end
  end
end

gem内のファイル名が同じだと上書きされるっぽい問題メモ

gem 'pharaoh_lang'を作成する際、 GitHub - kenchasonakai/pharaoh_lang gem 'miyabi'を参考に作らせていただきました。

その際にmiyabi/lib/format.rbのようにpharaoh/lib/format.rbというファイルを作って pharaoh_lang/lib/pharaoh_lang.rbでrequireするように作りました。

rspecで問題なくヒエログリフ変換されることを確認し、リリース。

自分のアプリにインストールし、developmant環境で$ rails specを実行してみたところgem 'miyabi'のメソッドがうまく動いてないよう。

$ rails console"aaa".methodsを実行してみるとformat.rbに書かれていたメソッドが上書きされて消えているよう。

gem 'miyabi'の他のファイルlib/check.rbに書かれていたものは残っていたのでファイル名が同じものだけ上書きされるっぽい。

gem 'pharaoh_lang'lib/format.rblib/format-hieroglyph.rbに変更してバージョンを変更しプッシュ。

自分のアプリでバージョンを0.1.1に指定してbundle installして$ rails specをしてみると上書きされてないっぽい。 以後気をつけます。

gemの作り方、バージョンアップ方法、意外なはまりどころがわかってお勉強になりました。

nilを返すscope内の処理について

# app/model/user.rb
class User < ApplicationRecord
  # find_byで見つかった一番最初のインスタンスを返す、見つからなかったらnilを返す
  scope :find_name, ->(first_name) { find_by(first_name: first_name) }
  # whereで見つかったActiveRecord::Relationを返す
  # 見つからなかったら空のActiveRecord::Relationを返す 
  scope :search_name, ->(first_name) { where(first_name: first_name) }
end

scope内でfind_byを使っている時に条件に当てはまるものが見つからなかった場合はモデルの全てのインスタンスを返してしまう。

irb(main):011:0> User.find_name("存在しない名前")
=> #Userのインスタンスが全て返ってくる

scope内でwhereを使っている時に条件に当てはまるものがなかった時は#<ActiveRecord::Relation []>の空配列を返す

irb(main):012:0> User.search_name("存在しない名前")
=> #<ActiveRecord::Relation []>

スコープはActiveRecord::Relationを必ず返す仕様なので、nilではなくallと同じ結果のActiveRecordRelationを返してしまうらしい。

scopeにはActiveRecord::Relationを返すものを使いましょう。

ActiveRecord::Relationを返すメソッド

all, scope (実装でnilを返すとallと同様になる), select (使い方次第), group, order, reorder, unscope, joins, where, rewhere, having, limit, offset, lock, none, readonly, create_with, from, distinct, extending, reverse_order, includes, eager_load, preload, references, uniq, merge, except, only