技術的なメモは個人esa.ioだったりこのブログだったりに書いてきたのですが、せっかくなので多くの人の目に触れるところに置く方がメリットがあると考え今話題の zenn を遅ればせながら使ってみました。
エディタもシンプルで必要な機能は揃っている印象ですし、見た目もスッキリしていて好みです。 しばらく使ってみて良い感触だったら人の目に触れさせたい技術メモはzennに積極的に書いていこうと思います。
こっちのブログは読書メモとか個人的な雑記とかに使う感じの棲み分けかなと思います。
仕事でまれにプロダクト等の公式サイトを作りたい、という要件が発生します。
コーダーさんが会社にいるわけではないので、ほとんどが「デザインはデザイナさんアサインするから、あとは任せた!」パターンでサーバエンジニアのチームに話が降りてきます。 またそういうサイトはある程度エンジニアなしで更新できることが必須の要件となるため、必然的にWordPressが候補に上がるわけです。
なんとなくWordPressってエンジニアからは避けられがちなイメージもありますが、これだけ普及していてプラグインやテーマなどのエコシステムも強力なOSSなのでせっかくだからきちんと使いこなせるようになっておこう。。という気持ちでこの書籍を手に取りました。
結論から言うと、この本は僕のニーズにぴったりでした。
"デザイン教科書" と言う名前ではありますが、一言で言うとこういう内容です。 → "HTMLとCSSですでに組まれた静的サイトがあり、それをWordPressでよく使われる機能やプラグイン等を使ってCMS化する手順を一通り体験できる。"
HTML、CSS、JS、サーバやPHPのある程度の知識がある人がサクッとWordPressでWebサイトを作るための基本的な知識を速習するのに最適という印象です。 ボリューム感もお手頃で、ささっと斜め読みで2日で一通り読み終えました。
逆に以下についてはあまり詳しく買いていないので、この辺を知りたい人は別の視点から書かれた書籍の方がおすすめかもしれません。
少しWordPressへの苦手意識というか嫌悪感がなくなったので、また次にWebサイト構築案件がきたらもうちょいポジティブな気持ちでWordPressにも向き合えそうです。
おまけ: ローカルでWordPressをインストールしてテーマ作成を行うためのdocker-compose.yml
version: "3" services: db: image: mysql:5.7 volumes: - db_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress wordpress: depends_on: - db image: wordpress:latest ports: - "8000:80" volumes: - ./wp-content:/var/www/html/wp-content environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DEBUG: 1 volumes: db_data:
例えばAPIなんかでたまにあるこう言う形。 これを受け取った場合、共通処理としてまずはerrorがあるかどうかを見て、もしerrorがなかった場合にはdataをそのAPIに合わせた型にして取り出したいとする。
{ "error": null, "data": { "title": "fuga" } }
{ "error": null, "data": { "nickname": "foobar" } }
json.RawMessage
を使うと後からjsonの一部だけを型を指定して取り出すことができる。
まさに今回欲しかったものにぴったり。
golang.org
サンプルはこちら https://play.golang.org/p/e2lW0-15o3P
package main import ( "encoding/json" "fmt" "log" ) var userJSON = `{ "error": null, "data": { "nickname": "hoge" } }` var todoJSON = `{ "error": null, "data": { "title": "fuga" } }` type Response struct { Error *ResponseError `json:"error,omitempty"` Data json.RawMessage `json:"data,omitempty"` // <- User か Todo になる } type ResponseError struct { Code int `json:"code,omitempty"` Message string `json:"message,omitempty"` } type User struct { Nickname string `json:"nickname,omitempty"` } type Todo struct { Title string `json:"title,omitempty"` } func parseResponse(data []byte) (*Response, error) { res := &Response{} if err := json.Unmarshal(data, res); err != nil { return nil, err } if res.Error != nil { return nil, fmt.Errorf("error response: %v\n", res.Error) } return res, nil } func main() { // User APIにアクセスした userRes, err := parseResponse([]byte(userJSON)) if err != nil { log.Fatalf("parse error: %v", err) } user := &User{} if err := json.Unmarshal(userRes.Data, user); err != nil { log.Fatalf("error: %v", err) } fmt.Printf("user: %+v\n", user) // TODO APIにアクセスした todoRes, err := parseResponse([]byte(todoJSON)) if err != nil { log.Fatalf("parse error: %v", err) } todo := &Todo{} if err := json.Unmarshal(todoRes.Data, todo); err != nil { log.Fatalf("error: %v", err) } fmt.Printf("todo: %+v\n", todo) }
FROM golang as builder ENV GOFLAGS=-mod=vendor WORKDIR /work COPY go.* ./ RUN go mod download COPY . ./ RUN CGO_ENABLED=0 GOOS=linux go build -mod=readonly -v -o app FROM alpine:latest RUN apk --no-cache add ca-certificates COPY --from=builder /work/app /app CMD ["/app"]
事前に go mod vendor しておき、 ENV GOFLAGS=-mod=vendor
を付与することで private リポジトリを get しようとしない。
参考: github.com
この記事の続きです。
よく考えると mysql サーバをローカルにインストールする必要はないので、以下のようにやってみました。
brew uninstall mysql brew install mysql-client # mysql との競合を避けるため /usr/local/opt/mysql-client 以下に入るので、以下のようにオプションを調整 bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/mysql-client/lib --with-cppflags=-I/usr/local/opt/mysql-client/include"
これで入りました。
ID トークンを確認する | Firebase にあるように、Fireabse Authentication によって発行された ID トークンを正しく検証することにより、そのユーザの user_id を確認することができます。
Firebase Admin SDK が提供されていればそれを使うことで簡単に検証できるのですが、Ruby 版は提供されていないので Rails から使いたい場合などは自分で検証処理を書くことになります。
検証すべき内容は ID トークンを確認する | Firebase に書いてあるのでそれに沿って書いていきます。
要: JWT gem
# @see https://firebase.google.com/docs/auth/admin/verify-id-tokens?hl=ja # # Usage: # validator = FirebaseAuth::TokenValidator.new(token) # payload = validator.validate! # class FirebaseAuth::TokenValidator class InvalidTokenError < StandardError; end ALG = 'RS256' CERTS_URI = 'https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com' CERTS_CACHE_KEY = 'firebase_auth_certificates' PROJECT_ID = 'YOUR_PROJECT_ID' ISSUER_URI_BASE = 'https://securetoken.google.com/' def initialize(token) @token = token end # # Validates firebase authentication token # # @raise [InvalidTokenError] validation error # @return [Hash] valid payload # def validate! options = { algorithm: ALG, iss: ISSUER_URI_BASE + PROJECT_ID, verify_iss: true, aud: PROJECT_ID, verify_aud: true, verify_iat: true, } payload, _ = JWT.decode(@token, nil, true, options) do |header| cert = fetch_certificates[header['kid']] if cert.present? OpenSSL::X509::Certificate.new(cert).public_key else nil end end # JWT.decode でチェックされない項目のチェック raise InvalidTokenError.new('Invalid auth_time') unless Time.zone.at(payload['auth_time']).past? raise InvalidTokenError.new('Invalid sub') if payload['sub'].empty? payload rescue JWT::DecodeError => e Rails.logger.error e.message Rails.logger.error e.backtrace.join("\n") raise InvalidTokenError.new(e.message) end private # 証明書は毎回取得せずにキャッシュする (要: Rails.cache) def fetch_certificates cached = Rails.cache.read(CERTS_CACHE_KEY) return cached if cached.present? res = Net::HTTP.get_response(URI(CERTS_URI)) raise 'Fetch certificates error' unless res.is_a?(Net::HTTPSuccess) body = JSON.parse(res.body) expires_at = Time.zone.parse(res.header['expires']) Rails.cache.write(CERTS_CACHE_KEY, body, expires_in: expires_at - Time.current) body end end
手元の環境では High Sierra のときはこの辺の考慮をしなくてもインストールできていた気がするのですが、さっき新規に bundle install をしたら以下のようなエラーになってしまいました。
ld: library not found for -lssl clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [mysql2.bundle] Error 1
brew でインストールした openssl が見つからないだけのようで、以下のような対応を行いました。(確か Sierra 以前の頃はこれやってた気がするんですが、なぜ High Sierra のときにはやらずにインストールできていたのだろう。。)
bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib --with-cppflags=-I/usr/local/opt/openssl/include"
参考: https://github.com/brianmario/mysql2/issues/1005
ちなみに今開発しているアプリのデプロイ先が App Engine Flexible Environment (ruby) なので、ruby や node.js をローカルにインストールしちゃう方法で開発を行なっています。 もちろんバージョンは揃えたい(開発者間での差異を無くしつつ、プロジェクトごとに違うバージョンを使えるようにしたい)ので、ruby や node は rbenv / nodenv を使い、MySQL 等のミドルウェアは dokcer-compose を使うようにしていて、コンテナとの付き合い方はこのぐらいの力の入れ具合がちょうどバランスいいかなと個人的には感じています。
とはいえローカルに開発環境を構築している関係上、今回のような個人の環境に依存する問題が発生してしまうことがありますし、実行環境が k8s だったり App Engine の custom runtime だったら全部コンテナ上に乗せて開発する方法を検討すると思いますのでその辺はケースバイケースですね。。