20211128のRailsに関する記事は19件です。

ゲストハウス支配人からエンジニアになってみて

はじめに ゲストハウススタッフからエンジニアになってみて、というテーマでお話しさせていただきます。 前職について エンジニア転職する前は、都内のゲストハウスの支配人として勤務をしておりました。 ゲストハウスとはドミトリーと呼ばれる相部屋の部屋がメインの宿泊施設です。 宿泊代がホテルに比べると安く、また1階がカフェ・バーになっており初めてのお客様同士でも話しやすい雰囲気のため、世界中から来る宿泊客で賑わっていました。...コロナ前までは(苦笑)。 エンジニアになろうと思ったきっかけ 元々私は文系の大学出身でしたし、エンジニアになるなんて微塵も考えたことはありませんでした。 しかしゲストハウスの運営をしていると、パソコンひとつ持って世界中を旅しながら仕事をしている人に出会うことも多く、彼らの話を聞いていると大抵エンジニアだったりデザイナーとして働いているとのことでした。ただそれでも羨ましいと思いつつも自分には出来ないことだと思っていました。 少し話は飛びますが、長年勤めているとトラブルや施設の故障などに度々出くわします。 私の勤めていたゲストハウスは大手でもなく当然修繕資金等も潤沢にあるわけではないので、今あるものでなんとか解決するということが必要な場面が多く、だんだんと大抵のことはちょっと調べればある程度は出来るという自信がついてきていました。 そんな日常の中である時宿泊客と雑談していたのですが、ゲストハウスの宿泊管理システムが使いづらいという愚痴を溢していると、たまたまそのお客様がエンジニアで「そんなの自分で作っちゃえばいいじゃん。」という風に軽く言われました。 その言葉が自分にとって衝撃的でしたが、そういえば最近大抵のことはある程度出来るよな〜と感じていたことからすごく納得し、いっちょエンジニアになって世界中を旅しながら仕事してやろう、と思ったのがエンジニアになろうとしたきっかけでした。 エンジニアとして働いてみた感想(前職と比べてどう変わったか) 現在はRailsエンジニアとして、とある会社様の販売管理システムを作っています。 やはり大きく変わったこととしては、フルリモートで出社する必要がないところです。 前職では一日中動き回っていましたが、現在は良くも悪くもほぼパソコンの前から動くことはありません。 そのため身体は楽ではありますが、劣っていくのが手に取るようにわかるので適度な運動は必須ですね。 また以前は勤務時間が不規則で家族との時間を取りにくかったりしたのですが、家の事も気にしながら仕事が出来るのはかなり有難いです。 その他にもこれまでは自主的に勉強をすることが少なかったのですが、エンジニア転職を目指してからは勉強が習慣化したこともあり、さらにいろいろなことに興味が湧いて、プログラミング以外も少しずつ勉強を始めて自分の幅を広げることが出来ていると思います。 今後はどんなエンジニアを目指したいか 社内の開発部員が少ないこともあり、要件定義から開発、保守まで少しずつ触れさせてもらっているのですが、やはりただプログラムが書けるだけでは将来的には全然意味がないという風に感じています。 「お客様の課題を解決するにはこういうものが必要で、それを利用してこうしていきましょう!」みたいな感じで物事を大きく捉え、プログラミングはあくまで手段として使ってお客様の課題解決に導く、しかも予算ややりたいことによって何パターンか提案出来たりする上司を見てめちゃくちゃかっこいいなと思ったので、そうなれることを目標に頑張ります。 とはいえまだまだこんなに簡単そうな事も出来ないなんて....と日々壁にぶつかっているので、毎日少しずつ乗り越えていきたいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FactoryBot のまとめ

