- 投稿日:2020-09-23T22:30:14+09:00
Rails6 Couldn't find User with 'id' = sign_outとなりログアウトができない
エラー内容
参考記事
https://qiita.com/chisaki0606/items/f1f03a6c226e49b5f7b3
ログアウトができない
今までできていたはずのログアウトが突如できなくなる事態が発生してしまう。このエラーで1日を費やしてしまったので、同じようなエラーとなっている人の助けになったらと思い、本稿を投稿することにした。
解決方法
参考記事の通りに
config/initializers/devise.rbconfig.sign_out_via = :deleteを下記のように変更する。
config/initializers/devise.rbconfig.sign_out_via = :getしかし、このまま再びログアウトしてもエラーは解決しない。
というのも、devise.rbのコードは再起動しなければ反映されないため、そのままではエラーのままとなる。
そのため、$ rails sとして、
localhost:3000
に再びアクセスする必要がある。
そうしてあげると、エラーから脱出することができ、正常にログアウトすることができる。終わりに
最後の再起動が重要であり、私はこれをしていないため、沼にハマることになってしまいました。同じようなエラーが悩んでいる方々の助けになれば幸いです。
また、記述に誤りがあるようでしたら、是非ご指摘いただけると幸いです。
- 投稿日:2020-09-23T22:27:08+09:00
Ruby on Railsでグラフを表示する方法(LazyHighChart)
まだまだプログラミングを学び始めたばかりなので拙い記事になってしまうかもしれませんが自分への備忘録&練習としてこういう記事を書いてきたいなと思います。よろしくおねがいします。
LazyHighChartとは
簡単に言うとグラフを表示するgemです。
HighChartsというJavaScript製グラフライブラリをRubyで使えるようにしたよって感じのgemみたい
早めに書いておきますがグラフ自体の表示方法を変えたりするのはまだよくわかっていないので今回は実装までしか書きません。Gemの導入
gem 'lazy_high_charts'まずはGemfileにこれを書いてあげてbundle install
これに加えてapplication.jsに
//= require highcharts/highcharts //= require highcharts/highcharts-more //= require highcharts/highstockと加えてあげましょう。
これで準備はできました。Viewでグラフを表示する
まずView側の記述です。
<%= high_chart('my-first-chart', @chart) %>この記述をしたところにグラフが描画されます。
Controller側の設定
ここでグラフの種類を決めたり(棒グラフ、円グラフ、折れ線グラフなど)を決めていくわけですがまだ先述にもある通り細かいところがわかってないのでとりあえず私が実装させた記述を書きます。
def create @post = Post.new(post_params) if @post.save -----------------------------------------------------#グラフを表示するための記述 @chart = LazyHighCharts::HighChart.new('graph') do |f| f.title(text: @post.select.name) f.xAxis(categories: ["Soldier", "Wizard", "Monk", "Fighter", "Gunner"]) f.series(name: "", yAxis: 1, data: [@post.vs_soldier_id,@post.vs_wizard_id,@post.vs_monk_id,@post.vs_fighter_id,@post.vs_gunner_id]) f.yAxis [ {title: {text: "", margin: 0} }, {title: {text: ""}, opposite: true}, ] f.legend(align: 'none') f.chart({defaultSeriesType: "column"}) end ------------------------------------------------------------------------- else render "new" end endnewアクションからストロングパラメーターで取得した値をcreateアクションで表示した時の記述です。
今回のは棒グラフが表示されます。
f.yAxis
f.legend
f.series
この3つは今回の実装でいらなかったんでよくわかってないです(すいません)f.title
書いてあるとおり、ここに入れた値がグラフのタイトルになります。f.xAxis
グラフの横軸の値です。今回はここは決まっていたんで文字列を入れてますね。そしてf.seriesのなかにある
data: []
ここにデータを入れていきます。(ここに値を入れるために変数をあれこれしたんですが初心者にはここが辛かった…)f.chart({defaultSeriesType: "column"})
ここの"column"がグラフの種類になるみたいですね。以上です。
まだまだわかってないことがたくさんあってガバガバな記事なってしまいましたが少しずついいものが書けるよう頑張っていきたいです。では〜
- 投稿日:2020-09-23T21:39:42+09:00
Railsアプリケーションで投稿検索機能を実装する(whereメソッド)
アプリ: ラーメン屋の写真や情報を友達と共有できるSNS
Ruby: 2.6.5
Rails: 5.2.0viewに検索フォームを設置する
form_withを使って、検索ワードをposts_controllerのsearchアクションに渡します。
app/views/layouts/_header.html.erb・ ・ ・ <div class="post_search"> <%= form_with url: search_posts_path, method: :get, local: true do |f| %> <%= f.text_field :search, class: 'form-control', placeholder: "キーワード検索" %> <%= f.button :type => "submit" do %> <i class="fas fa-search"></i> <% end %> <% end %> </div> ・ ・ ・ルーティング
routes.rb を下記のようにすることで、
/posts/searchというURL(search_posts_path)にgetリクエストを送ることでposts_controllerのsearchアクションにルーティングされます。config/routes.rb~ ~ resources :posts, only: [:new, :create, :edit, :show, :update, :destroy] do get :search, on: :collection end ~ ~posts_controller
検索ワードに合致する投稿を@postsで定義。
app/controllers/posts_controller.rb~ ~ def search @section_title = "「#{params[:search]}」の検索結果" @posts = if params[:search].present? Post.where(['shop_name LIKE ? OR nearest LIKE ?', "%#{params[:search]}%", "%#{params[:search]}%"]) .paginate(page: params[:page], per_page: 12).recent else Post.none end end ~ ~params[:search]でform_withから渡された検索ワードを受け取ります。
whereメソッドはテーブル内から条件に一致したレコードをすべて返します。
(検索ワードがない場合はPost.noneとし、投稿を取得しないようにしました。)whereメソッド
whereメソッドでは下記のように
モデル名.where('カラム名 = ?', "値")第一引数に ? を(プレースホルダーと呼ぶ)、第二引数に条件の値を入れることがあります。
このような書き方をすることで、SQLインジェクションというデータベースのデータを不正に操作する攻撃を防ぐことができるそうです。whereの第二引数には下記のように
"%#{params[:search]}%"検索ワードの前後に % を置いています。
こうすることで、「空白文字を含む任意の複数文字列」が検索ワードの前後に含まれても
その文字列を持つレコードを返すことができます。例
%二郎% → 「二郎」「ラーメン二郎」「つけ麺二郎」「ラーメン二郎八王子店」「二郎歌舞伎町店」 どれも該当する。 %二郎 → 「二郎」「ラーメン二郎」「つけ麺二郎」は該当するが、 「ラーメン二郎八王子店」「二郎歌舞伎町店」は該当しない。下記のように書くことでshop_nameとnearestという2つのカラムから
検索ワードに該当する文字列を検索し、レコードを返します。Post.where(['shop_name LIKE ? OR nearest LIKE ?', "%#{params[:search]}%", "%#{params[:search]}%"])あとは@postsをapp/views/posts/search.html.erbで表示させるようにしてください。
こんな感じ
↓
参考
【Rails】1つの検索フォームで複数カラムをまたいで検索する方法
【Rails】whereメソッドを使って欲しいデータの取得をしよう!
- 投稿日:2020-09-23T21:30:54+09:00
[初心者]Rails6 Vue Postgres開発環境をDocker-Composeを使って構築する方法
はじめに
Dockerを用いてRails,Vue,Posgre環境下で開発したいなと思った時に、
Rails,Vueの環境作りに手こずりましたので自分のメモとして保存します。この記事で分かること
・Rails6とVueとPostgresのDocker環境が構築できる
・RailsとVueの連動ができる
・PryにてインスタンスとDBの操作ができる環境
MacOS Mojave
Ruby 2.6.4
Rails 6.0.3.3
Vue 2.6.12
Webpack 4.44.2
yarn 1.22.5
Docker 2.3.0.5
VScodeGithubのリンク
僕のGithubのDocker-Start-Kitです。よろしければご活用ください。
Whiro0501/Docker_Rails6_VueDocker環境をMacに構築
ターミナルを開く
mkdirで任意の名前のディレクトリを作成
cdで作成したディレクトリに移動
code.でVScodeを開くterminalmkdir qiita cd qiita code .
VScodeが起動
VScode上のターミナルで作業していくので
ターミナルが起動していなければ⬆︎+Control+@でターミナルを開くVScodeのターミナル上で以下コマンドを入力してリモートリポジトリのファイルをローカルにコピー
VScodegit clone https://github.com/Whiro0501/Docker_Rails6_Vue.gitcdでDocker_Rails6_Vue/ディレクトリに移動
VScodecd Docker_Rails6_Vue/以下コマンドを実行してDockerイメージをビルド
VScodedocker-compose build以下を実行して、必要なノードモジュールを取得
VScodedocker-compose run web yarn install --check-files以下を実行して DB(Postgres)を作成
VScodedocker-compose run web rake db:create別のターミナルを開く
以下を実行してレールズアプリケーションを起動VScode#別ターミナルが億劫なら、docker-compose up -dでも良い docker-compose upさらに別のターミナルを開く
Viewを更新するたび毎回コンパイルが発生し、時間がかかるため以下を実行VScodedocker-compose exec web ./bin/webpack-dev-serverWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Railsアプリケーションが起動することを確認
VueとRailsの連動ってどうやるの?
初期構築時点ではRailsとVueが連動されておりませんので連動させていく。
以下でhomeコントローラを作成する(コントローラー名はなんでも良い)。
VScodedocker-compose exec web rails g controller home indexindex.html.erbが作成
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p>以下ファイルに"root to: 'home#index'"を追加
routes.rbRails.application.routes.draw do root to: 'home#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000まずはindex.html.erbに記述されている内容が表示
Rails側で下地ができたので、次にVueとの連動の設定
app.vueの初期設定app.vue<template> <div id="app"> <p>{{ message }}</p> </div> </template> <script> export default { data: function () { return { message: "Hello Vue!" } } } </script> <style scoped> p { font-size: 2em; text-align: center; } </style>hello_vue.jsの初期設定
hello_vue.jsimport Vue from 'vue' import App from '../app.vue' document.addEventListener('DOMContentLoaded', () => { const app = new Vue({ render: h => h(App) }).$mount() document.body.appendChild(app.$el) console.log(app) })app.vueが単一ファイルコンポーネントであり、
hello_vue.jsにオブジェクトとして渡される。
それをindex.html.erbに表示させるよう設定する。index.html.erbを以下の通り設定
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p> <%= javascript_pack_tag 'hello_vue.js' %> <%= stylesheet_pack_tag 'hello_vue.js' %>Webブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Vueとの連動が完了!!
Githubののファイルの説明
Whiro0501/Docker_Rails6_Vue
まず上記リンクのGithubの状態から説明する
端的に説明すると以下2つを設定した後の状態となる
従ってRails6とVueとPostgresが使用できる環境を整えることができるという理屈である。VScodedocker-compose run web rails new . --force --database=postgresql --webpack=vue加えて上記の状態だとPostgresがうまくRailsと連動できないため以下のように設定する。
こちらも公式ドキュメントを参考とした。database.ymldefault: &default adapter: postgresql encoding: unicode host: db username: postgres password: password pool: 5 development: <<: *default database: myapp_development test: <<: *default database: myapp_test production: <<: *default database: myapp_production username: myapp password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>Dockerfile
公式ドキュメントのベストプラクティスを参照にした。
DockerはFROM, RUN, COPY毎にレイヤーが作成されるため
RUNやCOPYはできるだけまとめると少ないレイヤーで収めることができるとのこと。DockerfileFROM ruby:2.6 # `apt-get install yarn`とするとエラーになる # プロジェクトに必要なツールをインストール # &&で繋げてコマンドを実行することによりレイヤーを1つとする #apt-get update と apt-get installは同一RUN上で行う(分けると最新版を使用できない) #RUNはイメージの作成次に実行(CMDはコンテナ起動時に実行) RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update -qq && apt-get install -y nodejs postgresql-client vim && \ apt-get install -y yarn # ディレクトリの作成 RUN mkdir /myapp # 作業ディレクトリの指定 #RUN , COPY, ADD 命令のみレイヤを作成するためWORKDIRは気にしなくて良い # 絶対パスとする WORKDIR /myapp # Gemfileが更新された時のみ、レイヤを再構築 #先にプロジェクト全体をコピーしないのはレイヤーを分けるため COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock # ライブラリの依存関係をインストール RUN bundle install # プロジェクト全体をコピー(Gemfile/Gemfile.lockはコピーされない) COPY . /myapp #コンテナを起動する毎に実行されるスクリプトを追加 COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] #コンテナの公開ポート番号の指定 EXPOSE 3000 #指定しなければコンテナ起動時にデフォルトで実行する処理 #Dockerfile では CMD 命令を 1 つしか記述できない #ENTRYPOINT 命令に対するデフォルト引数としてCMDを使用可能 CMD ["rails", "server", "-b", "0.0.0.0"]docker-compose
docker-compose.ymlもDocker公式ドキュメントを参考にした。
docker-compose.ymlversion: '3' services: db: # DBにpostgresを使用 image: postgres # ホストの./tmp/dbと/var/lib/postgresql/dataを同期させる volumes: - ./tmp/db:/var/lib/postgresql/data # 環境変数の指定 environment: POSTGRES_PASSWORD: password web: build: . # コンテナ起動時にserver.pidを削除し、rails sを実行する command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" # ホストのカレントディレクトリをコンテナの/myappと同期させる volumes: - .:/myapp # ホストとコンテナ間をポートフォワードする ports: - '3000:3000' # サービス間の依存関係 depends_on: - db # Docker環境でByebugを使用 stdin_open: true tty: trueGemfile
Gemfileに関してはデフォルトで入っているもの主となる。
追加したパッケージはコメントしているため不要であれば削除して構わないGemfilesource 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.6' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 6.0.3', '>= 6.0.3.3' # Use postgresql as the database for Active Record gem 'pg', '>= 0.18', '< 2.0' # Use Puma as the app server gem 'puma', '~> 4.1' # Use SCSS for stylesheets gem 'sass-rails', '>= 6' # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker gem 'webpacker', '~> 4.0' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use Active Model has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Active Storage variant # gem 'image_processing', '~> 1.2' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.4.2', require: false group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] #デバックツールの導入 gem 'pry-rails' gem 'pry-byebug' end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '~> 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' #自動補完用ツールの導入 gem 'solargraph' #静的コード解析ツールの導入 gem 'rubocop' gem 'rubocop-rails' #erbのフォーマットツールの導入 gem 'htmlbeautifier' end group :test do # Adds support for Capybara system testing and selenium driver gem 'capybara', '>= 2.15' gem 'selenium-webdriver' # Easy installation and use of web drivers to run system tests with browsers gem 'webdrivers' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]package.json
package.jsonについてはvue-routerとvuexを使いたいため追加している
Vuetify等、UIフレームワークを使用したいようであれば追加する。package.json{ "name": "myapp", "private": true, "dependencies": { "@rails/actioncable": "^6.0.0", "@rails/activestorage": "^6.0.0", "@rails/ujs": "^6.0.0", "@rails/webpacker": "4.3.0", "turbolinks": "^5.2.0", "vue": "^2.6.12", "vue-loader": "^15.9.3", "vue-template-compiler": "^2.6.12", "vue-router": "^3.0.1", "vuex": "^3.0.1" }, "version": "0.1.0", "devDependencies": { "webpack-dev-server": "^3.11.0" } }Railsでデバッグする
VScode上のターミナルを開く
以下をターミナルで実行VScodedocker-compose exec web rails consolepry が起動
VScode[1] pry(main)>postコントローラーを作成
docker-compose exec web rails g controller post indexpost_controller.rbを修正
post_controller.rbclass PostController < ApplicationController def index @post = Post.all end endpostのモデルを作成
VScodedocker-compose exec web rails g model post name:string age:integerDBにモデルを反映させる
VScodedocker-compose exec web rails db:migrateindex.html.erbを以下に書き換え
index.html.erb<%= @post.name %> <%= @post.age %>routes.rbを以下に修正
routes.rbRails.application.routes.draw do root to: 'post#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endpryでPostモデルのインスタンスを作成
VScode@post = Post.new => #<Post:0x00005589bc4beb78 id: nil, name: nil, age: nil, created_at: nil, updated_at: nil> #まだnameやageにはデータを入れていない #DBに保存もされていない Post.all => Post Load (2.2ms) SELECT "posts".* FROM "posts" [] #DBにインスタンスを保存する @post.save (0.7ms) BEGIN Post Create (5.9ms) INSERT INTO "posts" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2020-09-23 13:06:47.962085"], ["updated_at", "2020-09-23 13:06:47.962085"]] (3.1ms) COMMIT => true #もう一度Post.allをしてデータをDBから取得すると保存したインスタンスが呼び出される Post.all => Post Load (2.2ms) SELECT "posts".* FROM "posts" [#<Post:0x00005589bceec5f0 id: 1, name: nil, age: nil, created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00, updated_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00>] #@postインスタンスにデータを入れてみる @post.name = "Hiro" => "Hiro" @post.age = "29" => "29" #再び保存 @post.save Post Update (4.0ms) UPDATE "posts" SET "name" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["name", "Hiro"], ["updated_at", "2020-09-23 13:10:26.486888"], ["id", 1]] Post Update (2.0ms) UPDATE "posts" SET "age" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["age", 29], ["updated_at", "2020-09-23 13:10:56.785029"], ["id", 1]] (1.0ms) COMMIT => true #データが保存されている Post.all => Post Load (1.4ms) SELECT "posts".* FROM "posts" [#<Post:0x00007f1ddc7a77a8 id: 1, name: "Hiro", age: 29, created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00, updated_at: Wed, 23 Sep 2020 13:10:56 UTC +00:00>]Webブラウザで以下にアクセス
Webブラウザhttp://localhost:3000以下のようにDBからデータを取得できればOK
Binding.pryを試してみる
post_controller.rbを修正
class PostController < ApplicationController def index binding.pry @post = Post.all end endWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000pryのターミナルに戻る
pry(main)>以上で、pryでデバッグする環境が整った
参考
以下のサイトを参考にさせていただきました。
Docker ドキュメント日本語化プロジェクト
クィックスタート: Compose と Rails
Dockerfile のベストプラクティス
Webpacker の基本的な仕組み
Dockerを使って「Rails / PostgreSQL」の開発環境を作ろう!
- 投稿日:2020-09-23T21:30:54+09:00
Rails6 Vue Postgres開発環境をDocker-Composeを使って構築する方法
はじめに
Dockerを用いてRails,Vue,Posgre環境下で開発したいなと思った時に、
Rails,Vueの環境作りに手こずりましたので自分のメモとして保存します。この記事で分かること
・Rails6とVueとPostgresのDocker環境が構築できる
・RailsとVueの連動ができる
・PryにてインスタンスとDBの操作ができる環境
MacOS Mojave
Ruby 2.6.4
Rails 6.0.3.3
Vue 2.6.12
Webpack 4.44.2
yarn 1.22.5
Docker 2.3.0.5
VScodeGithubのリンク
僕のGithubのDocker-Start-Kitです。よろしければご活用ください。
Whiro0501/Docker_Rails6_VueDocker環境をMacに構築
ターミナルを開く
mkdirで任意の名前のディレクトリを作成
cdで作成したディレクトリに移動
code.でVScodeを開くterminalmkdir qiita cd qiita code .
VScodeが起動
VScode上のターミナルで作業していくので
ターミナルが起動していなければ⬆︎+Control+@でターミナルを開くVScodeのターミナル上で以下コマンドを入力してリモートリポジトリのファイルをローカルにコピー
VScodegit clone https://github.com/Whiro0501/Docker_Rails6_Vue.gitcdでDocker_Rails6_Vue/ディレクトリに移動
VScodecd Docker_Rails6_Vue/以下コマンドを実行してDockerイメージをビルド
VScodedocker-compose build以下を実行して、必要なノードモジュールを取得
VScodedocker-compose run web yarn install --check-files以下を実行して DB(Postgres)を作成
VScodedocker-compose run web rake db:create別のターミナルを開く
以下を実行してレールズアプリケーションを起動VScode#別ターミナルが億劫なら、docker-compose up -dでも良い docker-compose upさらに別のターミナルを開く
Viewを更新するたび毎回コンパイルが発生し、時間がかかるため以下を実行VScodedocker-compose exec web ./bin/webpack-dev-serverWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Railsアプリケーションが起動することを確認
VueとRailsの連動ってどうやるの?
初期構築時点ではRailsとVueが連動されておりませんので連動させていく。
以下でhomeコントローラを作成する(コントローラー名はなんでも良い)。
VScodedocker-compose exec web rails g controller home indexindex.html.erbが作成
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p>以下ファイルに"root to: 'home#index'"を追加
routes.rbRails.application.routes.draw do root to: 'home#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000まずはindex.html.erbに記述されている内容が表示
Rails側で下地ができたので、次にVueとの連動の設定
app.vueの初期設定app.vue<template> <div id="app"> <p>{{ message }}</p> </div> </template> <script> export default { data: function () { return { message: "Hello Vue!" } } } </script> <style scoped> p { font-size: 2em; text-align: center; } </style>hello_vue.jsの初期設定
hello_vue.jsimport Vue from 'vue' import App from '../app.vue' document.addEventListener('DOMContentLoaded', () => { const app = new Vue({ render: h => h(App) }).$mount() document.body.appendChild(app.$el) console.log(app) })app.vueが単一ファイルコンポーネントであり、
hello_vue.jsにオブジェクトとして渡される。
それをindex.html.erbに表示させるよう設定する。index.html.erbを以下の通り設定
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p> <%= javascript_pack_tag 'hello_vue.js' %> <%= stylesheet_pack_tag 'hello_vue.js' %>Webブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Vueとの連動が完了!!
Githubののファイルの説明
Whiro0501/Docker_Rails6_Vue
まず上記リンクのGithubの状態から説明する
端的に説明すると以下2つを設定した後の状態となる
従ってRails6とVueとPostgresが使用できる環境を整えることができるという理屈である。VScodedocker-compose run web rails new . --force --database=postgresql --webpack=vue加えて上記の状態だとPostgresがうまくRailsと連動できないため以下のように設定する。
こちらも公式ドキュメントを参考とした。database.ymldefault: &default adapter: postgresql encoding: unicode host: db username: postgres password: password pool: 5 development: <<: *default database: myapp_development test: <<: *default database: myapp_test production: <<: *default database: myapp_production username: myapp password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>Dockerfile
公式ドキュメントのベストプラクティスを参照にした。
DockerはFROM, RUN, COPY毎にレイヤーが作成されるため
RUNやCOPYはできるだけまとめると少ないレイヤーで収めることができるとのこと。DockerfileFROM ruby:2.6 # `apt-get install yarn`とするとエラーになる # プロジェクトに必要なツールをインストール # &&で繋げてコマンドを実行することによりレイヤーを1つとする #apt-get update と apt-get installは同一RUN上で行う(分けると最新版を使用できない) #RUNはイメージの作成次に実行(CMDはコンテナ起動時に実行) RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update -qq && apt-get install -y nodejs postgresql-client vim && \ apt-get install -y yarn # ディレクトリの作成 RUN mkdir /myapp # 作業ディレクトリの指定 #RUN , COPY, ADD 命令のみレイヤを作成するためWORKDIRは気にしなくて良い # 絶対パスとする WORKDIR /myapp # Gemfileが更新された時のみ、レイヤを再構築 #先にプロジェクト全体をコピーしないのはレイヤーを分けるため COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock # ライブラリの依存関係をインストール RUN bundle install # プロジェクト全体をコピー(Gemfile/Gemfile.lockはコピーされない) COPY . /myapp #コンテナを起動する毎に実行されるスクリプトを追加 COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] #コンテナの公開ポート番号の指定 EXPOSE 3000 #指定しなければコンテナ起動時にデフォルトで実行する処理 #Dockerfile では CMD 命令を 1 つしか記述できない #ENTRYPOINT 命令に対するデフォルト引数としてCMDを使用可能 CMD ["rails", "server", "-b", "0.0.0.0"]docker-compose
docker-compose.ymlもDocker公式ドキュメントを参考にした。
docker-compose.ymlversion: '3' services: db: # DBにpostgresを使用 image: postgres # ホストの./tmp/dbと/var/lib/postgresql/dataを同期させる volumes: - ./tmp/db:/var/lib/postgresql/data # 環境変数の指定 environment: POSTGRES_PASSWORD: password web: build: . # コンテナ起動時にserver.pidを削除し、rails sを実行する command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" # ホストのカレントディレクトリをコンテナの/myappと同期させる volumes: - .:/myapp # ホストとコンテナ間をポートフォワードする ports: - '3000:3000' # サービス間の依存関係 depends_on: - db # Docker環境でByebugを使用 stdin_open: true tty: trueGemfile
Gemfileに関してはデフォルトで入っているもの主となる。
追加したパッケージはコメントしているため不要であれば削除して構わないGemfilesource 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.6' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 6.0.3', '>= 6.0.3.3' # Use postgresql as the database for Active Record gem 'pg', '>= 0.18', '< 2.0' # Use Puma as the app server gem 'puma', '~> 4.1' # Use SCSS for stylesheets gem 'sass-rails', '>= 6' # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker gem 'webpacker', '~> 4.0' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use Active Model has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Active Storage variant # gem 'image_processing', '~> 1.2' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.4.2', require: false group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] #デバックツールの導入 gem 'pry-rails' gem 'pry-byebug' end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '~> 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' #自動補完用ツールの導入 gem 'solargraph' #静的コード解析ツールの導入 gem 'rubocop' gem 'rubocop-rails' #erbのフォーマットツールの導入 gem 'htmlbeautifier' end group :test do # Adds support for Capybara system testing and selenium driver gem 'capybara', '>= 2.15' gem 'selenium-webdriver' # Easy installation and use of web drivers to run system tests with browsers gem 'webdrivers' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]package.json
package.jsonについてはvue-routerとvuexを使いたいため追加している
Vuetify等、UIフレームワークを使用したいようであれば追加する。package.json{ "name": "myapp", "private": true, "dependencies": { "@rails/actioncable": "^6.0.0", "@rails/activestorage": "^6.0.0", "@rails/ujs": "^6.0.0", "@rails/webpacker": "4.3.0", "turbolinks": "^5.2.0", "vue": "^2.6.12", "vue-loader": "^15.9.3", "vue-template-compiler": "^2.6.12", "vue-router": "^3.0.1", "vuex": "^3.0.1" }, "version": "0.1.0", "devDependencies": { "webpack-dev-server": "^3.11.0" } }Railsでデバッグする
VScode上のターミナルを開く
以下をターミナルで実行VScodedocker-compose exec web rails consolepry が起動
VScode[1] pry(main)>postコントローラーを作成
docker-compose exec web rails g controller post indexpost_controller.rbを修正
post_controller.rbclass PostController < ApplicationController def index @post = Post.all end endpostのモデルを作成
VScodedocker-compose exec web rails g model post name:string age:integerDBにモデルを反映させる
VScodedocker-compose exec web rails db:migrateindex.html.erbを以下に書き換え
index.html.erb<%= @post.name %> <%= @post.age %>routes.rbを以下に修正
routes.rbRails.application.routes.draw do root to: 'post#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endpryでPostモデルのインスタンスを作成
VScode@post = Post.new => #<Post:0x00005589bc4beb78 id: nil, name: nil, age: nil, created_at: nil, updated_at: nil> #まだnameやageにはデータを入れていない #DBに保存もされていない Post.all => Post Load (2.2ms) SELECT "posts".* FROM "posts" [] #DBにインスタンスを保存する @post.save (0.7ms) BEGIN Post Create (5.9ms) INSERT INTO "posts" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2020-09-23 13:06:47.962085"], ["updated_at", "2020-09-23 13:06:47.962085"]] (3.1ms) COMMIT => true #もう一度Post.allをしてデータをDBから取得すると保存したインスタンスが呼び出される Post.all => Post Load (2.2ms) SELECT "posts".* FROM "posts" [#<Post:0x00005589bceec5f0 id: 1, name: nil, age: nil, created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00, updated_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00>] #@postインスタンスにデータを入れてみる @post.name = "Hiro" => "Hiro" @post.age = "29" => "29" #再び保存 @post.save Post Update (4.0ms) UPDATE "posts" SET "name" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["name", "Hiro"], ["updated_at", "2020-09-23 13:10:26.486888"], ["id", 1]] Post Update (2.0ms) UPDATE "posts" SET "age" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["age", 29], ["updated_at", "2020-09-23 13:10:56.785029"], ["id", 1]] (1.0ms) COMMIT => true #データが保存されている Post.all => Post Load (1.4ms) SELECT "posts".* FROM "posts" [#<Post:0x00007f1ddc7a77a8 id: 1, name: "Hiro", age: 29, created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00, updated_at: Wed, 23 Sep 2020 13:10:56 UTC +00:00>]Webブラウザで以下にアクセス
Webブラウザhttp://localhost:3000以下のようにDBからデータを取得できればOK
Binding.pryを試してみる
post_controller.rbを修正
class PostController < ApplicationController def index binding.pry @post = Post.all end endWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000pryのターミナルに戻る
pry(main)>以上で、pryでデバッグする環境が整った
参考
以下のサイトを参考にさせていただきました。
Docker ドキュメント日本語化プロジェクト
クィックスタート: Compose と Rails
Dockerfile のベストプラクティス
Webpacker の基本的な仕組み
Dockerを使って「Rails / PostgreSQL」の開発環境を作ろう!
- 投稿日:2020-09-23T17:27:04+09:00
Better_errors導入後、エラー画面が変わらない
better_error入れて見たがエラー画面変わらず
エラー画面をリッチに使いやすくするruby gem "Better_errors"。
リポジトリ見ると、railsであれば素直にbundle installすれば使えるよと書いてあるが
エラー画面は変わらず…解決策
以下を追記して解決しました。
/config/environments/development.rbBetterErrors::Middleware.allow_ip! "0.0.0.0/0"▼参考:Dockerコンテナでbetter_errorが働かない
https://github.com/BetterErrors/better_errors/issues/270
▼gitのソースはおそらくここ
https://github.com/BetterErrors/better_errors/wiki/Allowing-access-to-the-consoleDockerやVagrantを利用して開発する場合は
railsがbetter_errorsを許可するか判断するので
設定が必要になるそうです。gitの質疑だとDockerのIPアドレス入れても上手く行かない!と言っているので
じゃあもう0.0.0.0/0にして全てのIPアドレスを許可いた状態にしよう!という話しをしています。localhostのIPアドレスでもOKなので
/config/environments/development.rbBetterErrors::Middleware.allow_ip! "127.0.0.1/0"これでもいけました。
因みに 127.0.0.1 とは
ローカル・ループバック・アドレス。
自分自身を表す特別なIPアドレス。localhostのIPアドレスと言ったらこれにあたる。
▼参考
https://www.atmarkit.co.jp/ait/articles/0610/14/news021.htmlです。
ご参考までに。
- 投稿日:2020-09-23T16:33:46+09:00
Railsでログイン機能をシンプルに名前とパスワードだけで実装する(1)
はじめに
rails tutorialで使われているE-mailとパスワードを使ったログインより、もっとシンプルに実装する。
deviseなどのgemは使わない。前提
- rails tutorialを終了した程度の基本的なrailsの知識
- Mac
- Ruby on Rails6
- テストは省略
目標
ここではRoomテーブルの名前とパスワードを使ってログインする。
手順
- まずログインするモデルを作成する。今回はRoomテーブル
MacBook % rails g model Room name:string
- 生成されたマイグレーションファイルに追記し、マイグレーションをかける
- これによって、空の名前はデータベースに保存できなくなる
db/migrate/タイムスタンプ.create_rooms.rbclass CreateRooms < ActiveRecord::Migration[6.0] def change create_table :rooms do |t| t.string :name, null: false t.timestamps end end endMacBook % rails db:migrate
- Room.rbにhas_secure_passwordのメソッドを追加する
app/models/room.rbclass Room < ApplicationRecord validates :name, presence: true, length: { maximum: 50 } has_secure_password end
- password_digestカラムを追加するマイグレーションを作成し、マイグレーションをかける
MacBook % rails generate migration add_password_digest_to_rooms password_digest:stringMacBook % rails db:migrate
- Gemfileを開き、gem 'bcrypt'のコメントアウトを解除しinstallする
Gemfile~ # gem 'redis', '~> 4.0' # Use Active Model has_secure_password gem 'bcrypt', '~> 3.1.7' # Use Active Storage variant # gem 'image_processing', '~> 1.2' ~
- 空のpasswordと最低文字数を追加で制限する
app/models/room.rbclass Room < ApplicationRecord validates :name, presence: true, length: { maximum: 50 } has_secure_password validates :password, presence: true, length: { minimum: 6 } end
- Rails console でインスタンスが生成、データベースに保存できるか確認する
サーバーを立ち上げているのとは別のターミナルMacBook % rails c ~ irb(main):001:0> @room = Room.new(name:"tokyoroom",password:"password",password_confirmation:"password") (2.2ms) SET NAMES utf8mb4, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483 => #<Room id: nil, name: "tokyoroom", created_at: nil, updated_at: nil, password_digest: [FILTERED]> irb(main):002:0> @room.save (0.7ms) BEGIN Room Create (3.3ms) INSERT INTO `rooms` (`name`, `created_at`, `updated_at`, `password_digest`) VALUES ('tokyoroom', '2020-09-23 07:26:30.787094', '2020-09-23 07:26:30.787094', '$2a$12$SmCtpmRZn0M5BMtuT6BmAOKO.DMAmMOIYSXoHlxDrSbA2AQcAYnMC') (5.0ms) COMMIT => true続き[2]
(https://qiita.com/yongjugithub/items/65fcdf73e42857297321)
参考文献
https://railstutorial.jp/chapters/modeling_users?version=5.1#sec-adding_a_secure_password
- 投稿日:2020-09-23T16:33:46+09:00
Railsでログイン機能をシンプルに名前とパスワードだけで実装する
はじめに
rails tutorialで使われているE-mailとパスワードを使ったログインより、もっとシンプルに実装する。
deviseなどのgemは使わない。前提
- rails tutorialを終了した程度の基本的なrailsの知識
- Mac
- Ruby on Rails6
- テストは省略
目標
ここではRoomテーブルの名前とパスワードを使ってログインする。
手順
- まずログインするモデルを作成する。今回はRoomテーブル
MacBook % rails g model Room name:string
- 生成されたマイグレーションファイルに追記し、マイグレーションをかける
- これによって、空の名前はデータベースに保存できなくなる
db/migrate/タイムスタンプ.create_rooms.rbclass CreateRooms < ActiveRecord::Migration[6.0] def change create_table :rooms do |t| t.string :name, null: false t.timestamps end end endMacBook % rails db:migrate
- Room.rbにhas_secure_passwordのメソッドを追加する
app/models/room.rbclass Room < ApplicationRecord validates :name, presence: true, length: { maximum: 50 } has_secure_password end
- password_digestカラムを追加するマイグレーションを作成し、マイグレーションをかける
MacBook % rails generate migration add_password_digest_to_rooms password_digest:stringMacBook % rails db:migrate
- Gemfileを開き、gem 'bcrypt'のコメントアウトを解除しinstallする
Gemfile~ # gem 'redis', '~> 4.0' # Use Active Model has_secure_password gem 'bcrypt', '~> 3.1.7' # Use Active Storage variant # gem 'image_processing', '~> 1.2' ~
- 空のpasswordと最低文字数を追加で制限する
app/models/room.rbclass Room < ApplicationRecord validates :name, presence: true, length: { maximum: 50 } has_secure_password validates :password, presence: true, length: { minimum: 6 } end
- Rails console でインスタンスが生成、データベースに保存できるか確認する
サーバーを立ち上げているのとは別のターミナルMacBook % rails c ~ irb(main):001:0> @room = Room.new(name:"tokyoroom",password:"password",password_confirmation:"password") (2.2ms) SET NAMES utf8mb4, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483 => #<Room id: nil, name: "tokyoroom", created_at: nil, updated_at: nil, password_digest: [FILTERED]> irb(main):002:0> @room.save (0.7ms) BEGIN Room Create (3.3ms) INSERT INTO `rooms` (`name`, `created_at`, `updated_at`, `password_digest`) VALUES ('tokyoroom', '2020-09-23 07:26:30.787094', '2020-09-23 07:26:30.787094', '$2a$12$SmCtpmRZn0M5BMtuT6BmAOKO.DMAmMOIYSXoHlxDrSbA2AQcAYnMC') (5.0ms) COMMIT => true参考文献
https://railstutorial.jp/chapters/modeling_users?version=5.1#sec-adding_a_secure_password
- 投稿日:2020-09-23T16:31:33+09:00
select_tag 選択値設定(include_blank => true)
select_tag 空白行設定(include_blank => true)時、
DBから検索された値をVALに設定しても、空白テキストが表示されている
対策:$("#selectbox").val(DBから検索値).trigger('change')include_blank => falseなら、
$("#selectbox").val(DBから検索値)
- 投稿日:2020-09-23T14:37:52+09:00
Rails Kaminariでページネーション機能を作る
バージョン
・ruby 2.6.6
・rails 5.2.4.1gem 'kaminari' を実装
投稿機能を持ったアプリを作った際には、ページネーション機能はUX的にも必須です。
そこで、gemのKaminariを使って、ページネーション機能の実装を行います。まずGemfileにkaminariを追加して、bundle installを実行
Gemfilegem 'kaminari', '~> 1.2.0'ターミナルbundle installControllerを修正
すでに投稿機能を作成し、投稿一覧ページがあるのであれば、Controlerを修正する必要があります。
元々の自分の投稿一覧ページにおけるControllerは以下の通りです。controllers/posts_controller.rbdef index @posts = Post.all endこれらを次のように変更する。
controllers/posts_controller.rbdef index @posts = Post.page(params[:page]).per(10) endKaminariを追加したことで、各モデル上でpageとperというメソッドが使えるようになります。
pageメソッドの引数に現在のページ数を渡し、perの引数には何件でページを分割するかを渡します。
ここではperの引数に10を入れましたが、8件ずつページを区切りたいときは引数を8にします。Viewの変更
投稿一覧ページを表示する際には、each文を使うことが大体であると思いますが、rubyで用いる
<% end %> の後に <%= pagenate @posts %> と付け加えます。
hamlを使った場合は、listの最後に = paginate @posts のように表記すると良いようです。
詳しくは、hamlを使って記事を書いている方がいらっしゃるので、そちらを参考にしてください。views/posts/index.html.erb<% @posts.each do |post| %> . . . <% end %> <%= pagebate @posts %>ここまででミスがなければ、ページネーション用のリンクが自動で表示され、ページネーション機能が実装できます。
しかし、見やすいデザインとまではなってないと思います。そこで、Bootstrapを利用して、デザインを整えます。すでにBootstrapを導入している方は、次のステップは飛ばしてください。Bootstrapの導入
Bootstrapの導入には、yarnを利用してインストールするやり方、Bootstrapの公式サイトからダウンロードするやり方等ありますが、今回はCDNの方法で説明します。
ここの説明だけでは不安という方はhttps://www.youtube.com/watch?v=YY0mEyggH1E&t=713s
の動画で導入方法を説明しているものがありますので、そちらをご覧ください。行うステップは2つ。
1つ目はheadタグの最後に、公式サイトにあるコードを記述。layouts/application.html.erb<head> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous"> </head>2つ目はbodyタグの最後に、公式サイトにあるコードを記述
layouts/application.html.erb<body> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script> </body>以上で導入が完了します。
Bootstrap4用のViewテンプレートを生成
kaminariにはBootstrapやfoundationなどで使えるテーマが用意されています。
以下のコードをターミナルで実行すると「app/views/kaminari」配下にBootstrap4用のViewテンプレートが生成されます。このViewはkaminariデフォルトのViewより優先して適用されます。ターミナルrails g kaminari:views bootstrap4ここまで完了すると見た目も良いデザインとなります。
うまくいかない時はサーバーを再起動してみてください。また、英語の表記のままでは嫌だという人は日本語表記にする操作を行います。
「config/locales/kaminari_ja.yml」を追加し、以下のように記述します。config/locales/kaminari_ja.ymlja: views: pagination: first: '最初' last: '最後' previous: '前' next: '次' truncate: '...'ここまでで日本語が適用されていないときは「config/application.rb」の中に config.i18n.default_locale = :ja を追加する。
全体的に見ると、以下のようになります。config/application.rbrequire_relative 'boot' require 'rails/all' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) module Theclo class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. config.load_defaults 5.2 # Settings in config/environments/* take precedence over those specified here. # Application configuration can go into files in config/initializers # -- all .rb files in that directory are automatically loaded after loading # the framework and any gems in your application. config.i18n.default_locale = :ja config.time_zone = 'Tokyo' end end以上で実装完了です。
うまくいかない時は再度サーバーの再起動をしてみてください。
皆さんの参考になれば幸いです。
- 投稿日:2020-09-23T13:05:54+09:00
【Ruby on Rails】トップに戻るボタン
目標
開発環境
ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina前提
※ ▶◯◯ を選択すると、説明等が出てきますので、
よくわからない場合の参考にしていただければと思います。上記機能はなくても大丈夫です。
流れ
1 写真の用意
2 viewの編集
3 cssの編集
4 jsファイルの編集(ページスクロールにアニメーションを追加する場合)写真の用意
このような画像を用意してください。
ちなみにこの画像はipadで作成しましたので、ご自由にお使いください。
画像ファイルをapp/assets/images配下に格納してください。
viewの編集
今回は全てのページで表示したいため、下記場所に記載。
app/views/layouts/application.html.erb<body> <%= yield %> <span id="back"> <a href=""> <%= image_tag asset_path('arrow.jpg'), data: {"turbolinks"=>false}, class: "arrow" %> </a> </span> </body>
補足【image_tag asset_path( )】
app/assets/images配下の画像を読み込むことが出来ます。
補足【data: {"turbolinks"=>false}】
turbolinksの誤作動を防ぎます。cssの編集
app/application.css#back { position: fixed; right: 20px; bottom: 20px; } .arrow{ width: 50px; height: 50px; }
補足【position: fixed;】
position: fixed;により表示する場所を固定しています。jsファイルの編集
gem 'jquery-rails'を導入しておいてください。
マウスでクリックするとアニメーションを動作させます。app/assets/javascripts/application.js$(function() { $('#back a').on('click',function(event){ $('body, html').animate({ scrollTop:0 }, 800); event.preventDefault(); }); });
補足【$('#back a').on('click',function(event)】
$('.セレクタ名').on('click',function(event) {
イベント発生時に行われる処理
});
補足【$('body, html').animate】
$('セレクタ名').animate({
変化対象のプロパティ名:変化値
}, アニメーションの動作時間);
- 投稿日:2020-09-23T12:59:37+09:00
vhと%の違い
※主に自分の振り返り用です。
クレジットカード登録画面の下部に空白が生じるのをなんとかしたい。
写真ではわかりにくいですが、黄色で囲んだところに生じている空白を
無くしたいと思い奮闘しました。いろいろ調べて、htmlやbodyに
height: 100%;
を当てる方法を試したところ、他のページのビューにも影響が出てしまい
この方法は断念。。。このあと2時間ほど奮闘しましたが、
card_addクラスに
height: 100vh;
これであっさり解決。要素の高さ指定で%とvhの違いがよく理解できていなかったので
ここにたどり着くのに時間がかかったようです。vhと%の違い
【vh】
ページの表示領域に依存する。height: 100vh;と指定すれば、高さがページの表示領域いっぱいに表示される
【%】
親要素に依存する。height: 100%;と指定すれば親要素の大きさまで表示される。
- 投稿日:2020-09-23T12:29:53+09:00
No Method Errorについて
自分用のエラー解決録です。
フリマアプリ作成のチーム実装もいよいよ終盤。
各メンバーが開発したものをマスターにマージし、
自分のローカルにプルすると度々エラーが発生します。マイページからログアウトページ遷移しようとしたところ発生。
undefined method `each' for nil:NilClassという記述です。
場所はどこか?というと
user#showです。早速コントローラーを確認すると
class UsersController < ApplicationController def index @parents = Category.where(ancestry: nil) end def show end endshowの中身が空、、、
こちらに記述を追加class UsersController < ApplicationController def index @parents = Category.where(ancestry: nil) end def show @parents = Category.where(ancestry: nil) end endエラーを重ねることによって、エラー文から原因を自分で推測して
解決できるようになってきました。
自走力が少し身についてきたのかな?まだまだこれからですが、引き続き頑張ります!
- 投稿日:2020-09-23T11:31:26+09:00
任意の場所から文字を取り出せるメソッド作成
【概要】
1.結論
2.どのように記載するか
3.ここから学んだこと
1.結論
lengthメソッドとsliceメソッドを使用する!
2.どのように記載するか
def srt_search(strings) character_number = strings.length #---❶ character_reslut = strings.slice(character_number - 3, 3) #---❷ end上記のように記述しました!
❶lengthで、文字列を数に変更しました。
ex)"Goodjob"➡︎"8"文字に変換
❷今回は最後から3番目までの数字が欲しいので❶の文字数からslice(character_number - 3, 3)することでcharacter_numberからの文字数から"-3"した番目の"3"文字分を取得できます。
ex)"Goodjob"の8文字から"-3"すると最初から"5"番目(=最後から3番目まで)の"3"文字を抜き取る。
参考にしたURL:
【Ruby入門説明書】ruby sliceについて解説
3.ここから学んだこと
slice(character_number - 3, 3)の部分は、
slice(-3,3)とすれば、最後から3番目の3文字を常にとることができるなと思いました。ただ、文章の構成(ex:Hi, John! Nice to meet you!)になると単語区分でsliceが判断してしまい、"to meet you!"が抜き出される点は注意しないといけません。
- 投稿日:2020-09-23T09:27:52+09:00
Rails 6で認証認可入り掲示板APIを構築する #18・終 user controllerの実装
←Rails 6で認証認可入り掲示板APIを構築する #17 管理者権限の追加
全18回に渡る連載も今回で終了です。
今回はuser controllerを作ります。
今までの集大成なので、例示するコードを見ずに作ってみることをオススメします。仕様
主に管理者がユーザー管理をする用途と、ユーザーが自分自身の更新削除をするための機能群として想定しています。
- #index 管理者のみ閲覧可能
- #show 自分自身か管理者のみ閲覧可能
- #create 管理者のみ作成可能
- #update 自分自身か管理者のみ更新可能
- #destroy 管理者のみ削除可能
手順
- users_controllerの作成
- user_policyの作成
- user_policyテストの実装
- user_policyの実装
- users_controllerテストの実装
- users_controllerの実装
という手順で進めてみます。
1. users_controllerの作成
実装例
コマンド叩くだけなので簡単ですね。$ rails g controller v1/usersrubocopに怒られないように微修正したファイル群がこちら。
app/controllers/v1/users_controller.rb# frozen_string_literal: true module V1 # # users controller # class UsersController < ApplicationController end endspec/requests/v1/users_request_spec.rb# frozen_string_literal: true require "rails_helper" RSpec.describe "V1::Users", type: :request do end2. user_policyの作成
実装例
コマンド叩いてファイル作ります。
$ rails g pundit:policy userrubocopに怒られないように微修正を加えたらとりあえず完成。
app/policies/user_policy.rb# frozen_string_literal: true # # userのポリシークラス # class UserPolicy < ApplicationPolicy # # scope # class Scope < Scope def resolve scope.all end end endspec/policies/user_policy_spec.rb# frozen_string_literal: true require "rails_helper" RSpec.describe UserPolicy, type: :policy do let(:user) { User.new } subject { described_class } permissions ".scope" do pending "add some examples to (or delete) #{__FILE__}" end permissions :show? do pending "add some examples to (or delete) #{__FILE__}" end permissions :create? do pending "add some examples to (or delete) #{__FILE__}" end permissions :update? do pending "add some examples to (or delete) #{__FILE__}" end permissions :destroy? do pending "add some examples to (or delete) #{__FILE__}" end end3. user_policyテストの実装
実装例
仕様のおさらい。
- #index 管理者のみ閲覧可能
- #show 自分自身か管理者のみ閲覧可能
- #create 管理者のみ作成可能
- #update 自分自身か管理者のみ更新可能
- #destroy 管理者のみ削除可能
index, #create, #destroyで共通化、#show, #updateで共通化できそうですね。
それを念頭に実装したのがこちら。
spec/policies/user_policy_spec.rb# frozen_string_literal: true require "rails_helper" RSpec.describe UserPolicy, type: :policy do let(:user) { create(:user) } let(:another_user) { create(:user) } let(:admin_user) { create(:user, :admin) } subject { described_class } permissions :index?, :create?, :destroy? do it "未ログインの時に不許可" do expect(subject).not_to permit(nil, user) end it "adminユーザー以外でログインしている時に不許可" do expect(subject).not_to permit(user, user) end it "adminユーザーでログインしている時に許可" do expect(subject).to permit(admin_user, user) end end permissions :show?, :update? do it "未ログインの時に不許可" do expect(subject).not_to permit(nil, user) end it "ログインしているが別ユーザーの時に不許可" do expect(subject).not_to permit(user, another_user) end it "adminユーザーでログインしている時に許可" do expect(subject).to permit(admin_user, user) end it "ログインしていて同一ユーザーの時に許可" do expect(subject).to permit(user, user) end end end
another_user
という別ユーザーを定義しているのがポイント。
さて、この時点ではpolicyを設定していないのでテストがいくつかコケることを確認してください。
4. user_policyの実装
実装例
app/policies/user_policy.rb# frozen_string_literal: true # # userのポリシークラス # class UserPolicy < ApplicationPolicy def index? admin? end def show? me? || admin? end def create? admin? end def update? me? || admin? end def destroy? admin? end private def me? @record == @user end # # scope # class Scope < Scope def resolve scope.all end end end
me?
というprivateメソッドをuser_policy.rbに定義しているのがポイントです。application_policy.rbにある
mine?
は、@record.user == @user
と、@record
の持つuser
が自分のものか比較していました。
ですが今回は@record
と@user
が一致するか確認するので、英語の文法的にmine?
ではなくme?
になります。その上、user
自身と比較するのは現時点ではusers_controllerでしかなさそうなので、application_policyではなくuser_policyに提議しました。あとは特筆することもなく、テストが通過するようになったはずです。
5. users_controllerテストの実装
実装例
spec/requests/v1/users_request_spec.rb# frozen_string_literal: true require "rails_helper" RSpec.describe "V1::Users", type: :request do before do @user = create(:user, name: "userテスト") @authorized_headers = authorized_user_headers @user admin = create(:user, :admin) @authorized_admin_headers = authorized_user_headers admin end describe "GET /v1/users#index" do before do create_list(:user, 3) end it "正常レスポンスコードが返ってくる" do get v1_users_url, headers: @authorized_admin_headers expect(response.status).to eq 200 end it "件数が正しく返ってくる" do get v1_users_url, headers: @authorized_admin_headers json = JSON.parse(response.body) expect(json["users"].length).to eq(3 + 2) # headers用2件を含む end it "id降順にレスポンスが返ってくる" do get v1_users_url, headers: @authorized_admin_headers json = JSON.parse(response.body) first_id = json["users"][0]["id"] expect(json["users"][1]["id"]).to eq(first_id - 1) expect(json["users"][2]["id"]).to eq(first_id - 2) expect(json["users"][3]["id"]).to eq(first_id - 3) expect(json["users"][4]["id"]).to eq(first_id - 4) end end describe "GET /v1/users#show" do it "正常レスポンスコードが返ってくる" do get v1_user_url({ id: @user.id }), headers: @authorized_headers expect(response.status).to eq 200 end it "nameが正しく返ってくる" do get v1_user_url({ id: @user.id }), headers: @authorized_headers json = JSON.parse(response.body) expect(json["user"]["name"]).to eq("userテスト") end it "存在しないidの時に404レスポンスが返ってくる" do last_user = User.last get v1_user_url({ id: last_user.id + 1 }), headers: @authorized_headers expect(response.status).to eq 404 end end describe "POST /v1/users#create" do let(:new_user) do attributes_for(:user, name: "create_nameテスト", email: "email+create_test@example.com", admin: true) end it "正常レスポンスコードが返ってくる" do post v1_users_url, params: new_user, headers: @authorized_admin_headers expect(response.status).to eq 200 end it "1件増えて返ってくる" do expect do post v1_users_url, params: new_user, headers: @authorized_admin_headers end.to change { User.count }.by(1) end it "name, email, adminが正しく返ってくる" do post v1_users_url, params: new_user, headers: @authorized_admin_headers json = JSON.parse(response.body) expect(json["user"]["name"]).to eq("create_nameテスト") expect(json["user"]["email"]).to eq("email+create_test@example.com") expect(json["user"]["admin"]).to be true end it "不正パラメータの時にerrorsが返ってくる" do post v1_users_url, params: {}, headers: @authorized_admin_headers json = JSON.parse(response.body) expect(json.key?("errors")).to be true end end describe "PUT /v1/users#update" do let(:update_param) do update_param = attributes_for(:user, name: "update_nameテスト", email: "email+update_test@example.com", admin: true) update_param[:id] = @user.id update_param end it "正常レスポンスコードが返ってくる" do put v1_user_url({ id: update_param[:id] }), params: update_param, headers: @authorized_headers expect(response.status).to eq 200 end it "name, email, adminが正しく返ってくる" do put v1_user_url({ id: update_param[:id] }), params: update_param, headers: @authorized_headers json = JSON.parse(response.body) expect(json["user"]["name"]).to eq("update_nameテスト") expect(json["user"]["email"]).to eq("email+update_test@example.com") expect(json["user"]["admin"]).to be false # admin権限は書き換えできると困るのでfalseのまま end it "不正パラメータの時にerrorsが返ってくる" do put v1_user_url({ id: update_param[:id] }), params: { name: "" }, headers: @authorized_headers json = JSON.parse(response.body) expect(json.key?("errors")).to be true end it "存在しないidの時に404レスポンスが返ってくる" do last_user = User.last put v1_user_url({ id: last_user.id + 1 }), params: update_param, headers: @authorized_admin_headers expect(response.status).to eq 404 end end describe "DELETE /v1/users#destroy" do it "正常レスポンスコードが返ってくる" do delete v1_user_url({ id: @user.id }), headers: @authorized_admin_headers expect(response.status).to eq 200 end it "1件減って返ってくる" do expect do delete v1_user_url({ id: @user.id }), headers: @authorized_admin_headers end.to change { User.count }.by(-1) end it "存在しないidの時に404レスポンスが返ってくる" do last_user = User.last delete v1_user_url({ id: last_user.id + 1 }), headers: @authorized_admin_headers expect(response.status).to eq 404 end end endいくつかpostの時とは違う考慮点があります。
- headerを作る際に
create(:user)
をしているので、その2件分を考慮してテストを書くこと。
- 存在しないid確認の際も同様、last_userを取得して+1
- adminフラグは自由に書き換えれてしまうと困るので、createでadminフラグは反映されるがupdateでは反映されないこと
あたりを取り入れています。
また、レスポンスにadmin判定があるので、serializerの修正も必要ですね。
app/serializers/user_serializer.rb# user serializer # class UserSerializer < ActiveModel::Serializer - attributes :id, :name, :email + attributes :id, :name, :email, :admin end以上で準備完了。次にcontroller実装に入ります。
6. users_controllerの実装
実装例
controllerにアクセスできるようにするため、routesの修正をします。
config/routes.rbRails.application.routes.draw do namespace "v1" do resources :posts + resources :users mount_devise_token_auth_for "User", at: "auth" end
続いてcontrollerです。
こちらはpostのほぼ流用でいけますね。app/controllers/v1/users_controller.rb# frozen_string_literal: true module V1 # # users controller # class UsersController < ApplicationController before_action :set_user, only: %i[show update destroy] def index users = User.order(created_at: :desc).limit(20) authorize users render json: users end def show authorize @user render json: @user end def create user = User.new(user_create_params) user[:provider] = :email authorize user if user.save render json: user else render json: { errors: user.errors } end end def update authorize @user if @user.update(user_params) render json: @user else render json: { errors: @user.errors } end end def destroy authorize @user @user.destroy render json: @user end private def set_user @user = User.find(params[:id]) end def user_create_params # createの時のみadmin権限を設定できるようにする params.permit(:name, :email, :admin, :password) end def user_params params.permit(:name, :email, :password) end end endテストのセクションで書いたように、adminはcreateの時のみ付与できるようにしています。
以上です。
全18回に渡りご覧いただきありがとうございました。ぜひこれを元に、コメント機能やソーシャルログイン等の機能拡張していってください。
目次
【連載目次へ】
- 投稿日:2020-09-23T08:09:06+09:00
SREエンジニア採用面接における質問と趣旨
概要
会社では週に数回、採用面接を担当してるのですが、最近ではフロントエンド・バックエンドだけでなくSREの採用も執り行うようになりました。
ここではSREを採用する際に実際に私が面接で質問する主な観点と趣旨について公開していこうと思います。誰が書いてるか
現職は メタップス にて横断的なテックリードやSREエンジニアをしてます。学生の頃に「ユニバーサルHTML/XHTML」やヤコブ・ニールセンの「ウェブ・ユーザビリティ」に感化されフロントエンド技術に興味を持ち始め、その後バックエンドに携わるとミーハーらしくPoEAAやDDDにハマり、勢いに乗ってベトナム・ハノイでのオフショア事業を立ち上げました。自称フルスタックしつつ、現地メンバーの採用を始め育成計画やらアーキテクトとして10年ほど携わり、今に至ります。ここ数年の興味はもっぱらインフラで、SREとしての動きが主軸となりつつあります。
SREに求めるスキル
採用ページから抜粋。AWS DevDay 2019 で登壇したときの技術構成がベースとなってます。
技術的な必須要件
- AWSを利用したインフラ設計・構築・運用経験
- LinuxやDockerの運用経験
- クラウドネイティブなアプリケーションの設計・開発
- OSやミドルウェア、データベースのチューニング
- Ruby on RailsやNode.jsを使ったアプリケーションの開発
技術的な歓迎要件
- オーケストレーションツールを利用したインフラ構築
- OSやミドルウェアの検証・導入
- 大規模トラフィックを捌くインフラ基盤設計の経験
- インフラ運用の効率化・自動化
- 監査・情報セキュリティに関する知見
- OSSの公開、コントリビュート経験
利用技術
- クラウド: AWS
- OS: Linux
- 仮想化: ECS
- データベース: RDS・ElastiCache・ElastiCache・DynamoDB
- 構成管理: Terraform
- 開発言語: Ruby on Rails・Node.js
- 監視: Datadog
- ログ: Fluentd・Elasticsearch Service・Kibana
選考プロセス
- 書類選考
- カジュアル面談 (開発メンバーとの面談)
- 一次面談 (開発リーダーとの面談)
- 二次面談 (事業責任者・開発責任者との面談)
カジュアル面談は、選考に入る前に事業の紹介や候補者との情報交換のために設けられます。必ず実施するとは限りません。
どのフェーズで面接に関わっているか
主に人事がピックアップしてくれた方を中心に二次面接に関わることが多いです。
ただエンジニア経験が浅くても、ポートフォリオなどから会ってみたい方は割といるので、自分からオファーをかけることもあります。二次面接はどのような流れで進むか
- 挨拶
- 事業紹介 (事業責任者)
- SREの役割について説明 (開発責任者)
- 候補者の自己紹介
- 候補者からの質疑応答
- 技術面のスキルチェック (開発責任者)
- 候補者からの質疑応答
今回は「6. 技術面のスキルチェック」について深堀りします。
履歴書はどこまで見ているか
年齢と自己PRくらい。
職務経歴書はどこまで見ているか
仕事内容よりも、「どういったスキルをどの場面で、どのように活用したか」、「どのようなポジションで仕事に携わっていたか。周りとの関係性 (コミュニケーション面)」を見ることが多いです。
ポートフォリオは必要か
重要視してます。職務経歴書よりもソースコードから読み取れるスキル・経験則のほうが情報量が多いためです。QiitaやGitHub、Speaker Deckなど、公開できるリソースはどんどん公開していきましょう。
ケーススタディはあるか
あります。ここでは質問に対する答えの論理性や整合性を見ます。SREはアプリケーションエンジニアと密にコミュニケーションを取るため、説明の伝え方やわかり易さ、積極性も見てます。
コーディング試験はあるか
現状実施してませんが、将来的に取り入れる可能性はあります。
質問の観点と意図
本題。
アーキテクチャ設計の経験
- 趣旨
- SREはインフラのみ知識だけあれば良い訳ではなく、アプリケーション設計や開発経験も含めた総合的な知見や経験が求められます。Webシステムにおけるアーキテクチャの設計経験があれば、システムのどこにボトルネックがあり、問題を改善する上でどういった工夫を施したか、など詳しく知見を引き出すことができます
- 付随する質問事項
- アーキテクチャの概要説明
- システムの規模
- MAU、トラフィックなど
- 影響を受けたアーキテクチャ
- DDD、マイクロサービス、Twelve-Factor Appなど
- APIの設計
- Open API、Graph API、gRPCなど
- 選定理由
アプリケーション開発の経験
- 趣旨
- SREはインフラの運用・自動化を推進しますが、日々構成をアップデートしていく中で、アプリケーションコードにも手を入れなければならない場面が出てきます。例えば、マイクロサービスの統廃合であったり、システムリプレースにおける開発環境の仮想化・インテグレーションなどが当たります。アプリケーションエンジニアにはサービス開発に専念して欲しいため、インフラと密になりやすいタスクはSREがカバーする方針で運用しています
- 付随する質問事項
- 得意とする言語 (理由)・経験年数
- 不得意な言語があればその理由
- 利用したことのあるフレームワーク・それぞれの利点と問題点
- パフォーマンス最適化の経験
- 技術構成
- フロントエンド・バックエンドのどちらを得意とするか (システムを最適化する上でどちらを得意とするか)
- テストコードやレビューの経験
- レビュワーとしての観点
DB設計の経験
- 趣旨
- Webシステムでボトルネックとなる大半の要因はDBの設計やクエリの書き方にあります。SREはサービスを監視する上でネットワークのレイテンシも追跡しています。メトリクスに異常があれば、APMなどを介して問題のコードを洗い出し、クエリの実行計画を分析した上でアプリケーションエンジニアに共有するスキルが求められます
- 付随する質問事項
- 経験のあるDBエンジン
- チューニング経験
- どのように? (ハード・ソフト)
- トランザクション数・テーブル数
SREとしての経験
- 趣旨
- フロントエンドやバックエンド開発もある中で、何故SREを希望しているのか。SREとして将来的に何を目標として仕事をしたいか。前職までの経験で培ったスキル・その時々の課題などをヒアリングし、会社が求めている人材と一致するかを確認します
- 付随する質問事項
- ネットワークやサーバ・ミドルウェア構築の経験
- オンプレミスの経験
- スパイクアクセス
- トラフィックの算定方法
- どのような対策を施したか・結果はどうだったか
- AWS/GCPの経験
- 好きなサービス
- 興味のあるサービス
- 運用
- 自動化の経験・どのように改善したか
- 監視
- 利用したことのあるツール・選定基準
- オンコール対応の経験
- IaC
- 設計・構築の経験
- 設計パターンの具体例
- 利用したことのあるツール・選定基準
- ログ分析
- 設計・構築の経験
- アーキテクチャ構成・課題
- CI/CD・インフラ運用の自動化
- 設計・構築経験
- アーキテクチャ構成・課題
- セキュリティ
- アプリケーションのセキュリティ対策
- コンテナに対するセキュリティの知見
- IPS/IDSの知見
- 監査
- ガイドライン策定の経験
- インシデント管理
雑談
- 趣旨
- 開発に対する意欲や将来的に目指すキャリアプランをヒアリングし、事業メンバーとフィーリングが一致するかを確認します
- 付随する質問事項
- 転職理由
- 自身のスキルの優位性
- 自作でサービスを作ったことがあるか
- 使用言語・開発期間
- 成果と課題
- 興味のある技術
- OSSコントリビュート経験
- 自主的にシステムの課題を発見し、解決するスキルがあるか
- Qiitaなどでの技術公開・勉強会などでの登壇経験
- 情報の発信力。技術をアウトプットできるか
- 入社後に挑戦したいこと
- キャリアプラン
- VPoE or CTO?
- 最終的に入社の決め手となる要素は何か
まとめ
SREという職種は比較的新しく、人手が不足している職種の一つかと思います。サービスをインフラ・アプリケーション両方の観点から成長させていく楽しみもあるので、是非転職の際は検討してみてください!
- 投稿日:2020-09-23T08:09:06+09:00
SREエンジニア面接における質問と趣旨を公開する
概要
会社では週に数回、採用面接を担当してるのですが、最近ではフロントエンド・バックエンドだけでなくSREの採用も執り行うようになりました。
ここではSREを採用する際に実際に私が面接で質問する主な観点と趣旨について公開していこうと思います。誰が書いてるか
現職は メタップス にてテックリードやSREエンジニアをしてます。学生の頃に「ユニバーサルHTML/XHTML」やヤコブ・ニールセンの「ウェブ・ユーザビリティ」に感化されフロントエンド技術に興味を持ち始め、その後バックエンドに携わるとミーハーらしくPoEAAやDDDにハマり、勢いに乗ってベトナム・ハノイでのオフショア事業を立ち上げました。自称フルスタックしつつ、現地メンバーの採用を始め育成計画やらアーキテクトとして10年ほど携わり、今に至ります。ここ数年の興味はもっぱらインフラで、SREとしての動きがメインとなりつつあります。
SREに求めるスキル
採用ページから抜粋。AWS DevDay 2019 で登壇したときの技術構成がベースとなってます。
技術的な必須要件
- AWSを利用したインフラ設計・構築・運用経験
- LinuxやDockerの運用経験
- クラウドネイティブなアプリケーションの設計・開発
- OSやミドルウェア、データベースのチューニング
- Ruby on RailsやNode.jsを使ったアプリケーションの開発
技術的な歓迎要件
- オーケストレーションツールを利用したインフラ構築
- OSやミドルウェアの検証・導入
- 大規模トラフィックを捌くインフラ基盤設計の経験
- インフラ運用の効率化・自動化
- 監査・情報セキュリティに関する知見
- OSSの公開、コントリビュート経験
利用技術
- クラウド: AWS
- OS: Linux
- 仮想化: ECS
- データベース: RDS・ElastiCache・ElastiCache・DynamoDB
- 構成管理: Terraform
- 開発言語: Ruby on Rails・Node.js
- 監視: Datadog
- ログ: Fluentd・Elasticsearch Service・Kibana
どのフェーズで面接に関わっているか
主に人事がピックアップしてくれた方を中心に最終面接に関わることが多いです。
ただエンジニア経験が浅くても、ポートフォリオなどから会ってみたい方は割といるので、自分からオファーをかけることもあります。履歴書はどこまで見ているか
名前と年齢くらい。
職務経歴書はどこまで見ているか
仕事内容よりも、「どういったスキルをどの場面で、どのように活用したか」、「どのようなポジションで仕事に携わっていたか。周りとの関係性 (コミュニケーション面)」を見ることが多いです。
ポートフォリオは必要か
重要視してます。職務経歴書よりもソースコードから読み取れるスキル・経験則のほうが情報量が多いためです。QiitaやGitHub、Speaker Deckなど、公開できるリソースはどんどん公開していきましょう。
ケーススタディやコードテストはあるか
ケーススタディはあります。ここでは質問に対する答えの論理性・整合性を見ます。SREはアプリケーションエンジニアと密にコミュニケーションを取るため、説明の伝え方やわかり易さ、能動性も見ています。
また、現状コードテストは実施してませんが、将来的に取り入れる可能性はあります。質問の観点と意図
ようやく本題。
アーキテクチャ設計の経験
- 趣旨
- SREはインフラのみ理解しておけば良い訳ではなく、アプリケーション設計や開発経験も含めた総合的な知見やセンスが求められます。Webシステムにおけるアーキテクチャの設計経験があれば、システムのどこにボトルネックがあり、問題を改善する上でどういった工夫を施したか、など詳しく知見を引き出すことができます
- 付随する質問事項
- システムの規模
- MAU、トラフィックなど
- 影響を受けたアーキテクチャ
- DDD、マイクロサービス、Twelve-Factor Appなど
- APIの設計
- Open API、Graph API、gRPCなど
- 選定理由
アプリケーション開発の経験
- 趣旨
- SREはインフラの運用・自動化を推進しますが、日々構成をアップデートしていく中で、アプリケーションコードにも手を入れなければならない場面が出てきます。例えば、マイクロサービスの統廃合であったり、システムリプレースにおける開発環境の仮想化・インテグレーションなどが当たります。アプリケーションエンジニアにはサービス開発に専念して欲しいため、インフラと密になりやすいタスクはSREがサポートする方針で運用しています
- 付随する質問事項
- 得意とする言語 (理由)・経験年数
- 不得意な言語があればその理由
- 利用したことのあるフレームワーク・それぞれの利点と問題点
- パフォーマンス最適化の経験
- 技術構成
- フロントエンド・バックエンドのどちらを得意とするか
- テストコードやレビューの経験
- レビュワーとしての観点
DB設計の経験
- 趣旨
- Webシステムでボトルネックとなる大半の要因はDBの設計やクエリの書き方にあります。SREはサービスを監視する上でネットワークのレイテンシも追跡しています。メトリクスに異常があれば、APMなどを介して問題のコードを洗い出し、クエリの実行計画を分析した上でアプリケーションエンジニアに共有するスキルが求められます
- 付随する質問事項
- 経験のあるDBエンジン
- チューニング経験
- どのように? (ハード/ソフト)
- トランザクション数・テーブル数
SREとしての経験
- 趣旨
- フロントエンドやバックエンド開発もある中で、何故SREを希望しているのか。SREとして将来的に何を目標として仕事をしたいか。前職までの経験で培ったスキル・その時々の課題などをヒアリングし、会社が求めている人材と一致するかを確認します
- 付随する質問事項
- ネットワークやサーバ構築の経験
- オンプレミスの経験
- AWS/GCPの経験
- 好きなサービス
- 興味のあるサービス
- IaC
- 設計・構築の経験
- 利用したことのあるツール・選定基準
- ログ分析
- 設計・構築の経験
- アーキテクチャ構成・課題
- CI/CD・インフラ運用の自動化
- 設計・構築経験
- アーキテクチャ構成・課題
- ドキュメント管理
- 使用するツール
- インシデント管理
- ガイドライン策定の経験
雑談
- 趣旨
- 開発に対する意欲や将来的に目指すキャリアプランをヒアリングし、事業メンバーとフィーリングが一致するかを確認します
- 付随する質問事項
- 転職理由
- 自身のスキルの優位性
- 自作でサービスを作ったことがあるか
- 使用言語・開発期間
- 成果と課題
- OSSコントリビュート経験
- 自主的にシステムの課題を発見し、解決するスキルがあるか
- Qiitaなどでの技術公開・勉強会などでの登壇経験
- 情報の発信力。技術をアウトプットできるか
- 入社後に挑戦したいこと
- キャリアプラン
- VPoE or CTO?
- 最終的に入社の決め手となる要素は何か
まとめ
SREという職種は比較的新しく、人手が不足している職種の一つかと思います。サービスをインフラ・アプリケーション両方の観点から成長させていく楽しみもあるので、是非転職の際は検討してみてください!
- 投稿日:2020-09-23T08:09:06+09:00
SREエンジニア面接における質問と趣旨
概要
会社では週に数回、採用面接を担当してるのですが、最近ではフロントエンド・バックエンドだけでなくSREの採用も執り行うようになりました。
ここではSREを採用する際に実際に私が面接で質問する主な観点と趣旨について公開していこうと思います。誰が書いてるか
現職は メタップス にて横断的なテックリードやSREエンジニアをしてます。学生の頃に「ユニバーサルHTML/XHTML」やヤコブ・ニールセンの「ウェブ・ユーザビリティ」に感化されフロントエンド技術に興味を持ち始め、その後バックエンドに携わるとミーハーらしくPoEAAやDDDにハマり、勢いに乗ってベトナム・ハノイでのオフショア事業を立ち上げました。自称フルスタックしつつ、現地メンバーの採用を始め育成計画やらアーキテクトとして10年ほど携わり、今に至ります。ここ数年の興味はもっぱらインフラで、SREとしての動きが主軸となりつつあります。
SREに求めるスキル
採用ページから抜粋。AWS DevDay 2019 で登壇したときの技術構成がベースとなってます。
技術的な必須要件
- AWSを利用したインフラ設計・構築・運用経験
- LinuxやDockerの運用経験
- クラウドネイティブなアプリケーションの設計・開発
- OSやミドルウェア、データベースのチューニング
- Ruby on RailsやNode.jsを使ったアプリケーションの開発
技術的な歓迎要件
- オーケストレーションツールを利用したインフラ構築
- OSやミドルウェアの検証・導入
- 大規模トラフィックを捌くインフラ基盤設計の経験
- インフラ運用の効率化・自動化
- 監査・情報セキュリティに関する知見
- OSSの公開、コントリビュート経験
利用技術
- クラウド: AWS
- OS: Linux
- 仮想化: ECS
- データベース: RDS・ElastiCache・ElastiCache・DynamoDB
- 構成管理: Terraform
- 開発言語: Ruby on Rails・Node.js
- 監視: Datadog
- ログ: Fluentd・Elasticsearch Service・Kibana
選考プロセス
- 書類選考
- カジュアル面談 (開発メンバーとの面談)
- 一次面談 (開発リーダーとの面談)
- 二次面談 (事業責任者・開発責任者との面談)
カジュアル面談は、選考に入る前に事業の紹介や候補者との情報交換のために設けられます。必ず実施するとは限りません。
どのフェーズで面接に関わっているか
主に人事がピックアップしてくれた方を中心に二次面接に関わることが多いです。
ただエンジニア経験が浅くても、ポートフォリオなどから会ってみたい方は割といるので、自分からオファーをかけることもあります。二次面接はどのような流れで進むか
- 挨拶
- 事業紹介 (事業責任者)
- SREの役割について説明 (開発責任者)
- 候補者の自己紹介
- 候補者からの質疑応答
- 技術面のスキルチェック (開発責任者)
- 候補者からの質疑応答
今回は「6. 技術面のスキルチェック」について深堀りします。
履歴書はどこまで見ているか
年齢と自己PRくらい。
職務経歴書はどこまで見ているか
仕事内容よりも、「どういったスキルをどの場面で、どのように活用したか」、「どのようなポジションで仕事に携わっていたか。周りとの関係性 (コミュニケーション面)」を見ることが多いです。
ポートフォリオは必要か
重要視してます。職務経歴書よりもソースコードから読み取れるスキル・経験則のほうが情報量が多いためです。QiitaやGitHub、Speaker Deckなど、公開できるリソースはどんどん公開していきましょう。
ケーススタディはあるか
あります。ここでは質問に対する答えの論理性・整合性を見ます。SREはアプリケーションエンジニアと密にコミュニケーションを取るため、説明の伝え方やわかり易さ、積極性も見てます。
コーディング試験はあるか
現状実施してませんが、将来的に取り入れる可能性はあります。
質問の観点と意図
ようやく本題。
アーキテクチャ設計の経験
- 趣旨
- SREはインフラのみ知識だけあれば良い訳ではなく、アプリケーション設計や開発経験も含めた総合的な知見や経験が求められます。Webシステムにおけるアーキテクチャの設計経験があれば、システムのどこにボトルネックがあり、問題を改善する上でどういった工夫を施したか、など詳しく知見を引き出すことができます
- 付随する質問事項
- システムの規模
- MAU、トラフィックなど
- 影響を受けたアーキテクチャ
- DDD、マイクロサービス、Twelve-Factor Appなど
- APIの設計
- Open API、Graph API、gRPCなど
- 選定理由
アプリケーション開発の経験
- 趣旨
- SREはインフラの運用・自動化を推進しますが、日々構成をアップデートしていく中で、アプリケーションコードにも手を入れなければならない場面が出てきます。例えば、マイクロサービスの統廃合であったり、システムリプレースにおける開発環境の仮想化・インテグレーションなどが当たります。アプリケーションエンジニアにはサービス開発に専念して欲しいため、インフラと密になりやすいタスクはSREがカバーする方針で運用しています
- 付随する質問事項
- 得意とする言語 (理由)・経験年数
- 不得意な言語があればその理由
- 利用したことのあるフレームワーク・それぞれの利点と問題点
- パフォーマンス最適化の経験
- 技術構成
- フロントエンド・バックエンドのどちらを得意とするか (アプリケーションのパフォーマンスを最適化する上でどちらを得意とするか)
- テストコードやレビューの経験
- レビュワーとしての観点
DB設計の経験
- 趣旨
- Webシステムでボトルネックとなる大半の要因はDBの設計やクエリの書き方にあります。SREはサービスを監視する上でネットワークのレイテンシも追跡しています。メトリクスに異常があれば、APMなどを介して問題のコードを洗い出し、クエリの実行計画を分析した上でアプリケーションエンジニアに共有するスキルが求められます
- 付随する質問事項
- 経験のあるDBエンジン
- チューニング経験
- どのように? (ハード/ソフト)
- トランザクション数・テーブル数
SREとしての経験
- 趣旨
- フロントエンドやバックエンド開発もある中で、何故SREを希望しているのか。SREとして将来的に何を目標として仕事をしたいか。前職までの経験で培ったスキル・その時々の課題などをヒアリングし、会社が求めている人材と一致するかを確認します
- 付随する質問事項
- ネットワークやサーバ・ミドルウェア構築の経験
- オンプレミスの経験
- スパイクアクセス
- トラフィックの算定方法
- どのような対策を施したか・結果はどうだったか
- AWS/GCPの経験
- 好きなサービス
- 興味のあるサービス
- 監視
- 利用したことのあるツール・選定基準
- オンコール対応の経験
- IaC
- 設計・構築の経験
- 設計パターンの具体例
- 利用したことのあるツール・選定基準
- ログ分析
- 設計・構築の経験
- アーキテクチャ構成・課題
- CI/CD・インフラ運用の自動化
- 設計・構築経験
- アーキテクチャ構成・課題
- セキュリティ
- アプリケーションのセキュリティ対策
- コンテナに対するセキュリティの知見
- IPS/IDSの知見
- 監査
- ガイドライン策定の経験
- インシデント管理
雑談
- 趣旨
- 開発に対する意欲や将来的に目指すキャリアプランをヒアリングし、事業メンバーとフィーリングが一致するかを確認します
- 付随する質問事項
- 転職理由
- 自身のスキルの優位性
- 自作でサービスを作ったことがあるか
- 使用言語・開発期間
- 成果と課題
- 興味のある技術
- OSSコントリビュート経験
- 自主的にシステムの課題を発見し、解決するスキルがあるか
- Qiitaなどでの技術公開・勉強会などでの登壇経験
- 情報の発信力。技術をアウトプットできるか
- 入社後に挑戦したいこと
- キャリアプラン
- VPoE or CTO?
- 最終的に入社の決め手となる要素は何か
まとめ
SREという職種は比較的新しく、人手が不足している職種の一つかと思います。サービスをインフラ・アプリケーション両方の観点から成長させていく楽しみもあるので、是非転職の際は検討してみてください!