FactoryBot とは factory_bot_rails といった gem を導入することで使える。 → model のデータに紐づいたテストデータを簡単に作るためのもの。 spec 配下の factories の中に定義する。 各モデルのファイルを作成して、カラムに基づくデータを Faker を使って定義する。 Faker とは… ダミーデータを作るのに便利な gem のこと。 定義したデータをテストの際などで呼び出すことが可能になる! FactoryBot の定義の仕方 FactoryBot.defineをdo 〜 end の中で定義するような書き方をする。 作成例) FactoryBot.define do factory :article do title { Faker::Lorem.word } body { Faker::Lorem.sentence } end end 上記のような書き方だと、 title カラムでは、Faker::Lorem.wordによってランダムな単語が作成される。 body カラムでは、Faker::Lorem.sentenceによってランダムな文が作成される。 FactoryBot の呼び出し方 定義したFactoryBot を呼び出すためのメソッドが存在する。 【代表的なメソッド】 create メソッド DBに保存する形でレコードを更新するメソッドのこと。 FactoryBot を使ってレコードを作成する。 特徴としては、association も保存する! 例)FactoryBot.create(:user) build メソッド DB保存しない状態でインスタンスを作成するメソッドのこと。 FactoryBot を使って、インスタンスを new する。 特徴としては、association は保存する! 例)FactoryBot.build(:user) build_stubbed メソッド DB保存しない状態でインスタンスを作成するメソッドのこと。 特徴としては、「IDカラムには適当な値が入る」、「association も保存しない」 attributes_for メソッド パラメーターを生成するメソッドのこと。 FactoryBot の定義から、値をハッシュ形式で受け取る。 例)FactoryBot.attributes_for(:user) _list メソッド 生成系のメソッド + _list の記述で、それぞれに対応する同じデータを複数件生成できる。 例)build_list()、build_stubbed_list()、create_list()、attributes_for_list() ( 引用記事:https://qiita.com/morrr/items/f1d3ac46b029ccddd017 ) 重複しないデータを作る テストを実装していく中でvalidationによって重複したデータができては困る場合が出てくる。 そこで出てくるのが sequence である。 FactoryBot には sequence という機能がありsequence を使うことで重複を防ぐことができる!この機能を使うと、FactoryBot の機能を呼び出すたびに、n の数字が1 ずつ増えていく。 つまり、Faker で作ったデータの前に数字がつくので重複しないデータを作ることができる!! (例)sequence(:account) { |n| "#{n}_#{Faker::Internet.username}" } Factoryで関連を扱う association という機能を使うことで関連するダータを作ることができる。 belongs_to の関係を持っているモデルの Factory では、 association という機能を使うことで関連するデータを自動的に作成できるようになる! 書き方の例)association :user, factory: :user ※ association には省略形もあり、上記の例の場合だとuserだけで足りる! trait という機能を使うことで、Factory の場合わけをすることができる! 関連するモデルを持っている方を単体で呼び出せるようにすることができるということ。 with_ + belongs_toの関係を持つモデルに trait を指定して、そこで association の機能を使う。 書き方の例)user テーブルの Factory に下記の記述を追加。 trait :with_user_detail do # association :user_detail, factory: :user_detail の省略形 user_detail end 上記のコードを記述することで、場合分けができるようになる! 詳細データが必要ないときは、user だけ作成する  → FactoryBot.create(:user) 詳細データも必要なときは、user_detail も一緒に作成する  → FactoryBot.create(:user, :with_user_detail) 引用元 ワンダフルコード・講義資料 https://qiita.com/morrr/items/f1d3ac46b029ccddd017 まとめ FactoryBot はテストの実装でめちゃめちゃ使う gem である。 メソッドの理解が不十分なまま実装していたので、言語化してまとめていくことで理解を深めていくことができたと思う。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【jbuilder】部分テンプレートのオプション

環境 Ruby 3.0.2 Rails 6.1.4.1 部分テンプレート 部分テンプレート内で呼び出し方をasで指定 2つとも同じように取れる app/views/users/index.json.jbuilder json.partial! 'users/user', collection: @users, as: :user #or json.array! @users, partial: 'users/user', as: :user app/views/users/_user.json.jbuilder json.extract! user, :id, :name, :age 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】IN句の書き方

IN句の書き方いろいろ User.where(id: [1, 3, 6]) #=> SELECT `users`.* FROM `users` WHERE `users`.`id` IN ('1', '3', '6') ids = [1, 3, 6] User.where('id IN (?)', ids) #=> SELECT `users`.* FROM `users` WHERE (id IN (1, 3, 6)) User.where('id IN (?)', [1, 3, 6]) #=> SELECT `users`.* FROM `users` WHERE (id IN (1, 3, 6)) User.where('id IN (1, 3, 6)') #=> SELECT `users`.* FROM `users` WHERE (id IN (1, 3, 6))
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】Routingのネスト,member, collectionの違い

はじめに Railsでアプリケーション作成しております。 作成中にルーティングについて少々学習したので、自分用のメモとして残しておきます。 ルーティングについて ルーティングは、受け取ったHTTPリクエストに応じて、特定のコントローラー内のアクションを動作するように割り当てを行なっている。 Railsのルーティングはconfig/routes.rbで設定する。 config/routes.rb Rails.application.routes.draw do # ここにルーティングを設定する root 'home#index' end 設定したルーティングは、以下のコマンドを実行することで確認できます。 ターミナル $ bin/rails routes Prefix Verb URI Pattern Controller#Action root GET / home#index 実装したかったこと(前提) ユーザー(user)が、ある施設(house)に口コミ(review)を投稿する機能を実装します。 施設は複数あり、1つの施設に複数の口コミが投稿されると想定する。 各々の投稿のURLを規則的に振り当てるとすると、https://○○○/house/id/review/idというふうにしたい。 今回の各モデルのアソシエーションは以下のようにしている。 Userの認証モデルについてはdeviseにて実装済みである。 結論 ルーティングをネストするといい! config/routes.rb Rails.application.routes.draw do root 'home#index' devise_for :users # ネストしたルーティング resources :houses do resources :reviews end end ルーティングを確認する際は、-gや-cオプションを用いると見やすくなります。 ターミナル # -g :名前付きルーティングやHTTP動詞、URLパスのいずれかに部分マッチするルーティングのみ表示する $ bin/rails routes -g reviews Prefix Verb URI Pattern Controller#Action house_reviews GET /houses/:house_id/reviews(.:format) reviews#index POST /houses/:house_id/reviews(.:format) reviews#create new_house_review GET /houses/:house_id/reviews/new(.:format) reviews#new edit_house_review GET /houses/:house_id/reviews/:id/edit(.:format) reviews#edit house_review GET /houses/:house_id/reviews/:id(.:format) reviews#show PATCH /houses/:house_id/reviews/:id(.:format) reviews#update PUT /houses/:house_id/reviews/:id(.:format) reviews#update DELETE /houses/:house_id/reviews/:id(.:format) reviews#destroy # -c :特定のコントローラーのルーティングのみ表示する $ bin/rails routes -c reviews Prefix Verb URI Pattern Controller#Action house_reviews GET /houses/:house_id/reviews(.:format) reviews#index POST /houses/:house_id/reviews(.:format) reviews#create new_house_review GET /houses/:house_id/reviews/new(.:format) reviews#new edit_house_review GET /houses/:house_id/reviews/:id/edit(.:format) reviews#edit house_review GET /houses/:house_id/reviews/:id(.:format) reviews#show PATCH /houses/:house_id/reviews/:id(.:format) reviews#update PUT /houses/:house_id/reviews/:id(.:format) reviews#update DELETE /houses/:house_id/reviews/:id(.:format) reviews#destroy memberやcollectionとの違いは? ルーティングにREST以外のアクションを追加したい場合に、memberやcollectionを使用します。 memberやcollectionを使う場合とどのような違いが出るのか、確認してみます。 ①memberを使う場合 config/routes.rb Rails.application.routes.draw do root 'home#index' devise_for :users resources :houses do member do resources :reviews end end end ターミナル $ bin/rails routes -g reviews Prefix Verb URI Pattern Controller#Action reviews GET /houses/:id/reviews(.:format) reviews#index POST /houses/:id/reviews(.:format) reviews#create new_review GET /houses/:id/reviews/new(.:format) reviews#new edit_review GET /houses/:id/reviews/:id/edit(.:format) reviews#edit review GET /houses/:id/reviews/:id(.:format) reviews#show PATCH /houses/:id/reviews/:id(.:format) reviews#update PUT /houses/:id/reviews/:id(.:format) reviews#update DELETE /houses/:id/reviews/:id(.:format) reviews#destroy 一見これでも良さそうだが、houses後の:idとreview後の:idが同じになってしまう。 ②collectionを使う場合 config/routes.rb Rails.application.routes.draw do root 'home#index' devise_for :users resources :houses do collection do resources :reviews end end end ターミナル $ bin/rails routes -g reviews Prefix Verb URI Pattern Controller#Action reviews GET /houses/reviews(.:format) reviews#index POST /houses/reviews(.:format) reviews#create new_review GET /houses/reviews/new(.:format) reviews#new edit_review GET /houses/reviews/:id/edit(.:format) reviews#edit review GET /houses/reviews/:id(.:format) reviews#show PATCH /houses/reviews/:id(.:format) reviews#update PUT /houses/reviews/:id(.:format) reviews#update DELETE /houses/reviews/:id(.:format) reviews#destroy この場合、houses後に:idが付かないURLになってしまう。 以上のことから、今回のケースではネストした方が良いということがわかりました。 コントローラーやビューでの振る舞い ルーティングをネストすれば、houseとreviewのIDを別々に定義できることがわかりました。 それでは、それぞれのidを用いて、DBにデータを保存するにはどうすれば良いのか? 今回はform_withを用いた口コミ作成、編集フォームを例に考えます。 コントローラーでのインスタンスの定義や、ビューでの記述については以下のようにしました。 コントローラーの記述 app/controllers/reviews_controller.rb class ReviewsController < ApplicationController def new @house = House.find(params[:house_id]) @review = current_user.reviews.build end def create @review = current_user.reviews.build(review_create_params) @review.house_id = params[:house_id] if @review.save flash[:success] = "口コミを投稿しました!" redirect_to house_path(@review.house_id) else render 'new' end end def edit @house = House.find(params[:house_id]) @review = Review.find(params[:id]) end def update @review = Review.find(params[:id]) if @review.update(review_update_params) flash[:success] = "口コミを修正しました!" redirect_to root_url else render 'edit' end end private def review_create_params params.require(:review).permit(:content, :user_id) end def review_update_params params.require(:review).permit(:content) end end 口コミは、どの施設に対する口コミなのかということを定義する必要があります。 そのため、@houseを上記のような方法で取得しています。 ビューファイルの記述 app/views/reviews/new.html.slim = form_with model: [@house, @review], local: true do |f| = f.text_field :content, placeholder: "口コミ本文を書いてください(10,000字以内)" = f.submit "口コミを投稿する" app/views/reviews/edit.html.slim = form_with model: [@house, @review], local: true do |f| = f.text_field :content = f.submit '口コミを修正する' ビュー側では、form_withの引数に[@house, @review]のように配列を渡すように記述する必要があります。 以上になります。誤りなどありましたら、ご指摘お願いします。 参考 https://railsguides.jp/routing.html https://pikawaka.com/rails/form_with
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】SQLでor検索

A OR Bの結果が出力される。 User.where(name: 'コナン') .or(User.where(email: 'ran@gmail.com')) #=> SELECT `users`.* FROM `users` WHERE (`users`.`name` = 'コナン' OR `users`.`email` = 'ran@gmail.com') orメソッドがまだなかったときはこんな書き方をよく見かけたらしい。 User.where("name = ? OR email = ?", 'コナン', 'ran@gmail.com') #=> SELECT `users`.* FROM `users` WHERE (name = 'コナン' OR email = 'ran@gmail.com')
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】複数レコード一括保存のRspecの書き方

https://ryucoding.com/programming/rails-form-bulk-create で紹介されている複数レコードを一括保存するcreateアクションをテストするリクエストspecの書き方で詰まったのでその備忘録です。 テスト対象のコントローラーとアクション //questions_controller def create @form = Form::QuestionCollection.new(question_collection_params) if @form.save redirect_to root_url else render 'new' end end . . . . . def question_collection_params params.require(:form_question_collection).permit(questions_attributes: [:content, :mode_num]) end クイズ出題アプリで[question]という出題文を表すモデルを同時に10個作成するためのアクションです。 rspec //questions_request_spec.rb describe "POST /create" do context "空欄なく入力した場合" do it "redirects to root path" do expect{ post questions_path, params: {form_question_collection: {questions_attributes:  {0=> {content: "test question1", mode_num:1}, 1 =>{content: "test question2", mode_num:1}, 2 =>{content: "test question3", mode_num:1}, 3 =>{content: "test question4", mode_num:1}, 4 =>{content: "test question5", mode_num:1}, 5 =>{content: "test question6", mode_num:1}, 6 =>{content: "test question7", mode_num:1}, 7 =>{content: "test question8", mode_num:1}, 8 =>{content: "test question9", mode_num:1}, 9 =>{content: "test question10", mode_num:1}}}} }.to change(Question, :count).by (10) expect(response).to redirect_to root_path end end [content]と[mode_num]はカラム名です。保存に成功し際はroot_pathにリダイレクトすることをテストするためのコードです。 上記の書き方で同時に10個のレコードをcreateするアクションのリクエストspecを実現できました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】左外部結合と内部結合

環境 Ruby 3.0.2 Rails 6.1.4.1 前提条件 class Owner < ActiveRecord::Base has_many :dogs end class Dog < ActiveRecord::Base belongs_to :owner end 左外部結合 左側のテーブルにしかないレコードも取得して結合する。 下の例でいうと、飼犬がいないオーナーのデータも取得できる。 Owner.left_joins(:dogs) => SELECT `owners`.* FROM `owners` LEFT OUTER JOIN `dogs` ON `dogs`.`owner_id` = `owners`.`id` 内部結合 結合条件に一致するレコードのみを結合する。 下の例でいうと、飼犬がいるオーナーのデータのみ取得できる。 Owner.joins(:dogs) => SELECT `owners`.* FROM `owners` INNER JOIN `dogs` ON `dogs`.`owner_id` = `owners`.`id` 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Railsチュートリアル】ユーザー検索機能の実装

はじめに 前回の記事【Railsチュートリアル】いいね機能の実装に引き続きRailsチュートリアル第6版sample_appの機能拡張を進めていく。 今回は以下の様なユーザー検索機能を実装していく。 前提 第6版sample_appが完成している 手順 Gemfileにransackを追加 Gemfile gem 'ransack' 検索フォームを作成 app/views/users/_search_form.html.erb <%= search_form_for @q do |f| %> <%= f.label :name_cont, 'User Search' %> <div class="input-group"> <%= f.text_field :name_cont, placeholder: "Enter username...", class: 'form-control' %> <span class="input-group-btn"> <%= f.submit 'Go', class: "btn btn-primary" %> </span> </div> <% end %> ユーザーコントローラーを変更 app/controllers/users_controller.rb class UsersController < ApplicationController . . . def index if params[:q] && params[:q].reject { |key, value| value.blank? }.present? @q = User.ransack(search_params, activated_true: true) @title = "Search Result" else @q = User.ransack(activated_true: true) @title = "All users" end @users = @q.result.paginate(page: params[:page]) end . . . private . . . def search_params params.require(:q).permit(:name_cont) end end ビューを変更 app/views/users/index.html.erb <% provide(:title, 'All users') %> <h1>All users</h1> <div class="row"> <div class="search_form"> <%= render 'users/search_form' %> </div> </div> <%= will_paginate %> <% unless @users.empty? %> <ul class="users"> <%= render @users %> </ul> <% else %> <p class="search_message"> Couldn't find any user. </p> <% end %> <%= will_paginate %> cssを追加 app/assets/stylesheets/custom.scss /* search_form */ .search_form { overflow: auto; margin: 10px; float: left; .input-group { width: 300px; .form-control { width: 250px; } .btn { width: 50px; } } } .search_message { margin-top: 30px; font-weight: bold; font-size: 1.3em; }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

bundle installが原因でdocker-composeが立ち上がらなかった話

everyday-railsというテスト本を元にdocker環境で学習しようとしたのがことの発端です。 私自身dockerのことをよくわかっていなかったので、なかなか解決に時間がかかってしまいました。 前提 この記事では、docker-composeにrailsの環境(everyday-railsで用意されているソースを元に使います。)を構築するにあたって遭遇したエラーとその対処について書きます。 Dockerファイルなど dockerファイル dockerfile FROM ruby:2.7 ENV LANG C.UTF-8 RUN apt-get update -qq && apt-get install -y \ build-essential \ nodejs \ && rm -rf /var/lib/apt/lists/* RUN gem install bundler WORKDIR /tmp ADD Gemfile Gemfile ADD Gemfile.lock Gemfile.lock RUN bundle install ENV APP_HOME /myapp RUN mkdir -p $APP_HOME WORKDIR $APP_HOME ADD . $APP_HOME docker-compose.yml docker-compose.yml version: '3' services: web: build: . ports: - "3000:3000" command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/myapp - bundle:/usr/local/bundle depends_on: - db db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: password ports: - '3306:3306' volumes: - mysql_data:/var/lib/mysql volumes: bundle: mysql_data: database.yml(config/database.ymlのことです。) database.yml default: &default adapter: mysql2 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 username: root password: password host: db development: <<: *default database: development_database test: <<: *default database: test_database production: <<: *default database: production_database Gemfile Gemfile # gem 'sqlite3' ↑これを消して gem 'mysql2'とします これは今回使うデータベースがmysqlのためです。 docker-composeを立ち上げる ここまででdocker-composeの設定となるファイルを書いたら、docker-composeを立ち上げます。 コマンドは ターミナル docker-compose build 何も問題なければ、以下のようにターミナルに表示されるはずです。 ➜ everydayrails-rspec-2017 git:(master) ✗ docker-compose ps NAME COMMAND SERVICE STATUS PORTS ➜ everydayrails-rspec-2017 git:(master) ✗ docker-compose build [+] Building 1.5s (15/15) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 32B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/ruby:2.7 1.3s => [ 1/10] FROM docker.io/library/ruby:2.7@sha256:2b5ffc71a256f93e98a1b596f38bbe33632c5c48138f939aae7347e65343383f 0.0s => [internal] load build context 0.0s => => transferring context: 13.34kB 0.0s => CACHED [ 2/10] RUN apt-get update -qq && apt-get install -y build-essential nodejs && rm -rf /var/lib/apt/lists/* 0.0s => CACHED [ 3/10] RUN gem install bundler 0.0s => CACHED [ 4/10] WORKDIR /tmp 0.0s => CACHED [ 5/10] ADD Gemfile Gemfile 0.0s => CACHED [ 6/10] ADD Gemfile.lock Gemfile.lock 0.0s => CACHED [ 7/10] RUN BUNDLER_VERSION=2.1.2 bundle install 0.0s => CACHED [ 8/10] RUN mkdir -p /myapp 0.0s => CACHED [ 9/10] WORKDIR /myapp 0.0s => CACHED [10/10] ADD . /myapp 0.0s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:c57dc4b7785a80ee5b1a6c2086bda32e5ed8f009d69648a18b0f6ef045ca7400 0.0s => => naming to docker.io/library/everydayrails-rspec-2017_web 0.0s Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them 今回遭遇したエラーというのが、このbuildを行なった時に出たエラーとなります。 エラー文 ### 省略します => CACHED [ 4/10] WORKDIR /tmp 0.0s => CACHED [ 5/10] ADD Gemfile Gemfile 0.0s => CACHED [ 6/10] ADD Gemfile.lock Gemfile.lock 0.0s => ERROR [ 7/10] RUN bundle install ------ > [ 7/10] RUN bundle install: #11 0.555 You must use Bundler 2 or greater with this lockfile. ------ executor failed running [/bin/sh -c bundle install]: exit code: 20 ERROR: Service 'web' failed to build : Build failed bundle installを走らせた時にエラーが発生しているようです。 gemfile.lockにはbundlerのバージョン2を使う必要があるとのことです。 ですが、私の環境ではbundlerは2以上を使っていました。 確認方法としては、 gem list bundler で現在インストールされているものをリストアップ Gemfile.lockの一番下にある BUNDLED WITHを見る これらを行うことでbundlerのバージョンを見ることができます。 バージョンを指定して、bundle installを実行する際には ターミナル bundle _1.16.6_ install と打つことで`1.16.6_を用いてbundle installができます。 ちょっと脱線しましたが、本題に戻ります。 私の環境では、bundlerを2以上で作成しているのにエラーでは2以上がいると怒られています。 ここで対処法としていくつか考えました。 1.バージョンを下げてみる 2.「BUNDLER_VERSION=2.1.2 bundle install」を実行する 3.バージョンを2で指定してみる これくらいしか思いつきませんでした。 それぞれ実行してみると、、、、、、、 2の手順でエラーに変化がありました。 requires ruby version >= 2.6, which is incompatible という文に変わり、rubyのバージョンを2.6以上にしないといけないようです。 なので、dockerファイルのFROMの部分を書き換えます。 FROM ruby:2.7 としてください。 これでbuildができました。 次はdocker-composeの中でbundle installを走らせます。 docker-compose run web bundle install その後 コマンド docker-compose up を入力してください これでlocalhost:3000にアクセスすることで表示されるはずなのですが、実際にアクセスしてみると、エラーになるはずです。 おそらく、databaseが無いと怒られます。私がそうでした。 これを解消するには、 rails db:create rails db:migrate の2つを実行して、databaseを作成しないといけません。 ただこのコマンドを打つだけでは、コンテナの外で実行していることになるので、ちょっとコマンドを追加しないといけません。 docker-compose exec web rails db:create docker-compose exec web rails db:migrate これで何のエラーもなくデータベースが作成されたら成功です! localhost:3000にアクセスすると正常に動くはずです。 まとめ bundlerのエラーが出た時は、バージョンを落とすか上げる。 Gemfile.lockを削除して再度bundle installを実行する 必要に応じてrubyのバージョンも上げること エラー文をよく読むこと 以上です!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

スクラムを友達と回し始めた話(プロローグ)

初めに 趣味開発でもスクラムという手法が使えるのか?ということを試しているスクラム歴1年の僕の話です 状況 チームの人数は僕含めて6人 目的はWebアプリ開発(スケジュール管理アプリ) Webアプリ開発・スクラム共に経験者は僕だけ 現在はsprint3 僕は社会人2年目のAWSを用いてサーバレスシステムを構築していたり、ネイティブアプリを開発していたり多種多様なことをしているエンジニア メンバーはITに関わっているが、SIerだったり、大学生だったりする(今回使う技術は未経験) 全員同じサークル出身のため面識はある 使用ツール・技術 Rails6 Docker git管理 GitHub SourceTree コミュニケーション Slack Skype スクラム管理 Jira Trello どうしてスクラムを始めたか 現在のメンバーが多少なりとも、今の仕事に不満を持っていたり、Webアプリ開発に興味があった 僕がスクラムについてアウトプットする場が欲しかった 今どういう状態か 開発を行う段階ではなく、勉強段階である 勉強にはRailsチュートリアルを用いている 僕が感じた、趣味と業務のスクラムの違い 項目 趣味 開発 僕の役割 SMとPOの兼任 開発チーム 使える時間 週5時間 毎日7時間以上 デイリースクラム Slackで日報投稿 通話MTG スプリント期間 2week 2week スプリントバックログへの意識 超えても趣味だし良いよね 絶対にSprint跨がないこと これからの改善点 僕以外の現役Railsエンジニアorスクラム経験者の獲得(SM or TLが欲しい) スプリントを超えるということが見積もりができないということに繋がることを認知 チームを今より好きになってもらう Railsチュートリアルが嫌になってしまった時も周りにサポートできる姿勢を貫く
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

「Ruby」where文で同じカラムで複数指定する方法

where文で配列を同じカラムで複数指定する方法 変更前 @q = Tweet.where(completed: "0") 変更後 @q = where(completed: ['0', '1']) このように配列にすれば指定できる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

kaminariの導入からオリジナルページネーションデザインを作成する

kmainariのページネーションデザインをどうするかを考えたことがあるかと思います。テンプレートもあるので手軽に作ることもできますがオリジナルがいいなと思ったので今回はその作り方をアウトプットしていきます。 作成するページネーション↓ 基本的にはstyleをあてるだけなので、もっとかっこいいものも作れますよ。 アプリ作成 rails _6.1.4.1_ new kaminari-design -d mysql rails db:create サーバーサイドの構築 scaffoldでサクッと作成していきます。 rails g scaffold post title:string rails db:migrate 初期データの投入 db/seeds.rb 100.times do |i| Post.create!( title: "title#{i + 1}" ) end rails db:seed これで100個のデータが投入されます。 viewで確認 http://localhost:3000/posts title100までできていることが確認できるかと思います。 kaminari導入 gemfile gem 'kaminari' bundle install ページベーションの適用 以下のファイルを編集します。 app/controller/posts_controller.rb def index @posts = Post.all.page(params[:page]).per(5) end app/views/posts/index.html.erb <p id="notice"><%= notice %></p> <h1>Posts</h1> <table> <thead> <tr> <th>Title</th> <th colspan="3"></th> </tr> </thead> <tbody> <% @posts.each do |post| %> <tr> <td><%= post.title %></td> <td><%= link_to 'Show', post %></td> <td><%= link_to 'Edit', edit_post_path(post) %></td> <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </tbody> </table> <%# 追記 %> <%= paginate @posts %> <br> <%= link_to 'New Post', new_post_path %> http://localhost:3000/posts どうでしょうか。これでkaminariの導入が完了です。 ではデザインを適用していきましょう! 次からが肝になってきます。 kaminariのviewファイルを作成 rails g kaminari:views default 以下のファイルが作成されるはずです。 オリジナルデザインの作成 viewと比べてみると First Prev 数字 ... Next Last 現在のページ ページネーション本体  class名  first prev page gap next last cuurent pagination というようにclass名が適用されています。なのでcssでstyleを当てればオリジナルデザインの作成が完了します。 kaminari.cssを以下のフォルダ内に作成し、記述していきましょう! app/assets/stylesheets/kaminari.css .pagination{ width: fit-content; margin: 25px auto; font-size: 0.8rem; line-height: 2rem; } .first a, .prev a, .page a, .next a, .last a{ color: #000000; text-decoration: none; padding: 5px; border: 1px solid #000000; } .first a:hover, .prev a:hover, .page a:hover, .next a:hover, .last a:hover{ border: 1px solid #ffffff;; background-color: #000000; color: #ffffff; } span.current{ color: #777777; } こうすることで以下のようになります。(現在ページ7、カーソル位置5) 以上でオリジナルデザインのページネーションが完了しました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【しくじり先生】失敗続きのエンジニア転職1年間を振り返って最短で満足のいく転職をするにはどうすれば良いかを考えてみた

はじめに こんにちは、28歳未経験から12月より150名規模の自社開発企業で働くことになったもきおです。エンジニア転職を目指し2020年10月に前職を辞め、早1年も経ってしまいました。 仕事をしていながらなら分かるが学習にコミットして流石に一年は長かった。 1年間色々と細かい失敗を繰り返し続けました。でも失敗ばかりだったから伝えられることも多くあると思うんです。そこで今回は今までの流れを振り返りつつ、失敗から何を学びどのようにすればもっと早く満足のいくエンジニア転職ができるかを考えてみました。 書きたいことが多く結構なボリュームになってしまいましたが最後までご覧いただけますと幸いです。 こんな人に読んで欲しい ・プログラミングスクールからエンジニア転職を目指している方 ・独学からエンジニア転職を目指している方 ・エンジニア転職活動をしている方 ・これからプログラミングを学んでエンジニア転職を考えている方 今までの流れ まず初めに「おいもきお、一年も何やってたんだよ」と声が聞こえてきそうなので今までの流れをざっと表で振り返っていきます。 期間 やったこと 2020年10~12月 Progateで基礎固め、DMMWEBCAMP事前学習 2020年12月~3月 DMMWEBCAMP受講 2020年4月~6月 1回目のエンジニア転職活動 2020年7月 フリーランス案件準備、案件結局もらえず 2020年8~10月 実務が積めるエンジニアスクール 2020年10~11月 エンジニア転職活動2回目 実はエンジニア転職活動は2回しています。1回目と2回目は何が違ったのかなどもお伝えできればなと思います。 エンジニアになりたいと思ったら最初にやるべき行動 振り返っていく前に余談を挟みます。 皆さんがエンジニアになりたいと思ったらまず何をするでしょうか? まぁ間違いなくプログラミング学習ですよね。そしてプログラミングスクールに通うか、独学で勉強して転職活動していくかって感じになると思います。 しかしエンジニア系YouTuberのしまぶーさんも仰ってましたが最初にやるべき行動はいきたい企業を探すことです。 いきたい企業を探す→行きたい企業の必要な言語、技術がわかる→必要な言語、技術に対して学習開始→ポートフォリオ作成 この流れが最も明確に学習を進められると思います。 ここでいきたい企業が明確に決まれば問題ないですが最初からそこまで明確には決められないのでスタートアップ系とか大枠の事業内容とかとにかく一旦色んな企業を学習する前、初期段階から見てみるのが良いかなと思います。 また、現役エンジニアの方に積極的にコミュニケーションをとってエンジニア業界の話をまずは聞いてみるのが良いかと思います。現在はTwitter、色んなエンジニアコミュニティなど様々な現役エンジニアの方へのアプローチがあると思います。 2020年10~12月 Progate、DMMWEBCAMP事前学習 そんなこんな言ってますが当時の自分は「プログラミングスクール通ってポートフォリオ作ってエンジニア転職活動すれば転職できるっしょ」くらいに思ってました。 そこで特に仕事を継続して学習しようとはせずプログラミング学習に打ち込むため仕事を辞めることを決意しました。まあ今思えばですけどこの選択は間違ってはなかったとは思います。 さて話を戻して会社を辞めてプログラミング学習を始めたわけですがDMMWEBCAMPはかなり人気で10月から入校したかったのに12月になってしまいました。 なぜDMMWEBCAMPというスクールを選んだのか、実際受講してみてどうだったかはまた別の記事でお伝えしていきたいと思います。 なので最初の2ヶ月はProgateと入校1ヶ月前からDMMWEBCAMPのカリキュラムが配布されるので事前学習をしていました。 事前学習のメリットは振り返ると以下2点 ・本受講で余裕が生まれモチベーション高く学習を進められる ・期限に縛られないで受講できるので理解をしっかりと深め学習できる 当時は今と比べると全然学習時間が取れていませんでしたね。平均3、4時間。多くても6時間くらい。それでも事前学習をできていたのは振り返ってもかなり良かったと思います。 下記Twitterで投票もしてもらいましたが大半が事前学習をするべきを回答していただいていました。どの程度まで事前学習した方がいいのかはこのリンクのスレッドとかで議論されているので良かったらみてください YouTubeのコメントにて「DMMWEBCAMPの事前学習をする必要があると思ってるのはあなただけなんじゃないの」とコメントいただいたので初めて投票機能使ってみたいとおもいます。結果をコメントしていただいた方にご返信するので受講された方はご協力いただけますと幸いです。— もきお (@mokio_50) November 21, 2021 この期間で感じたこと ・事前学習は大事 ・事前学習から危機感を持って学習する 2020年12月~3月DMMWEBCAMP受講 実際の内容とかは後日また記事にしようと思うので省きますが当時の自分を客観的に他受講生と見比べると技術レベルは中の中、あるいは中の下って感じだった気がします。特に後半は結構失速しました笑 受講当時、自分は「学習は量より質でしょ」って思ってたし、「12時間学習しました!」みたいなツイートを見ても「あーそうなんだ」くらいな感じで思ってたしなんなら少ない時間でこれだけ進んでる自分をかっこいいとさえ思ってました(ちょっと誇張してはいるが今考えると普通にキモい)。 そんなこんなで学習時間確保の大切さをわかっていませんでした。よって大体一日6~7時間くらいしか学習していませんでした。今振り返ると圧倒的に絶対的な学習の確保は必要だったなとつくづく思っております。 なぜ絶対的な学習時間の確保が必要であると感じるようになったのか。 それは学習のモチベーション維持にあると思っております。 プログラミング学習はちゃんと継続できる人が、学習する人の1割程度と言われているように様々なところで挫折しそうになるのでモチベーション維持が非常に大切だと感じています。 モチベーション維持のためには小さな成功体験を積み重ねることが大切だと思います。なので質を重視してしまうと、実際思うように学習が進まないときに、モチベーション低下につながります。 一方で量にこだわり学習時間をちゃんと確保していけば学習時間を確保できたことが小さな成功体験になっていくのでモチベーションを維持しやすいのかなと今は感じています。その小さな成功体験によって段々と質の方も自然と良くなっていったなと振り返って見て感じました。 振り返ってみてプログラミングスクールで重要なのは常に危機感を持つことだと思います。 これは井の中の蛙でもないのですが、同期の受講生の中で一番学習した!同期の中で一番技術力がついた!くらい思えるくらい学習しないと満足のいく転職先にいけない可能性は高いです。 これから受講される方はそれくらい高いモチベーションで受講されるのをオススメします。 実際はそんなこともないのですが、要はそれくらいの気持ちで向上心高く貪欲に学習をすると良い方向に進んでいけると思いました。 この期間の失敗から学んだこと ・「質より量」を重視して学習する ・余裕を持つことは大事だが、余裕をぶっこいてると痛い目見るのでどんどん余裕を持って学習できるよう学習を進めていく。 2020年4月~6月 1回目のエンジニア転職活動 さて、プログラミングスクールもなんとか卒業しポートフォリオも一応作成できたので就職活動に移りました。 まず当時の自分のスペックを表にしてみました。客観的にみて10段階評価もつけてみました。 項目 どのくらいやったか 客観的な評価 職務経歴書 ある程度添削してもらい3回くらい修正 7 企業研究 受ける企業を直前に2時間程度 3 面接対策 受ける企業頻出質問5個ぐらい回答を用意 3 ポートフォリオ 一応完成、オリジナリティはある。エラーとかは多発 4 GitHub草 一応毎日生やしてはいた1コミットくらいしかしてない 4 Qiita記事 1記事もかけていなかった 0 この期間の活動を転職活動と学習に分けて振り返っていきたいと思います。 転職活動について 当時はDMMWEBCAMPさんの紹介に任せっきりで自発的に転職活動できていなかったのが一番の失敗した要因だったかなとは振り返ってみて思いました。 エントリー、選考状況は以下でした。 項目 件数 エントリー数 39社 書類選考通過数 11社 一次面接社数 10社 最終面接社数 2社 内定数 1社 内定は一社いただき後に開発経験もしっかり積めそうでしたが、これが本当に自分のやりたかったことなのかと思うと違うと思い辞退しました。 まず転職活動で大事にしたいのは受け身で転職活動をしないこと。 受け身で就活すると特にいきたくない企業ばかり受けることになり、モチベーションも下がるし面接時に志望動機がどうしても弱くなってしまうので企業へ熱意が伝わりづらくなってしまいます。 スクールの紹介は転職活動でのツール(手段)の一つにすぎないという気持ちで転職活動をした方がよっぽど成功する気がしています。これはスクールの紹介企業がダメだとかは全く言っておらず、スクール頼りにならないことが結果的にスクールの紹介で良い企業に内定をもらえたりするからです。 実際現在DMMWEBCAMP生限定のコミュニティであるShuffleというコミュニティに参加させていただいていますが、大半の人が満足のいく企業にスクールの紹介で入社されている印象です。 でもこの方々の多くはWantedlyとかで自ら動いて企業を探してエントリーしつつ、結果的にスクールの紹介企業で内定承諾した人達が多かったです。 よくスクールの紹介以外で転職活動をすると転職保証がなくなりますみたいな感じの制度を持っているスクールが多いですが、これはマジで無視しましょう笑 転職保証に関してはあってないようなものだと思っているくらいがちょうどいいと思います。 大きな決断をしなければいけない転職活動でそういった制度に縛られて視野を狭めるのはやめましょう。正直ここに関してスクール運営をしている企業の方々には申し訳ない発言をしているとは思いますが、本気で満足する企業に就職するにはお伝えしなければいけないと思い、伝えさせていただいております。 学習について プログラミングスクールを卒業してからはJavaと基本情報技術者試験の勉強を進めていました。 振り返ってみるとこれは間違いなく失敗だったと思います笑 内定をいただいた企業で役員との最終面接の際に「やはり目に見えるアウトプットがないと学習の興味度が感じられない。Javaを勉強するのは良いが簡単なポートフォリオを作ってくるくらいじゃないと評価できない。むしろ今まで学習してきたRailsでもう一個自分の興味のある分野でポートフォリオを作るとかの方が俺は好きだなー」っておっしゃってました。この企業はJavaをメインで扱っていて、それでもそうおっしゃるということはやはり成果物がなくただ学習するだけだと評価対象には全くならないんだなと感じました。 なのでJavaやPHPなどRubyは求人数が少ないからみたいな感じで他の言語に手を出して安易に学習するのは間違いなく辞めた方が良いです。 実際その言語でないとできないものを作りたい(Rubyじゃ作れないスマートフォンアプリを作りたい)等具体的なアウトプットや明確にいきたい企業が学習した言語と違うみたいな感じであれば別ですが。 あと2回目の転職活動の方でも書きますが企業が使っている言語を学習していなくても採用される可能性は全然あります。要は何か一つの言語を極めていくこと。これが企業評価として大事なんだなと振り返って思いました。 あと資格は重要なのかについてはそんなにガチで取りに行く必要はないかなと思います。 資格を持っていてもそこまで評価は変わらない。優先順位としては低い感じですかね。 ただコンピューターサイエンスを学ぶ面では良かったと思うので参考書を買ってちょくちょく読んでいると面接の技術質問対策にはなるかなと思いました。 ここまで学習の失敗をダラダラ書いてきましたが転職活動と並行して追加で何を勉強したら企業に評価されるかというとLinux、SQL、 Git、AWSなどのインフラへの理解等、どんなサーバーサイド言語でを使用したとしても汎用性の高いのものを学習するのが良いのかなと思いました。 実際企業に入っても(まだ入社してないけど笑)学習が無駄にならないし、技術質問でも「Linuxコマンドはどんなの使ってましたか?」とかSQL知識を問われたりとか、Gitの使用経験とかも聞かれたので学んでおいて損はないと思います。 あとは作成したポートフォリオのブラッシュアップですかね。テストコード書いたり、エラー修正したり、非同期通信増やしたり。ここら辺はどんな機能を追加したから良いとかではなく、改善する姿勢を見せていくことが重要だと思います。 最後にこのフェーズで言いたいと思ったのは学習習慣を途切れさせないこと。 これはマジで重要だと思います。就活はメインでやっていくのですが1日30分でも良いので必ず1日の何処かで学習するようにした方が良いです。学習習慣が途切れていると就活入ってから学習していないなと面接官にすぐバレます。 学習習慣はマジで脆いです。二、三日学習しないだけでも、もろに崩れていきます。 そして学習が30分しかできなかったと思うのではなく、30分学習できたと自分を褒めてあげてください。これが転職活動が始まった後も学習習慣を途切れさせない秘訣だと自分は思います。 この期間の失敗から学んだこと 転職活動 ・自発的に企業を探していく意識を持つ ・転職保証制度に縛られない ・色んな求人媒体を使用して広い視野を持って企業を探す 学習 ・安易に他の学習をしない ・追加で学ぶなら汎用性の高いものを学習 ・一日30分でも良いから学習の継続週間を途切れさせないようにする ・ちょっとでも学習できた自分を褒めてあげる ・ポートフォリオのブラッシュアップをコンスタントにやる 2020年7月 フリーランス案件準備、案件結局もらえず さて、最終的に内定を辞退して何を思ったのかというと「やはり実務経験を積まないと満足いく企業に就職できないんじゃね?」って思いました。実際そんなことないのにね笑 ただ後に記載しますが短い期間でも実務経験を積めるに越したことはないのも事実です。 そこでフリーランスエンジニアの方に相談し、他のエンジニアの方と一緒に同じ案件に参画できる可能性があるとお伝えされました。1人でやるならまず厳しいけど、他のエンジニアの方と一緒に参画できるならアリかもしれないと思い参画を希望しました。 ただ現実はそんなに甘くはなかった。結果的に未経験だったからか企業に推薦して参画できるかもってなってもその後企業から返信が来なかったりして結局案件に参加することができませんでした。 その期間にLaravelを使用した案件に参画する可能性が高いからLaravelをかじったり、基本その方の案件で多いのはPythonのDjangoだったのでそれをかじったりと学習は瞑想していました。 改めて一つの言語に絞って極めていく重要性を感じた時でもありました。 ここら辺の学習はマジで無駄だったなと思います笑 でもそういった視野を広げてフリーランス業界を知れたのは良かったと思います。 今ではフリーランスの実際の現場とかの話を聞いたからか全くと言っていいほどフリーランスになりたいとは思わないけど笑 この期間で学んだこと ・広く浅く学んでも市場価値は全く変わらない ・フリーランス事情、大変さ ・未経験からフリーランスはほぼ間違いなくやめた方が良い 2020年8~10月 実務が積めるエンジニアスクール入校 学習は瞑想する一方だし、フリーランスエンジニアの方に頼る一方じゃなくて自分でも動かないといけないなと思っていた矢先のこと、YouTubeでちょくちょく拝見させていただいた山浦清人さん @kiyotoyamauraが8月より始まる「実務が詰めるエンジニアスクール」を募集しているではありませんか!! これは応募しない手はない!と思い応募し、無事応募選考を通り入校させていただきました。 このスクールは自分の時は1ヶ月半実務期間、残りは就職活動サポート期間って感じでした。 実際実務をやって思ったのは想像の何倍も大変だったということ。しかも山浦さんにアドバイスをもらいつつもそれくらい大変だったので、1人で実務案件をこなすのはどれだけ大変なんだろうと考えるだけでも嫌になったのを覚えています。笑 でも曲がりなりにも実務案件をやり切れたのは自分の中の経験として非常に大きかったし、面接でもこれだけやったから自信を持って実務案件について説明することができました。 そして実務案件と同じくらいすごく良い経験になったのはその後の就職活動サポートです。 現役エンジニアでもあり、採用担当もされていた山浦さんの提出書類、Wantedlyプロフィール添削、面接対策は本当に参考になったし模擬面接を録画して何度も見返すことでかなり面接力みたいなのがかなりついたと思います。 2020年10~11月 エンジニア転職活動2回目 さて、いよいよ2回目の転職活動が始まりました。また別記事に詳しい就活戦略とかは書いていこうと思うので今回はある程度の概要だけ書こうと思います。 また一回目と同じようにスペックを以下に記載していきます。 項目 どのくらいやったか 客観的な評価 職務経歴書 土台をさらに添削してもらい3回くらい修正 9 企業研究 企業ブログ、コーポレートサイトを網羅的に 10 面接対策 頻出質問網羅的に、録画してひたすら見返す 8 ポートフォリオ ちょくちょく修正はしていた 5 GitHub草 ちゃんと生やしていた。平均5、6コミットくらい 7 Qiita記事 15記事書いた 8 エントリー、選考状況は以下でした。 項目 件数 エントリー数 79社 書類選考通過数 30社 一次面接社数 11社 最終面接社数 5社 内定数 4社 最初は最悪開発経験がある程度早い段階でしっかり積める企業であればいいかな程度に思っていましたが、終わってみれば想像の数倍上手くいったなと感じております。もちろん実務が詰めるスクールでの就活対策も非常に役に立ちましたが、DMMWEBCAMPでの職務経歴書の土台作りがあったからこそスムーズに言ったとつくづく感じました。 学習していない言語を使う企業も内定をいただけました。聞いてみたらやはり未経験の学習なんてたかが知れているので特に学習してきた言語はそこまで見ていないとのこと。それよりも何を考え学習してきたかという学習のプロセスが大事だと企業の人に言われました。 評価されたポイント 内定をいただけた企業、落ちた企業にフィードバックをひたすら求め評価していただいた点を羅列しておきます。 ・積極的に自ら技術にキャッチアップし自走できるタイプと判断 ・忍耐力と柔軟性を兼ね備えている ・未経験だが努力できる性格 ・人柄も、勉強熱心な姿勢もベンチャー向きな印象 ・受け答えも端的で落ち着いている ・未経験ながら要件定義〜開発と弊社で生かせる実務を経験 ・エンジニアとして大切な技術に対する向上心がある ・一緒に会社を創っていきたいメンバーだと思えた ・Qiita記事を継続的にアウトプットしている ・ポートフォリオのコンセプトは良い 面接に落ちた理由 また面接に落ちた理由もフィードバックを求めたら何社かもらえたので羅列しておきます。 ・技術力を付けたい気持ち、技術的ポテンシャルは感じるが会社への貢献欲求が感じられない ・継続的にうちの会社で働く気があまり感じられない ・実際に面接してみて必要なスキル面がうちの基準に満たない ・サービスに対する見方や志向性の部分がポートフォリオに落とし込み切れていない これらから企業が未経験の中でどういう人材を求めていてどこら辺を軸に活動すれば良いかを最後に記載して終わろうと思います。 これからエンジニア転職活動される方へ まず大前提として意識しておくべきなのは面接を通じて面接官に一緒に働きたいと思ってもらうことです。常にここは頭の片隅に置いておくのが良いかなと思います。面接対策をしているときもこの発言は相手が一緒に働きたいと思える発言なのかという感じで。 2回にわたるエンジニア転職活動で重要だと感じたのはコミュニケーション能力とかそう言った前提のものはもちろん必要だとして企業への熱意をしっかりと伝えられる状態にすること、技術への興味関心をしっかりと伝えていくことの2点が重要だと感じました。ここら辺を深ぼっていきます。 企業への熱意をしっかりと伝えられる状態にするには ここに関しては基本的なことになりますが、企業をよく知ること、自社開発企業であれば自社サービスをよく知ることの2つ重要になってくると思いました。 ・企業をよく知ること とにかく企業のコーポレートサイトを始め、wantedlyの企業サイトでのストーリーや募集要項の読み込み、ブログをやっているならそこら辺もしっかり読み込むことが大事だと思います。 これだけだと普通だし、どこを意識して読めばいいんだよと言われそうなのでもう少し深く記載していきます。 どう言ったところを意識して読めばいいのかというと社員インタビュー、技術ブログ記事は結構読み込んだ方が良いです。 また役員面接とかになってくるとしたらその人の名前で検索して出てきた記事を片っ端から読んでいました。 そこでいろんな価値観や考え方が書かれており、色々見ていくと自分が共感できる部分も何個か出てくると思います。自分は面接時に「この方がこういったことをブログに書かれていて自分もこう言った体験があったので非常に共感できました」とカルチャーへの共感を伝えていました。ただカルチャーや企業理念に共感したとかそう言ったものを伝えてしまうと上部な感じや薄いなと思われるのがオチです。 ・自社サービスをよく知ること これは実際に使ってみる、Twitterとかでそのサービスを調べ他の人がレビューしていたりしていないかなどを探してみる、また強豪他社になるサービスを調べて比較してみたりするのが良いかと思います。 サービスの良かったところ、今後こう言った風に機能改善して行きたいとお伝えできるとちゃんと見てくれてるなと思ってもらえると思います。ここで難しいのが機能改善提案は良いのですが一歩間違えると上から目線に捉えられてしまう可能性もあるので伝えるときには注意が必要です。「未経験なのに何言ってんだみたいな感じで聞いていただければ幸いなんですけど」みたいな感じで枕詞を最初に添えてお伝えしていった方が良いかなと思います。 技術への興味関心を伝えるには まず代表的なのはもちろんポートフォリオだと思います。継続的にブラッシュアップしていき完成度の高いポートフォリオにしていくのは企業評価としても高いのではないかなと思います。 しかしそれ以外にも技術的な興味を伝えるアプローチは沢山あります。自分が力を入れたのはQiitaでのアウトプットです。ただメモ用みたいな感じの記事ではなく、しっかりと学んだ技術を理解しているなと感じさせられるような記事を書けると良いのかなと思いました。そう言った記事が書ければ自然と他の方から見られる回数も多くなりLGTMやストックなど数字としても良いアピールができるかと思います。 あとはIoT機器に触れたり、LINEbotとAWS Lambdaを使用し何か自宅のポストに投函されたらラインに通知がいくような装置を作る、みたいな感じで面白そうだからやってみた的な体験が一つでもできると技術的興味を伝えられると思います。 自分はお風呂の換気扇を自動停止する環境をIoT機器で作ってみました笑 あと学習面で評価されたのは日報作成でした。実務が詰めるエンジニアスクール開始当初から3ヶ月以上日報を書いていて就活が始まった後もずっと書いていたのをWantedlyプロフィールに載せていたのですが、これは思ってたより面接にて触れていただく機会が多く評価されたと思います。 あとがき コロナ影響からか現状かなり未経験からエンジニアを目指す方が増えており、未経験からのエンジニア転職は完全に買い手市場になっているとは思います。 しかしながら継続的に学習し、しっかりとした就活対策をすれば満足のいける企業に入社できる可能性があるのも事実だなと今回改めて転職活動をしてみて思いました。 努力は必ず報われるなんていう無責任なことは言えないけれど、継続的に努力していければ必ず良い方向に向かっていくことができる。自分自身もそういう気持ちで入社後も貪欲に技術力を磨いて行きたいと思います。 最後までご覧いただき本当にありがとうございました!! 少しでも良かったと思っていただけたらLGTMポチッといただけますと幸いです。 Twitterでも今後も転職活動で思ったことを呟いていくのでご覧いただけると幸いです。 @mokio_50
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【しくじり先生】失敗続きの未経験からのエンジニア転職1年間を振り返って最短で満足のいく転職をするにはどうすれば良いかを考えてみた

はじめに こんにちは、28歳未経験から12月より150名規模の自社開発企業で働くことになったもきおです。エンジニア転職を目指し2020年10月に前職を辞め、早1年も経ってしまいました。 仕事をしていながらなら分かるが学習にコミットして流石に一年は長かった。 1年間色々と細かい失敗を繰り返し続けました。でも失敗ばかりだったから伝えられることも多くあると思うんです。そこで今回は今までの流れを振り返りつつ、失敗から何を学びどのようにすればもっと早く満足のいくエンジニア転職ができるかを考えてみました。 書きたいことが多く結構なボリュームになってしまいましたが最後までご覧いただけますと幸いです。 こんな人に読んで欲しい ・プログラミングスクールからエンジニア転職を目指している方 ・独学からエンジニア転職を目指している方 ・エンジニア転職活動をしている方 ・これからプログラミングを学んでエンジニア転職を考えている方 今までの流れ まず初めに「おいもきお、一年も何やってたんだよ」と声が聞こえてきそうなので今までの流れをざっと表で振り返っていきます。 期間 やったこと 2020年10~12月 Progateで基礎固め、DMMWEBCAMP事前学習 2020年12月~3月 DMMWEBCAMP受講 2020年4月~6月 1回目のエンジニア転職活動 2020年7月 フリーランス案件準備、案件結局もらえず 2020年8~10月 実務が積めるエンジニアスクール 2020年10~11月 エンジニア転職活動2回目 実はエンジニア転職活動は2回しています。1回目と2回目は何が違ったのかなどもお伝えできればなと思います。 エンジニアになりたいと思ったら最初にやるべき行動 振り返っていく前に余談を挟みます。 皆さんがエンジニアになりたいと思ったらまず何をするでしょうか? まぁ間違いなくプログラミング学習ですよね。そしてプログラミングスクールに通うか、独学で勉強して転職活動していくかって感じになると思います。 しかしエンジニア系YouTuberのしまぶーさんも仰ってましたが最初にやるべき行動はいきたい企業を探すことです。 いきたい企業を探す→行きたい企業の必要な言語、技術がわかる→必要な言語、技術に対して学習開始→ポートフォリオ作成 この流れが最も明確に学習を進められると思います。 ここでいきたい企業が明確に決まれば問題ないですが最初からそこまで明確には決められないのでスタートアップ系とか大枠の事業内容とかとにかく一旦色んな企業を学習する前、初期段階から見てみるのが良いかなと思います。 また、現役エンジニアの方に積極的にコミュニケーションをとってエンジニア業界の話をまずは聞いてみるのが良いかと思います。現在はTwitter、色んなエンジニアコミュニティなど様々な現役エンジニアの方へのアプローチがあると思います。 2020年10~12月 Progate、DMMWEBCAMP事前学習 そんなこんな言ってますが当時の自分は「プログラミングスクール通ってポートフォリオ作ってエンジニア転職活動すれば転職できるっしょ」くらいに思ってました。 そこで特に仕事を継続して学習しようとはせずプログラミング学習に打ち込むため仕事を辞めることを決意しました。まあ今思えばですけどこの選択は間違ってはなかったとは思います。 さて話を戻して会社を辞めてプログラミング学習を始めたわけですがDMMWEBCAMPはかなり人気で10月から入校したかったのに12月になってしまいました。 なぜDMMWEBCAMPというスクールを選んだのか、実際受講してみてどうだったかはまた別の記事でお伝えしていきたいと思います。 なので最初の2ヶ月はProgateと入校1ヶ月前からDMMWEBCAMPのカリキュラムが配布されるので事前学習をしていました。 事前学習のメリットは振り返ると以下2点 ・本受講で余裕が生まれモチベーション高く学習を進められる ・期限に縛られないで受講できるので理解をしっかりと深め学習できる 当時は今と比べると全然学習時間が取れていませんでしたね。平均3、4時間。多くても6時間くらい。それでも事前学習をできていたのは振り返ってもかなり良かったと思います。 下記Twitterで投票もしてもらいましたが大半が事前学習をするべきを回答していただいていました。どの程度まで事前学習した方がいいのかはこのリンクのスレッドとかで議論されているので良かったらみてください YouTubeのコメントにて「DMMWEBCAMPの事前学習をする必要があると思ってるのはあなただけなんじゃないの」とコメントいただいたので初めて投票機能使ってみたいとおもいます。結果をコメントしていただいた方にご返信するので受講された方はご協力いただけますと幸いです。— もきお (@mokio_50) November 21, 2021 この期間で感じたこと ・事前学習は大事 ・事前学習から危機感を持って学習する 2020年12月~3月DMMWEBCAMP受講 実際の内容とかは後日また記事にしようと思うので省きますが当時の自分を客観的に他受講生と見比べると技術レベルは中の中、あるいは中の下って感じだった気がします。特に後半は結構失速しました笑 受講当時、自分は「学習は量より質でしょ」って思ってたし、「12時間学習しました!」みたいなツイートを見ても「あーそうなんだ」くらいな感じで思ってたしなんなら少ない時間でこれだけ進んでる自分をかっこいいとさえ思ってました(ちょっと誇張してはいるが今考えると普通にキモい)。 そんなこんなで学習時間確保の大切さをわかっていませんでした。よって大体一日6~7時間くらいしか学習していませんでした。今振り返ると圧倒的に絶対的な学習の確保は必要だったなとつくづく思っております。 なぜ絶対的な学習時間の確保が必要であると感じるようになったのか。 それは学習のモチベーション維持にあると思っております。 プログラミング学習はちゃんと継続できる人が、学習する人の1割程度と言われているように様々なところで挫折しそうになるのでモチベーション維持が非常に大切だと感じています。 モチベーション維持のためには小さな成功体験を積み重ねることが大切だと思います。なので質を重視してしまうと、実際思うように学習が進まないときに、モチベーション低下につながります。 一方で量にこだわり学習時間をちゃんと確保していけば学習時間を確保できたことが小さな成功体験になっていくのでモチベーションを維持しやすいのかなと今は感じています。その小さな成功体験によって段々と質の方も自然と良くなっていったなと振り返って見て感じました。 振り返ってみてプログラミングスクールで重要なのは常に危機感を持つことだと思います。 これは井の中の蛙でもないのですが、同期の受講生の中で一番学習した!同期の中で一番技術力がついた!くらい思えるくらい学習しないと満足のいく転職先にいけない可能性は高いです。 これから受講される方はそれくらい高いモチベーションで受講されるのをオススメします。 実際はそんなこともないのですが、要はそれくらいの気持ちで向上心高く貪欲に学習をすると良い方向に進んでいけると思いました。 この期間の失敗から学んだこと ・「質より量」を重視して学習する ・余裕を持つことは大事だが、余裕をぶっこいてると痛い目見るのでどんどん余裕を持って学習できるよう学習を進めていく。 2020年4月~6月 1回目のエンジニア転職活動 さて、プログラミングスクールもなんとか卒業しポートフォリオも一応作成できたので就職活動に移りました。 まず当時の自分のスペックを表にしてみました。客観的にみて10段階評価もつけてみました。 項目 どのくらいやったか 客観的な評価 職務経歴書 ある程度添削してもらい3回くらい修正 7 企業研究 受ける企業を直前に2時間程度 3 面接対策 受ける企業頻出質問5個ぐらい回答を用意 3 ポートフォリオ 一応完成、オリジナリティはある。エラーとかは多発 4 GitHub草 一応毎日生やしてはいた1コミットくらいしかしてない 4 Qiita記事 1記事もかけていなかった 0 この期間の活動を転職活動と学習に分けて振り返っていきたいと思います。 転職活動について 当時はDMMWEBCAMPさんの紹介に任せっきりで自発的に転職活動できていなかったのが一番の失敗した要因だったかなとは振り返ってみて思いました。 エントリー、選考状況は以下でした。 項目 件数 エントリー数 39社 書類選考通過数 11社 一次面接社数 10社 最終面接社数 2社 内定数 1社 内定は一社いただき後に開発経験もしっかり積めそうでしたが、これが本当に自分のやりたかったことなのかと思うと違うと思い辞退しました。 まず転職活動で大事にしたいのは受け身で転職活動をしないこと。 受け身で就活すると特にいきたくない企業ばかり受けることになり、モチベーションも下がるし面接時に志望動機がどうしても弱くなってしまうので企業へ熱意が伝わりづらくなってしまいます。 スクールの紹介は転職活動でのツール(手段)の一つにすぎないという気持ちで転職活動をした方がよっぽど成功する気がしています。これはスクールの紹介企業がダメだとかは全く言っておらず、スクール頼りにならないことが結果的にスクールの紹介で良い企業に内定をもらえたりするからです。 実際現在DMMWEBCAMP生限定のコミュニティであるShuffleというコミュニティに参加させていただいていますが、大半の人が満足のいく企業にスクールの紹介で入社されている印象です。 でもこの方々の多くはWantedlyとかで自ら動いて企業を探してエントリーしつつ、結果的にスクールの紹介企業で内定承諾した人達が多かったです。 よくスクールの紹介以外で転職活動をすると転職保証がなくなりますみたいな感じの制度を持っているスクールが多いですが、これはマジで無視しましょう笑 転職保証に関してはあってないようなものだと思っているくらいがちょうどいいと思います。 大きな決断をしなければいけない転職活動でそういった制度に縛られて視野を狭めるのはやめましょう。正直ここに関してスクール運営をしている企業の方々には申し訳ない発言をしているとは思いますが、本気で満足する企業に就職するにはお伝えしなければいけないと思い、伝えさせていただいております。 学習について プログラミングスクールを卒業してからはJavaと基本情報技術者試験の勉強を進めていました。 振り返ってみるとこれは間違いなく失敗だったと思います笑 内定をいただいた企業で役員との最終面接の際に「やはり目に見えるアウトプットがないと学習の興味度が感じられない。Javaを勉強するのは良いが簡単なポートフォリオを作ってくるくらいじゃないと評価できない。むしろ今まで学習してきたRailsでもう一個自分の興味のある分野でポートフォリオを作るとかの方が俺は好きだなー」っておっしゃってました。この企業はJavaをメインで扱っていて、それでもそうおっしゃるということはやはり成果物がなくただ学習するだけだと評価対象には全くならないんだなと感じました。 なのでJavaやPHPなどRubyは求人数が少ないからみたいな感じで他の言語に手を出して安易に学習するのは間違いなく辞めた方が良いです。 実際その言語でないとできないものを作りたい(Rubyじゃ作れないスマートフォンアプリを作りたい)等具体的なアウトプットや明確にいきたい企業が学習した言語と違うみたいな感じであれば別ですが。 あと2回目の転職活動の方でも書きますが企業が使っている言語を学習していなくても採用される可能性は全然あります。要は何か一つの言語を極めていくこと。これが企業評価として大事なんだなと振り返って思いました。 あと資格は重要なのかについてはそんなにガチで取りに行く必要はないかなと思います。 資格を持っていてもそこまで評価は変わらない。優先順位としては低い感じですかね。 ただコンピューターサイエンスを学ぶ面では良かったと思うので参考書を買ってちょくちょく読んでいると面接の技術質問対策にはなるかなと思いました。 ここまで学習の失敗をダラダラ書いてきましたが転職活動と並行して追加で何を勉強したら企業に評価されるかというとLinux、SQL、 Git、AWSなどのインフラへの理解等、どんなサーバーサイド言語を使用したとしても汎用性の高いのものを学習するのが良いのかなと思いました。 実際企業に入っても(まだ入社してないけど笑)学習が無駄にならないし、技術質問でも「Linuxコマンドはどんなの使ってましたか?」とかSQL知識を問われたりとか、Gitの使用経験とかも聞かれたので学んでおいて損はないと思います。 あとは作成したポートフォリオのブラッシュアップですかね。テストコード書いたり、エラー修正したり、非同期通信増やしたり。ここら辺はどんな機能を追加したから良いとかではなく、改善する姿勢を見せていくことが重要だと思います。 最後にこのフェーズで言いたいと思ったのは学習習慣を途切れさせないこと。 これはマジで重要だと思います。就活はメインでやっていくのですが1日30分でも良いので必ず1日の何処かで学習するようにした方が良いです。学習習慣が途切れていると就活入ってから学習していないなと面接官にすぐバレます。 学習習慣はマジで脆いです。二、三日学習しないだけでも、もろに崩れていきます。 そして学習が30分しかできなかったと思うのではなく、30分学習できたと自分を褒めてあげてください。これが転職活動が始まった後も学習習慣を途切れさせない秘訣だと自分は思います。 この期間の失敗から学んだこと 転職活動 ・自発的に企業を探していく意識を持つ ・転職保証制度に縛られない ・色んな求人媒体を使用して広い視野を持って企業を探す 学習 ・安易に他の学習をしない ・追加で学ぶなら汎用性の高いものを学習 ・一日30分でも良いから学習の継続週間を途切れさせないようにする ・ちょっとでも学習できた自分を褒めてあげる ・ポートフォリオのブラッシュアップをコンスタントにやる 2020年7月 フリーランス案件準備、案件結局もらえず さて、最終的に内定を辞退して何を思ったのかというと「やはり実務経験を積まないと満足いく企業に就職できないんじゃね?」って思いました。実際そんなことないのにね笑 ただ後に記載しますが短い期間でも実務経験を積めるに越したことはないのも事実です。 そこでフリーランスエンジニアの方に相談し、他のエンジニアの方と一緒に同じ案件に参画できる可能性があるとお伝えされました。1人でやるならまず厳しいけど、他のエンジニアの方と一緒に参画できるならアリかもしれないと思い参画を希望しました。 ただ現実はそんなに甘くはなかった。結果的に未経験だったからか企業に推薦して参画できるかもってなってもその後企業から返信が来なかったりして結局案件に参加することができませんでした。 その期間にLaravelを使用した案件に参画する可能性が高いからLaravelをかじったり、基本その方の案件で多いのはPythonのDjangoだったのでそれをかじったりと学習は瞑想していました。 改めて一つの言語に絞って極めていく重要性を感じた時でもありました。 ここら辺の学習はマジで無駄だったなと思います笑 でもそういった視野を広げてフリーランス業界を知れたのは良かったと思います。 今ではフリーランスの実際の現場とかの話を聞いたからか全くと言っていいほどフリーランスになりたいとは思わないけど笑 この期間で学んだこと ・広く浅く学んでも市場価値は全く変わらない ・フリーランス事情、大変さ ・未経験からフリーランスはほぼ間違いなくやめた方が良い 2020年8~10月 実務が積めるエンジニアスクール入校 学習は瞑想する一方だし、フリーランスエンジニアの方に頼る一方じゃなくて自分でも動かないといけないなと思っていた矢先のこと、YouTubeでちょくちょく拝見させていただいた山浦清人さん @kiyotoyamauraが8月より始まる「実務が詰めるエンジニアスクール」を募集しているではありませんか!! これは応募しない手はない!と思い応募し、無事応募選考を通り入校させていただきました。 このスクールは自分の時は全体で3ヶ月、1ヶ月半実務期間、1ヶ月半転職サポート期間って感じでした。現在は2ヶ月実務期間、2ヶ月転職サポートとなっているみたいです。 実務案件の詳しい内容は以下にまとめています。 実際実務をやって思ったのは想像の何倍も大変だったということ。しかも山浦さんにアドバイスをもらいつつもそれくらい大変だったので、1人で実務案件をこなすのはどれだけ大変なんだろうと考えるだけでも嫌になったのを覚えています。笑 でも曲がりなりにも実務案件をやり切れたのは自分の中の経験として非常に大きかったし、面接でもこれだけやったから自信を持って実務案件について説明することができました。 そして実務案件と同じくらいすごく良い経験になったのはその後の就職活動サポートです。 現役エンジニアでもあり、採用担当もされていた山浦さんの提出書類、Wantedlyプロフィール添削、面接対策は本当に参考になったし模擬面接を録画して何度も見返すことでかなり面接力みたいなのがかなりついたと思います。 2020年10~11月 エンジニア転職活動2回目 さて、いよいよ2回目の転職活動が始まりました。また別記事に詳しい就活戦略とかは書いていこうと思うので今回はある程度の概要だけ書こうと思います。 また一回目と同じようにスペックを以下に記載していきます。 項目 どのくらいやったか 客観的な評価 職務経歴書 土台をさらに添削してもらい3回くらい修正 9 企業研究 企業ブログ、コーポレートサイトを網羅的に 10 面接対策 頻出質問網羅的に、録画してひたすら見返す 8 ポートフォリオ ちょくちょく修正はしていた 5 GitHub草 ちゃんと生やしていた。平均5、6コミットくらい 7 Qiita記事 15記事書いた 8 エントリー、選考状況は以下でした。 項目 件数 エントリー数 79社 書類選考通過数 30社 一次面接社数 11社 最終面接社数 5社 内定数 4社 最初は最悪開発経験がある程度早い段階でしっかり積める企業であればいいかな程度に思っていましたが、終わってみれば想像の数倍上手くいったなと感じております。もちろん実務が詰めるスクールでの就活対策も非常に役に立ちましたが、DMMWEBCAMPでの職務経歴書の土台作りがあったからこそスムーズに言ったとつくづく感じました。 自分自身最初はSES、受託、自社開発を絞らずとりあえず使いたいサーバーサイド言語で企業を調べていましたが、調べていくうちに自分自身やっている事業への関心がとても高いことに気づきました。「やっている事業に共感できる、面白いと思える企業に行きたい!」と思ったので自社開発企業に段々と絞って就職活動を進めて行きました。 よって面接をする企業もだんだんと絞ったため30社書類通過しても結果的に11社のみしか受けなかったです。それによって一社一社しっかりと準備できたのは良かったかなと思います。 学習していない言語を使う企業も内定をいただけました。聞いてみたらやはり未経験の学習なんてたかが知れているので特に学習してきた言語はそこまで見ていないとのこと。それよりも何を考え学習してきたかという学習のプロセスが大事だと企業の人に言われました。 評価されたポイント 内定をいただけた企業、落ちた企業にフィードバックをひたすら求め評価していただいた点を羅列しておきます。 ・積極的に自ら技術にキャッチアップし自走できるタイプと判断 ・忍耐力と柔軟性を兼ね備えている ・未経験だが努力できる性格 ・人柄も、勉強熱心な姿勢もベンチャー向きな印象 ・受け答えも端的で落ち着いている ・未経験ながら要件定義〜開発と弊社で生かせる実務を経験 ・エンジニアとして大切な技術に対する向上心がある ・一緒に会社を創っていきたいメンバーだと思えた ・Qiita記事を継続的にアウトプットしている ・ポートフォリオのコンセプトは良い 面接に落ちた理由 また面接に落ちた理由もフィードバックを求めたら何社かもらえたので羅列しておきます。 ・技術力を付けたい気持ち、技術的ポテンシャルは感じるが会社への貢献欲求が感じられない ・継続的にうちの会社で働く気があまり感じられない ・実際に面接してみて必要なスキル面がうちの基準に満たない ・サービスに対する見方や志向性の部分がポートフォリオに落とし込み切れていない これらから企業が未経験の中でどういう人材を求めていてどこら辺を軸に活動すれば良いかを最後に記載して終わろうと思います。 これからエンジニア転職活動される方へ まず大前提として意識しておくべきなのは面接を通じて面接官に一緒に働きたいと思ってもらうことです。常にここは頭の片隅に置いておくのが良いかなと思います。面接対策をしているときもこの発言は相手が一緒に働きたいと思える発言なのかという感じで。 2回にわたるエンジニア転職活動で重要だと感じたのはコミュニケーション能力とかそう言った前提のものはもちろん必要だとして企業への熱意をしっかりと伝えられる状態にすること、技術への興味関心をしっかりと伝えていくことの2点が重要だと感じました。ここら辺を深ぼっていきます。 企業への熱意をしっかりと伝えられる状態にするには ここに関しては基本的なことになりますが、企業をよく知ること、自社開発企業であれば自社サービスをよく知ることの2つ重要になってくると思いました。 ・企業をよく知ること とにかく企業のコーポレートサイトを始め、wantedlyの企業サイトでのストーリーや募集要項の読み込み、ブログをやっているならそこら辺もしっかり読み込むことが大事だと思います。 これだけだと普通だし、どこを意識して読めばいいんだよと言われそうなのでもう少し深く記載していきます。 どう言ったところを意識して読めばいいのかというと社員インタビュー、技術ブログ記事は結構読み込んだ方が良いです。 また役員面接とかになってくるとしたらその人の名前で検索して出てきた記事を片っ端から読んでいました。 そこでいろんな価値観や考え方が書かれており、色々見ていくと自分が共感できる部分も何個か出てくると思います。自分は面接時に「この方がこういったことをブログに書かれていて自分もこう言った体験があったので非常に共感できました」とカルチャーへの共感を伝えていました。ただカルチャーや企業理念に共感したとかそう言ったものを伝えてしまうと上部な感じや薄いなと思われるのがオチです。 ・自社サービスをよく知ること これは実際に使ってみる、Twitterとかでそのサービスを調べ他の人がレビューしていたりしていないかなどを探してみる、また強豪他社になるサービスを調べて比較してみたりするのが良いかと思います。 サービスの良かったところ、今後こう言った風に機能改善して行きたいとお伝えできるとちゃんと見てくれてるなと思ってもらえると思います。ここで難しいのが機能改善提案は良いのですが一歩間違えると上から目線に捉えられてしまう可能性もあるので伝えるときには注意が必要です。「未経験なのに何言ってんだみたいな感じで聞いていただければ幸いなんですけど」みたいな感じで枕詞を最初に添えてお伝えしていった方が良いかなと思います。 技術への興味関心を伝えるには まず代表的なのはもちろんポートフォリオだと思います。継続的にブラッシュアップしていき完成度の高いポートフォリオにしていくのは企業評価としても高いのではないかなと思います。 しかしそれ以外にも技術的な興味を伝えるアプローチは沢山あります。自分が力を入れたのはQiitaでのアウトプットです。ただメモ用みたいな感じの記事ではなく、しっかりと学んだ技術を理解しているなと感じさせられるような記事を書けると良いのかなと思いました。そう言った記事が書ければ自然と他の方から見られる回数も多くなりLGTMやストックなど数字としても良いアピールができるかと思います。 あとはIoT機器に触れたり、LINEbotとAWS Lambdaを使用し何か自宅のポストに投函されたらラインに通知がいくような装置を作る、みたいな感じで面白そうだからやってみた的な体験が一つでもできると技術的興味を伝えられると思います。 自分はお風呂の換気扇を自動停止する環境をIoT機器で作ってみました笑 あと学習面で評価されたのは日報作成でした。実務が詰めるエンジニアスクール開始当初から3ヶ月以上日報を書いていて就活が始まった後もずっと書いていたのをWantedlyプロフィールに載せていたのですが、これは思ってたより面接にて触れていただく機会が多く評価されたと思います。 あとがき コロナ影響からか現状かなり未経験からエンジニアを目指す方が増えており、未経験からのエンジニア転職は完全に買い手市場になっているとは思います。 しかしながら継続的に学習し、しっかりとした就活対策をすれば満足のいける企業に入社できる可能性があるのも事実だなと今回改めて転職活動をしてみて思いました。 努力は必ず報われるなんていう無責任なことは言えないけれど、継続的に努力していければ必ず良い方向に向かっていくことができる。自分自身もそういう気持ちで入社後も貪欲に技術力を磨いて行きたいと思います。 最後までご覧いただき本当にありがとうございました!! 少しでも良かったと思っていただけたらLGTMポチッといただけますと幸いです。 Twitterでも今後も転職活動で思ったことを呟いていくのでご覧いただけると幸いです。 @mokio_50
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

インチキをしてRailsでExcelを読み書きする

Excel大好きな人達 多くの案件ではExcel好きなプロパーとかExcel好きなプロパーとかExcel好きなプロパーが跋扈しており、確固たる理由はないがなんとなく「Excelライクで」とか言われることが非常に多いと感じています。 Excelライクと言わないまでも、Excelをアップロードできたりダウンロードできたりと言った要件は、非常にカジュアルに生じています。 「DXの意味わかっているの?」と言いたくなるのですが、これが原状なのでしょうがありません。 Railsライブラリの限界 ただ、Railsエンジニアなら一度は経験したことがあると思うのですが、RailsにはExcelをうまく扱えるライブラリがあまりありません。 ライブラリ 機能 注記 Axlsx 新規作成から書き出しだけ 新規作成のみで、テンプレートファイルからの新規作成もできない。複雑なワークシートを作ろうと思うと、コードが恐ろしく読みにくくなる Roo 読み込みだけ 読み込み専用 RubyXL 読み書き可能 数少ない読み書き可能なライブラリだが、parseが恐ろしく遅いのであまり使い物にならない Pythonにはopenpyxlがある 一方、Pythonは世界中のデータサイエンティストが使っていることもあって、openpyxlという非常に使いやすいライブラリが存在して、ものすごく手軽に扱うことが可能になっています。 今回は、Rubyからopenpyxlを呼び出してみました。 コンテナにpython及びライブラリを入れる 今回はDockerを使っている前提で、Rubyの動いているコンテナにpythonをインストールします。システム管理やaws-cliを動かすためにすでに入っているケースも多いと思います。 Dockerfile FROM ruby:2.7.4-alpine RUN mkdir /app ENV APP_ROOT /app WORKDIR $APP_ROOT RUN apk add --update --no-cache \ ... python3 python3-dev py3-pip && \ pip install openpyxl ... コンテナを使っていない場合はvenvを使ったほうがいいと思いますが、本稿では触れません。 簡単なPythonスクリプトを作成する ここでは、標準入力から{"A1": "Hello, World!"}のようなJSONを受け取り、テンプレートのExcelファイルに書き込んだうえ、そのExcelファイルを標準出力に書き出すスクリプトを作成しました。 メインのロジックをあまりRailsの外におきたくなかったので、極力シンプルにしています。 python/to_excel.py import os import sys import json import openpyxl import tempfile cell_values = json.loads(sys.stdin.read()) wb = openpyxl.load_workbook("spec/fixtures/template.xlsx") ws = wb.worksheets[0] for cell, value in cell_values.items(): ws[cell] = value tmp = tempfile.NamedTemporaryFile(delete=False) wb.save(tmp.name) tmp.close() with open(tmp.name, 'rb') as f: sys.stdout.buffer.write(f.read()) os.unlink(tmp.name) Ruby(Rails)からpopenでpythonを呼び出す excel = IO.popen('python3 python/to_excel.py', 'r+') do |io| io.puts cell_values.to_json io.close_write io.read end excelにはExcelファイルのバイナリが入ります。ActiveStorageに入れるなり、send_dataするなりして料理しましょう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Railsチュートリアル】いいね機能の実装(アニメーション付)

はじめに 前回の記事改【Railsチュートリアル】プロフィール画像をアプリ内で設定できるように変更に引き続きRailsチュートリアル第6版sample_appの機能拡張を進めていく。 今回は以下の様ないいね機能を実装していく。 instagramのいいねボタンによく似たハートが膨らむアニメーションを付けている。 前提 第6版sample_appが完成している Favoriteモデル Favoriteテーブルを追加 $ rails g model Favorite user_id:integer micropost_id:integer user_idとmicropost_idにインデックスを追加し、組み合わせがユニークであるという複合キーインデックスも追加する。 db/migrate/[timestamp]_create_favorites.rb class CreateFavorites < ActiveRecord::Migration[6.1] def change create_table :favorites do |t| t.integer :user_id t.integer :micropost_id t.timestamps end add_index :favorites, :user_id add_index :favorites, :micropost_id add_index :favorites, [:user_id, :micropost_id], unique: true end end $ rails db:migrate ユーザーとマイクロポストに、Favoriteに対して1対多の関連づけを追加し、またhas_many throughを用いてuser.likesとmicropost.liked_byを使えるようにする。 app/models/user.rb class User < ApplicationRecord . . . has_many :favorites, dependent: :destroy has_many :likes, through: :favorites, source: :micropost . . . end app/models/micropost.rb class Micropost < ApplicationRecord . . . has_many :favorites, dependent: :destroy has_many :liked_by, through: :favorites, source: :user . . . end app/models/favorite.rb class Favorite < ApplicationRecord belongs_to :user belongs_to :micropost validates :user_id, presence: true validates :micropost_id, presence: true end ユーザーモデルにメソッドを追加する。 app/models/user.rb class User < ApplicationRecord . . . # マイクロポストをライクする def like(micropost) likes << micropost end # マイクロポストをライク解除する def unlike(micropost) favorites.find_by(micropost_id: micropost.id).destroy end # 現在のユーザーがライクしていたらtrueを返す def likes?(micropost) likes.include?(micropost) end private . . . end ルーティングを追加する。 config/routes.rb Rails.application.routes.draw do . . . resources :users do member do get :following, :followers , :likes end end . . . end likeページの作成 ステータスページにlike数を追加。 app/views/shared/_status.html.erb <% @user ||= current_user %> . . . <a href="<%= likes_user_path(@user) %>"> <strong id="likes" class="stat"> <%= @user.likes.count %> </strong> likes </a> </div> ユーザーコントローラーにlikeアクションを追加。 app/controllers/users_controller.rb class UsersController < ApplicationController . . . def likes @title = "Likes" @user = User.find(params[:id]) @microposts = @user.likes.paginate(page: params[:page]) render 'show_like' end private . . . end ビューを作成する。 gravatarの部分はこちらの記事でimage_tagに変更している。 app/viwes/users/show_like.html.erb <% provide(:title, @user.name) %> <div class="row"> <aside class="col-md-4"> <section class="user_info"> <% if @user.avatar? %> <%= image_tag @user.avatar.url, width: "100px", height: "100px", class:"icon"%> <% else%> <%= image_tag "default_user.jpeg", width: "100px", height: "100px", class:"icon"%> <% end %> <h1><%= @user.name %></h1> <span><%= link_to "view my profile", @user %></span> <span><b>Microposts:</b> <%= @user.microposts.count %></span> </section> <section class="stats"> <%= render 'shared/stats' %> </section> </aside> <div class="col-md-8"> <h3><%= @title %></h3> <% if @user.likes.any? %> <ol class="microposts"> <%= render @microposts %> </ol> <%= will_paginate @microposts %> <% end %> </div> </div> likeボタンの作成 yarnを用いてFontAwesomeをインストールする。 $ yarn add @fortawesome/fontawesome-free 以下の記述を追加する。 app/javascript/packs/application.js . . . import '@fortawesome/fontawesome-free/js/all'; app/assets/stylesheets/custom.scss $fa-font-path: '@fortawesome/fontawesome-free/webfonts'; @import '@fortawesome/fontawesome-free/scss/fontawesome'; @import '@fortawesome/fontawesome-free/scss/solid'; @import '@fortawesome/fontawesome-free/scss/regular'; @import '@fortawesome/fontawesome-free/scss/brands'; @import '@fortawesome/fontawesome-free/scss/v4-shims'; . . . ルーティングを追加する。 config/routes.rb Rails.application.routes.draw do . . . resources :favorites, only: [:create, :destroy] end マイクロポストパーシャルにrenderを追加する。 app/views/microposts/_micropost.html.erb <li id="micropost-<%= micropost.id %>"> . . . </span> <span class="like" id="like_form_<%= micropost.id %>"> <% if micropost.liked_by.include?(current_user) %> <%= render "microposts/unlike", micropost: micropost %> <% else %> <%= render "microposts/like", micropost: micropost %> <% end %> </span> </li> likeパーシャル、unkikeパーシャルを追加する。 app/viws/microposts/_like.html.erb <span class="timestamp"><%=micropost.liked_by.count%>&nbsp;like</span> <%= form_for(current_user.favorites.build, remote: true, class:"btnlike") do |f| %> <div><%= hidden_field_tag :micropost_id, micropost.id %></div> <%= button_tag(class: "btn-like" ) do %> <i class="far fa-heart heart-empty "></i> <% end %> <% end %> app/viws/microposts/_unlike.html.erb <span class="timestamp"><%=micropost.liked_by.count%>&nbsp;like</span> <%= form_for(current_user.favorites.find_by(micropost_id: micropost.id), html: { method: :delete }, remote: true) do |f| %> <%= button_tag( class: "btn-like") do %> <i class="fas fa-heart heart"></i> <% end %> <% end %> cssを追加する。 app/assets/stylesheets/custom.scss . . . .heart { color: rgb(255, 74, 74); font-size: 25px; animation: anime 1s; } @keyframes anime{ 15% { transform: scale(1.3); } 20% { transform: scale(1); } } .heart-empty { font-size: 25px; -webkit-text-stroke: 5px white } .btn-like:hover > .heart-empty { color: rgb(168, 168, 168); } .btn-like { position: relative; left: 60px; } .btn-like { border: none; background-color: rgb(255, 255, 255); :hover { background-color: rgb(255, 255, 255); } } Favoriteコントローラーを作成し、以下を記述する。 $ rails g controller Favorites app/controllers/favorites_controller.rb class FavoritesController < ApplicationController before_action :logged_in_user def create micropost = Micropost.find(params[:micropost_id]) current_user.like(micropost) redirect_back(fallback_location: root_url) end def destroy micropost = Favorite.find(params[:id]).micropost current_user.unlike(micropost) redirect_back(fallback_location: root_url) end end Ajaxによる非同期化 like_html.erbとunlike_html.erbにremote:trueを追加する。 app/views/microposts/_like.html.erb <%= form_for(current_user.favorites.build, remote: true) do |f| %> . . . app/views/microposts/_unlike.html.erb <%= form_for(current_user.favorites.find_by(micropost_id: micropost.id), html: { method: :delete }, remote: true) do |f| %> . . . Favoriteコントローラーを変更する。 app/contorollers/favorites_contoroller.rb class FavoritesController < ApplicationController before_action :logged_in_user def create @user = current_user @micropost = Micropost.find(params[:micropost_id]) current_user.like(@micropost) respond_to do |format| format.html { redirect_back(fallback_location: root_url) } format.js end end def destroy @user = current_user @micropost = Favorite.find(params[:id]).micropost current_user.unlike(@micropost) respond_to do |format| format.html { redirect_back(fallback_location: root_url) } format.js end end end JS-ERbファイルを作成する。 app/views/favorites/create.js.erb $("#likes").html('<%= @user.likes.count %>'); $("#like_form_<%= @micropost.id %>").html("<%= escape_javascript(render('microposts/unlike', micropost: @micropost)) %>"); app/views/favorites/destroy.js.erb $("#likes").html('<%= @user.likes.count %>'); $("#like_form_<%= @micropost.id %>").html("<%= escape_javascript(render('microposts/like', micropost: @micropost)) %>");
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Railsチュートリアル】いいね機能の実装

はじめに 前回の記事改【Railsチュートリアル】プロフィール画像をアプリ内で設定できるように変更に引き続きRailsチュートリアル第6版sample_appの機能拡張を進めていく。 今回は以下の様ないいね機能を実装していく。 前提 第6版sample_appが完成している Favoriteモデル Favoriteテーブルを追加 $ rails g model Favorite user_id:integer micropost_id:integer user_idとmicropost_idにインデックスを追加し、組み合わせがユニークであるという複合キーインデックスも追加する。 db/migrate/[timestamp]_create_favorites.rb class CreateFavorites < ActiveRecord::Migration[6.1] def change create_table :favorites do |t| t.integer :user_id t.integer :micropost_id t.timestamps end add_index :favorites, :user_id add_index :favorites, :micropost_id add_index :favorites, [:user_id, :micropost_id], unique: true end end $ rails db:migrate ユーザーとマイクロポストに、Favoriteに対して1対多の関連づけを追加し、またhas_many throughを用いてuser.likesとmicropost.liked_byを使えるようにする。 app/models/user.rb class User < ApplicationRecord . . . has_many :favorites, dependent: :destroy has_many :likes, through: :favorites, source: :micropost . . . end app/models/micropost.rb class Micropost < ApplicationRecord . . . has_many :favorites, dependent: :destroy has_many :liked_by, through: :favorites, source: :user . . . end app/models/favorite.rb class Favorite < ApplicationRecord belongs_to :user belongs_to :micropost validates :user_id, presence: true validates :micropost_id, presence: true end ユーザーモデルにメソッドを追加する。 app/models/user.rb class User < ApplicationRecord . . . # マイクロポストをライクする def like(micropost) likes << micropost end # マイクロポストをライク解除する def unlike(micropost) favorites.find_by(micropost_id: micropost.id).destroy end # 現在のユーザーがライクしていたらtrueを返す def likes?(micropost) likes.include?(micropost) end private . . . end ルーティングを追加する。 config/routes.rb Rails.application.routes.draw do . . . resources :users do member do get :following, :followers , :likes end end . . . end likeページの作成 ステータスページにlike数を追加。 app/views/shared/_status.html.erb <% @user ||= current_user %> . . . <a href="<%= likes_user_path(@user) %>"> <strong id="likes" class="stat"> <%= @user.likes.count %> </strong> likes </a> </div> ユーザーコントローラーにlikeアクションを追加。 app/controllers/users_controller.rb class UsersController < ApplicationController . . . def likes @title = "Likes" @user = User.find(params[:id]) @microposts = @user.likes.paginate(page: params[:page]) render 'show_like' end private . . . end ビューを作成する。 gravatarの部分はこちらの記事でimage_tagに変更している。 app/viwes/users/show_like.html.erb <% provide(:title, @user.name) %> <div class="row"> <aside class="col-md-4"> <section class="user_info"> <% if @user.avatar? %> <%= image_tag @user.avatar.url, width: "100px", height: "100px", class:"icon"%> <% else%> <%= image_tag "default_user.jpeg", width: "100px", height: "100px", class:"icon"%> <% end %> <h1><%= @user.name %></h1> <span><%= link_to "view my profile", @user %></span> <span><b>Microposts:</b> <%= @user.microposts.count %></span> </section> <section class="stats"> <%= render 'shared/stats' %> </section> </aside> <div class="col-md-8"> <h3><%= @title %></h3> <% if @user.likes.any? %> <ol class="microposts"> <%= render @microposts %> </ol> <%= will_paginate @microposts %> <% end %> </div> </div> likeボタンの作成 ルーティングを追加する。 config/routes.rb Rails.application.routes.draw do . . . resources :favorites, only: [:create, :destroy] end マイクロポストパーシャルにrenderを追加する。 app/views/microposts/_micropost.html.erb <li id="micropost-<%= micropost.id %>"> . . . </span> <span class="like" id="like_form_<%= micropost.id %>"> <% if micropost.liked_by.include?(current_user) %> <%= render "microposts/unlike", micropost: micropost %> <% else %> <%= render "microposts/like", micropost: micropost %> <% end %> </span> </li> likeパーシャル、unkikeパーシャルを追加する。 app/viws/microposts/_like.html.erb <%= form_for(current_user.favorites.build) do |f| %> <div><%= hidden_field_tag :micropost_id, micropost.id %></div> <%= button_tag(class: "btn btn-default" ) do %> <%= content_tag :span, micropost.liked_by.count, class: "glyphicon glyphicon-heart-empty" %> <% end %> <% end %> app/viws/microposts/_unlike.html.erb <%= form_for(current_user.favorites.find_by(micropost_id: micropost.id), html: { method: :delete }) do |f| %> <%= button_tag( class: "btn btn-default") do %> <%= content_tag :span, micropost.liked_by.count, class: "glyphicon glyphicon-heart" %> <% end %> <% end %> cssを追加する。 app/assets/stylesheets/custom.scss . . . /* likes */ .glyphicon-heart { color: red; } .btn-default:hover > .glyphicon-heart-empty { color: red; } .btn-default { position: relative; left: 60px; } Favoriteコントローラーを作成し、以下を記述する。 $ rails g controller Favorites app/controllers/favorites_controller.rb class FavoritesController < ApplicationController before_action :logged_in_user def create micropost = Micropost.find(params[:micropost_id]) current_user.like(micropost) redirect_back(fallback_location: root_url) end def destroy micropost = Favorite.find(params[:id]).micropost current_user.unlike(micropost) redirect_back(fallback_location: root_url) end end Ajaxによる非同期化 like_html.erbとunlike_html.erbにremote:trueを追加する。 app/views/microposts/_like.html.erb <%= form_for(current_user.favorites.build, remote: true) do |f| %> . . . app/views/microposts/_unlike.html.erb <%= form_for(current_user.favorites.find_by(micropost_id: micropost.id), html: { method: :delete }, remote: true) do |f| %> . . . Favoriteコントローラーを変更する。 app/contorollers/favorites_contoroller.rb class FavoritesController < ApplicationController before_action :logged_in_user def create @user = current_user @micropost = Micropost.find(params[:micropost_id]) current_user.like(@micropost) respond_to do |format| format.html { redirect_back(fallback_location: root_url) } format.js end end def destroy @user = current_user @micropost = Favorite.find(params[:id]).micropost current_user.unlike(@micropost) respond_to do |format| format.html { redirect_back(fallback_location: root_url) } format.js end end end JS-ERbファイルを作成する。 app/views/favorites/create.js.erb $("#likes").html('<%= @user.likes.count %>'); $("#like_form_<%= @micropost.id %>").html("<%= escape_javascript(render('microposts/unlike', micropost: @micropost)) %>"); app/views/favorites/destroy.js.erb $("#likes").html('<%= @user.likes.count %>'); $("#like_form_<%= @micropost.id %>").html("<%= escape_javascript(render('microposts/like', micropost: @micropost)) %>");
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails 6.0 + Docker + MySQL5x + devise-token-auth での環境構築

この記事の概要 RailsのAPIモードで認証周り作ったときに苦労したので、備忘録メモとして…。 成果物 GitHub: try-rails6-api-with-devise 各種バージョン Ruby 2.7 Rails 6.0.0 mysql 5.7.21 前提条件 Dockerを使える環境が整っていること できること Rails 6.0 + Docker + MySQL5x + devise-token-auth での環境構築 devise-token-authを使った、サインアップ、サインイン、サインアウトができる ユーザがサインインしていることを確認し、サインインしていたらuser情報を取得する できないこと(やらないこと) コピペで環境構築できるように作った記事なので、各項目の詳しい説明は割愛 環境構築手順 1. try-rails6-api のテンプレートを使用し、リポジトリを作成する リポジトリ名は try-rails6-api-with-devise とする 必要に応じて、 try-rails6-api と記載している箇所を自分で作成したリポジトリ名に変更する(当記事であれば try-rails6-api-with-devise に変更) 2. try-rails6-apiのREADME.md に沿って環境構築する 3. 必要なGemを追加する Gemfile Gemfile ・ ・ ・ # 認証 gem "devise" gem "devise_token_auth" # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible # ※ 疎通確認をPostmanでする場合、必要となる場合があるので追加しておく gem 'rack-cors' 4. ビルド&追加したGemをインストールする docker-compose build --no-cache docker-compose run back bundle exec rails g devise:install docker-compose run back bundle exec rails g devise_token_auth:install User auth 5. devise_token_auth の設定 config/initializers/devise_token_auth.rb config/initializers/devise_token_auth.rb # frozen_string_literal: true DeviseTokenAuth.setup do |config| # By default the authorization headers will change after each request. The # client is responsible for keeping track of the changing tokens. Change # this to false to prevent the Authorization header from changing after # each request. config.change_headers_on_each_request = false # By default, users will need to re-authenticate after 2 weeks. This setting # determines how long tokens will remain valid after they are issued. # config.token_lifespan = 2.weeks # Limiting the token_cost to just 4 in testing will increase the performance of # your test suite dramatically. The possible cost value is within range from 4 # to 31. It is recommended to not use a value more than 10 in other environments. config.token_cost = Rails.env.test? ? 4 : 10 # Sets the max number of concurrent devices per user, which is 10 by default. # After this limit is reached, the oldest tokens will be removed. # config.max_number_of_devices = 10 # Sometimes it's necessary to make several requests to the API at the same # time. In this case, each request in the batch will need to share the same # auth token. This setting determines how far apart the requests can be while # still using the same auth token. # config.batch_request_buffer_throttle = 5.seconds # This route will be the prefix for all oauth2 redirect callbacks. For # example, using the default '/omniauth', the github oauth2 provider will # redirect successful authentications to '/omniauth/github/callback' # config.omniauth_prefix = "/omniauth" # By default sending current password is not needed for the password update. # Uncomment to enforce current_password param to be checked before all # attribute updates. Set it to :password if you want it to be checked only if # password is updated. # config.check_current_password_before_update = :attributes # By default we will use callbacks for single omniauth. # It depends on fields like email, provider and uid. # config.default_callbacks = true # Makes it possible to change the headers names config.headers_names = {:'access-token' => 'access-token', :'client' => 'client', :'expiry' => 'expiry', :'uid' => 'uid', :'token-type' => 'token-type' } # By default, only Bearer Token authentication is implemented out of the box. # If, however, you wish to integrate with legacy Devise authentication, you can # do so by enabling this flag. NOTE: This feature is highly experimental! # config.enable_standard_devise_support = false # By default DeviseTokenAuth will not send confirmation email, even when including # devise confirmable module. If you want to use devise confirmable module and # send email, set it to true. (This is a setting for compatibility) # config.send_confirmation_email = true end 6. rack-cors の設定 rack-cors がインストールされていることを確認する docker-compose run --rm back bundle info rack-cors 設定ファイル作成 touch config/initializers/core.rb config/initializers/core.rb config/initializers/core.rb Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins "localhost:3000" # フロント側のポート番号を指定 resource "*", headers: :any, expose: ["access-token", "expiry", "token-type", "uid", "client"], methods: [:get, :post, :put, :patch, :delete, :options, :head] end end 7. Modelの設定 app/models/user.rb app/models/user.rb # frozen_string_literal: true class User < ActiveRecord::Base # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :rememberable, :validatable include DeviseTokenAuth::Concerns::User end 8. Controllerの設定 (01) Registrations Controller コントローラ作成 docker-compose run back rails g controller v1/registrations --no-assets --no-helper app/controllers/v1/registrations_controller.rb app/controllers/v1/registrations_controller.rb module V1 class RegistrationsController < DeviseTokenAuth::RegistrationsController private def sign_up_params params.permit(:email, :password, :password_confirmation, :name) end end end (02) Users Controller コントローラ作成 docker-compose run back rails g controller v1/users --no-assets --no-helper app/controllers/v1/users_controller.rb app/controllers/v1/users_controller.rb module V1 class UsersController < ApplicationController # Sign inしてないと以下のMethodは実行できない before_action :authenticate_v1_user! # 全件検索 def index user = User.all if user render json: { user: user}, status: :ok else render user end end end end (03) Application Controller app/controllers/application_controller.rb app/controllers/application_controller.rb class ApplicationController < ActionController::API include DeviseTokenAuth::Concerns::SetUserByToken rescue_from ActiveRecord::RecordNotFound, with: :render_404 before_action :configure_permitted_parameters, if: :devise_controller? def render_404 render status: 404, json: { message: "record not found." } end def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) end end 9. Routingの設定 config/routes.rb config/routes.rb Rails.application.routes.draw do mount_devise_token_auth_for 'User', at: 'auth' namespace :v1, defaults: { format: :json } do get :healthcheck, to: 'sessions#healthcheck' mount_devise_token_auth_for 'User', at: 'auth', controllers: { registrations: 'v1/registrations', sessions: "devise_token_auth/sessions" } resources :users end end 10. マイグレーション実行 docker-compose run --rm back bundle exec rake db:migrate 疎通確認 Postmanを使用 1. コンテナ起動 docker-compose up 2. サインアップ URL [POST] http://localhost:4000/v1/auth Body: raw(JSON) {"email": "sample@test.com", "password": "xxxxxxxx", "name": "サンプル 太郎"} 3. サインイン URL [POST] http://localhost:4000/v1/auth/sign_in Body: raw(JSON) {"email": "sample@test.com", "password": "xxxxxxxx"} 4. サインアウト URL [DELETE] http://localhost:4000/v1/auth/sign_out Headers サインインで取得した、以下の項目を設定する access-token uid client expiry content-type token-type 5. ユーザ情報取得(サインインしていないと取得できない) URL [GET] http://localhost:4000/v1/users Headers サインインで取得した、以下の項目を設定する access-token uid client expiry content-type token-type
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む