- 投稿日:2019-05-23T23:18:49+09:00
Windows10 で WSL を使って Rails 環境を構築したときのメモ
はじめに
本記事の趣旨はタイトルの通り。
WSL( Windows Subsystem for Linux ) 環境で Rails 環境を構築したときのメモ。本記事を実施した環境
ツール バージョン 確認方法 Windows 10 Home 64bit Windows Subsystem for Linux Ubuntu 18.04.2 LTS (Bionic Beaver) $ cat /etc/os-release rbenv 1.1.2-2 $ rbenv -v Ruby 2.6.1p33 $ ruby -v Rails 5.2.3 $ rails -v gem 3.0.1 $ gem -v Bundler 2.0.1 $ bundler -v n 4.1.0 $ n --version Node.js 10.15.3 $ node -v npm 6.4.1 $ npm -v WSL( Windows Subsystem for Linux ) を入れよう
WIndows 10 の Professional でも Home でも WSL は入れられる。
WSL の導入は次の記事に従って作業すればスムーズに行えた。
- WSL(Windows Subsystem for Linux)を使ってみた ( 画像ありの分かりやすい記事、ありがとうございました )
WSL を入れたら
1. 環境を最新にしよう
Ubuntu のターミナルから次のコマンドを実行して環境を更新する。
sudo
はスーパーユーザでの実行権限を付与するコマンド。apt-get
は管理者権限での実行が必要なので、sudo
をつけて実行する。環境を更新する$ sudo apt-get update $ sudo apt-get upgradeRails 環境を構築しよう
注意
ご使用の環境で Kaspersky が起動していると以降の作業で通信を行う際にエラーとなって各種ツールのインストールやRailsプロジェクトの作成に失敗する。
ここでは Kaspersky を停止して作業を継続した。
1. 各種ライブラリを入れよう
rbenv を入れた あとに rbenv 経由で Ruby を入れるのだが、その際に ruby-build という rbenv のプラグインを入れる 必要がある。
で、その ruby-build のインストールにあたって色々と必要なライブラリがある。
ここでは実際に Ruby を入れる際に発生する余計なエラーを回避すべく、それらを事前に入れておく。各種ライブラリのインストール$ sudo apt-get install make $ sudo apt-get install gcc $ sudo apt-get install -y libssl-dev libreadline-dev zlib1g-dev2. Node.js を入れよう
こちらも同じく事前にエラーを回避するための手順。
Rails を実行する際に JavaScript のエンジンが必要になるのだが、 Node.js を入れておくことでこれに対応できる。(注)
これはあくまで WSL 上の Ubuntu における環境構築手順なので、Windows 上ですでに Node.js を入れていてもこの手順は実施する必要がある。インストールは次のコマンドを実行する。
Node.jsのインストール$ sudo apt-get install npmこれで Node.js そのものはインストールされたのだが
n
というツールを入れることで Node.js のバージョン管理を行うことができる。
n
のインストールは次のコマンドを実行する。nのインストール$ sudo npm install -g n $ sudo n stable(注)
手前味噌で恐縮だが、n
による Node.js のバージョン管理については 別記事 で記載しているので、ご興味あればそちらも参照されたい。
そちらの記事では LinuxMint 18 が確認環境だが、同じ Debian ベースのデストリビューションなので違和感なく進められると思う。3. rbenv を入れよう
どうせやるなら rbenv で Ruby のバージョンを管理したい。
ということで、 rbenv を GitHub からgit clone
で取ってくる。rbenvをインストール$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
rbenv がインストールできたら次のコマンドを実行して rbenv の PATH を通す。
rbenvのPATHを通す$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrcそして次のコマンドを実行して rbenv の設定を行う。
rbenvの設定を行う$ ~/.rbenv/bin/rbenv init
と打つと
実行結果# Load rbenv automatically by appending # the following to ~/.bashrc: eval "$(rbenv init -)"とでるので、
eval "$(rbenv init -)"
を.bashrc
に追記する。
まとめると、.bashrc
には次の2行が追記されることになる。追記される2行export PATH="$HOME/.rbenv/bin:$PATH" eval "$(rbenv init -)"最後にターミナルを再起動して環境変数の反映させる。
($ source ~/.bashrc
か、もしくは$ exec $SHELL -l
でも反映できる )
- 参考
4. ruby-build を入れよう
rbenv をインストールしたら次は Ruby を入れるためのプラグイン、 ruby-build を入れる。
ruby-buildをインストール$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-buildここで 先の手順 でインストールしたライブラリが効いてくる。
これらのライブラリを入れていない場合は、逐次エラーが発生してその都度ライブラリをインストールしなければならず、非常に鬱陶しい。5. Ruby を入れよう
ようやく Ruby のインストールである。
Ruby のバージョンは任意のもので良い。ここでは2.6.1
を入れてみる。
次のコマンドを実行して Ruby のバージョン 2.6.1 をインストールする。Rubyのバージョン2.6.1をインストール$ rbenv install 2.6.1 $ rbenv rehash $ rbenv globalで、Ruby のバージョンは。。。
Rubyのバージョンを確認$ ruby -v ruby 2.6.1p33と、指定したバージョン(
2.6.1
) がインストールされていることが確認できた。6. Rails を入れよう
Ruby のインストールまで終わったら、次は Rails を入れるための作業にはいる。
Rails は gem 経由でインストールする。バージョンは指定しない。Railsのインストール$ gem install rails Fetching railties-5.2.3.gem /home/hogehoge/.rbenv/rbenv.d/exec/gem-rehash/rubygems_plugin.rb:6: warning: Insecure world writable dir /home/hogehoge/.rbenv/versions in PATH, mode 040777 Successfully installed railties-5.2.3 Successfully installed rails-5.2.3 Parsing documentation for railties-5.2.3 Installing ri documentation for railties-5.2.3 Parsing documentation for rails-5.2.3 Installing ri documentation for rails-5.2.3 Done installing documentation for railties, rails after 0 seconds 2 gems installedということで、2019年05月現在、
5.2.3
のバージョンがインストールされた。
既存の Rails プロジェクトにあわせたバージョンを指定したい場合は次のように指定してやれば良い。
( ここでは5.2.0
を指定した )Railsのインストール(バージョン指定)$ gem install rails --version="5.2.0"7. sqlite を入れよう
Rails を使うにあたり SQLite3 のインストールが必要になる。SQLite そのものは gem 経由でインストールするのだが、ここでも依存ライブラリを先に入れておかなければならない。
まずは依存ライブラリのインストールから。
SQLite3の依存ライブラリのインストール$ sudo apt-get install libsqlite3-dev次に
SQLIte3
のインストール。SQLite3のインストール$ gem install sqlite3 -v 1.3.138. bundler を入れよう
Rails では一旦プロジェクトを作ると、そのプロジェクトで扱っているライブラリは Gemfile で管理され、それらは bundler でインストールすることになる。
ということで、 bundler をインストールしておく。bundlerのインストール$ gem install bundlerRails プロジェクトを作ろう
1. Rails プロジェクトを作ろう
ここまでで Ruby のインストールと Rails のインストール、およびそれらを使う際に必要な最低限のライブラリのインストールが完了した。
実際に Rails プロジェクトを作って起動してみる。プロジェクトの作成は次のコマンドで行う。
Railsのプロジェクト作成$ rails new sample-app
2. Rails プロジェクトを起動しよう
これで雛形ができたので、プロジェクト直下に移動してアプリケーションを起動する。
Railsアプリの起動$ cd sample-app/ $ rails s => Booting Puma => Rails 5.2.3 application starting in development => Run `rails server -h` for more startup options Puma starting in single mode... * Version 3.12.1 (ruby 2.6.1-p33), codename: Llamas in Pajamas * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://localhost:3000 Use Ctrl-C to stopあとはブラウザから http://localhost:3000 にアクセスして、次のページが見れれば環境構築は完了。
Windows のフォルダにシンボリックリンクを貼って Rails プロジェクトを Windows から編集しよう
上記までで Ubuntu on WSL の環境に Rails を導入できたが、このままだと Windows 環境から Rails プロジェクトの編集ができない。
Ubuntu から Windows のフォルダは
/mnt/c/
から参照できるので、Rails のプロジェクトを Windows 側のフォルダに作成してそこを Ubuntu 側で参照しに行っても良いが、毎回/mnt/c
から参照しにくのは流石に面倒臭い。ということで、シンボリックリンクである。
ここでやることの目的は
- Ubuntu から Windows への参照の手間を減らすこと
で、やることは以下の2つ。
- あらかじめ Windows のユーザホームフォルダ直下に
Rails
フォルダを作成しておく- Ubuntu のユーザホームディレクトリから
Rails
フォルダに対してシンボリックリンクを貼る以下の作業で
lns -s
を実行し、Rails
をフォルダにシンボリックリンクを貼る。シンボリックリンクを貼る$ pwd /home/hoge # Ubuntu 上のホームディレクトリ $ ln -s /mnt/c/Users/hoge/Rails # シンボリックリンクを貼る
ls -l
を実行すると、シンボリックリンクを確認$ ls -l total 0 lrwxrwxrwx 1 hoge hoge 27 May 22 23:15 Rails -> /mnt/c/Users/hoge/Rails上記のとおり、Windows のフォルダに対してシンボリックリンクが貼れている。
あとはシンボリックリンクを貼ったフォルダに対して
- 既存の Rails プロジェクトをここに移動させる
- ここで Rails プロジェクトを新たに作成する
等を行うことで、Windows から Rails プロジェクトを編集することができる。
これで
- Rails アプリの管理は Ubuntu on WSL
- Rails アプリの編集は Windows
という構成ができた。
所感
気分によって今日は Mac、今日は Windows という感じで作業ができると嬉しいと思い、Windows での Rails 環境構築を実施してみた。
とりあえずこれで Windows で Rails の開発ができるようになったはずなので、これから遊んでみようと思う。参考
- 投稿日:2019-05-23T22:32:13+09:00
credentials.yml.encでシークレットキーを管理
はじめに
Rails5.2から
secrets.yml
が廃止され、credentials.yml.enc
に統合されたことをメンターの方に教えて頂いたため、API Keyなどのシークレットキーをcredentials.yml.enc
にまとめた。
恥ずかしい話、今まではENV["hogehoge.key"]
と書いてシークレットキーを~/.bash_profile
にまとめていた。
もちろん、アプリごとにシークレットキーを管理したほうが良い(当たり前だが)ので、今回行ったcredentials.yml.enc
の設定に関する一連の流れを備忘録として残しておく。編集方法
credentials.yml.enc
を開いてみると、config/credentials.yml.encmsb4Uzo8vfnzbP65VQ58Hmu4o5WzNDTVqv9EFRnR5.....
このように暗号化されて直接編集することはできない。
credential.yml.enc
を編集するにはbin/rails credentials:edit
を実行する。
エディタを指定する必要があるので、今回はコマンドでEDITOR="vi" bin/rails credentials:edit
と入力。初期値は以下の通り。
Terminal# aws: # access_key_id: 123 # secret_access_key: 345 # Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies. secret_key_base: o8vfnzbP65VQ58Hmu4o5WzNDTVqv9EFRnR5.....AWS等各種サービスで発行されたシークレットキーをここに入力する。
変更が完了すると、再びcredential.yml.enc
が暗号化されキーの値が変わる。読み取り方法
各種シークレットキーをアプリ内で読み取る場合、
Rails.application.credentials.aws[:access_key_id
]のように入力する。(以下コード参照)
尚、初期値はコメントアウトされているため、読み取る際には外しておくこと。Terminalaws: access_key_id: 65VQ58Hmu4o5WzNDT... #=> Rails.application.credentials.aws[:access_key_id] secret_access_key: DTVqv9EFRnR... #=> Rails.application.credentials.aws[:secret_access_key] secret_key_base: 8be8e637d755f79c799048bed8be0c... #=> Rails.application.credentials.secret_key_base本番環境(Heroku)でのシークレットキーの読み取り
暗号化されている
credential.yml.enc
を読み取る際にはmaster.key
が必要となる。
しかし、master.key
はRails5.2において.gitignore
に標準指定されているため、そのままでは本番環境でcredential.yml.enc
を読み取ることはできない。
よってHerokuで読み取る際にはheroku config:set RAILS_MASTER_KEY=マスターキーの値
をコマンドで入力しマスターキーの値を指定する。config/environments/production.rbconfig.require_master_key = true上記のように設定することで、本番環境におけるマスターキーが指定されていない場合にエラー表示を出すことができる。
基本的に
credential.yml.enc
の用途は「本番環境での秘匿情報の管理」だが、各環境で別々に秘匿情報を管理するためのrails-env-credentialsというgemもあるらしい。参考
Railsガイド セキュリティ10.1-独自のcredential
Rails5.2から追加された credentials.yml.enc のキホン
- 投稿日:2019-05-23T21:27:18+09:00
【Rails】コピペで使えるdevise備忘録
はじめに
deviseでユーザーログイン機能を追加するにあたって、普段よく使っているものの備忘録です。
rootをログイン画面に設定
deviseのcontrollerを作成し、
routes.rb
で以下のように設定。$ rails g devise:controllers usersroutes.rbRails.application.routes.draw do # rootをログイン画面に設定 devise_scope :user do root "users/sessions#new" end devise_for :users, :controllers => { sessions: 'users/sessions' }ログイン後のpathを指定
application_controller.rb
で以下を記載。application_controller.rbclass ApplicationController < ActionController::Base def after_sign_in_path_for(resource) tasks_path endこのようにログイン後最初のページを条件分岐させることも可能です↓
application_controller.rbclass ApplicationController < ActionController::Base def after_sign_in_path_for(resource) if admin_user? users_path else tasks_path end endストロングパラメーターのpermit
deviseではサインアップ時にemailとpassword系のみを受け取るようにストロングパラメーターが設けられているので、それ以外の
:name
などを許可したい場合↓application_controller.rbclass ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? . . . private def configure_permitted_parameters added_attrs = [ :name, :email, :password, :password_confirmation, ] devise_parameter_sanitizer.permit :sign_up, keys: added_attrs devise_parameter_sanitizer.permit :account_update, keys: added_attrs devise_parameter_sanitizer.permit :sign_in, keys: added_attrs endおわり
他にも備忘録しておきたい事ありそうなので、思い出し次第追加したいです。
- 投稿日:2019-05-23T20:27:52+09:00
1日1問解いてSQLをマスター!SQLの学習サービス Qdash を作った話
目次
- はじめに
- なぜ作ろうと思ったか
- 使ってる技術
- 同じようなサービスを作りたい人のために実装を紹介
- 1日に1回、指定の時間に問題を切り替えて表示する
- 質問箱風なOGP画像を生成
- これから
- 最後に
はじめに
Qdash という1日1問形式の SQL 学習サービスを作りました。
問題画面
回答画面
なぜ作ろうと思ったか
とあるデータを見たいけど、いつも SQL を書ける人にお願いしている。
勉強はしたいが、中々勉強する時間が取れない。と思ってるディレクター、営業、マーケターの方!!
でも1日の中でも隙間時間はありますよね?その隙間時間に問題を解き、SQL は任せて!と自信を持って言えるようになりませんか?
というのがサービスのコンセプトです。使っている技術
・ Ruby
・ Rails
・ ServiceWorker / Webpush
・ HerokuRails / Heroku で手早く作りました。
push 通知をするために ServiceWorker と Webpush にも挑戦しました。 (この記事では触れません)実装紹介
似たようなサービスを作りたい人のために実装をいくつか紹介します!
1日に1回、指定の時間に問題を切り替えて表示する
SQL を学びたい人にとって負担にならないように1日1問という仕様にしました。
あなたならどのように実装しますか?今回は Cookie と Heroku scheduler を使って実装してみました。
class HomeController < ApplicationController def index @question = today_question delete_cookie_if_question_changed @answer = Answer.find_by(id: answer_id) end private # flesh set by scheduler.rake def today_question today_question = TodayQuestion.last || TodayQuestion.create_randomly today_question.question end def delete_cookie_if_question_changed answer = @question.answers.find_by(id: answer_id) cookies.delete('answer_id') if answer.nil? end def answer_id cookies['answer_id'] end end回答をした際に cookie をセットします。
class AnswersController < ApplicationController def create answer = Answers::Factory.build(answer_choice_params) if answer.save cookies['answer_id'] = answer.id redirect_to root_path else redirect_to root_path, notice: '回答に失敗しました。' end end private def answer_choice_params params.permit(:answer_choice_id) end endHeroku scheduler で1日1回、今日の問題をDBに登録しています。
時間と実行するコマンドはアドオンを入れた後に Heroku の管理画面から設定することができます。# sheduler.rake task set_question_randomly: :environment do TodayQuestion.create_randomly end昨日と同じ問題が出たらテンションが下がるのでそれは避けるようにしています。
class TodayQuestion < ApplicationRecord belongs_to :question def self.create_randomly question = nil loop do last_question = TodayQuestion.last.question question = Question.pick_randomly break if last_question.id != question.id end create(question: question) end end質問箱風なOGP画像を生成
続いて、質問箱風な OGP の生成処理です。
問題の作成時に問題のタイトルを画像に書き込み、画像を S3 にアップロードします。 (active_storage を利用)そして、シェアした時に作成した問題文が書かれたOGP画像が表示されるようにします。
# Gemfile gem 'mini_magic'class OgpImageGenerator def initialize(question: question) @question = question end def generate image = load_base_image image.combine_options do |c| c.gravity 'West' c.pointsize 30 c.draw "text 55,0 '#{title}'" c.size "70x" c.fill '#000' c.font Rails.root.join('public', 'hiraginokakugoW6.ttc').to_s c.interline_spacing 10 c.kerning 4 end image end private def title ApplicationController.helpers .sanitize(@question.title) .chars.each_slice(15) .map(&:join) .join("\n") end def load_base_image MiniMagick::Image.read(Rails.root.join('public', 'images', 'ogp_base.png')) end endclass Question < ApplicationRecord .. before_save :generate_ogp_image before_update :generate_ogp_image has_one_attached :ogp_image def generate_ogp_image return unless self.will_save_change_to_title? ogp_image_path = OgpImageGenerator.new(question: self).generate.path file = File.open(ogp_image_path) self.ogp_image.attach( io: file, filename: "question_ogp_image_#{id}_#{SecureRandom.urlsafe_base64}.png", content_type: "image/png" ) file.close end end問題を作成すると、このような OGP 画像が自動で生成されます。
これから
ログイン機能とコース機能を作って問題を解けるようにしたいと思っています。
ログインしていなくても問題を解くことができる一方で、熱量の高い人はログインしてまとまった時間で勉強できたら良いですね。実は一番大変なのは機能の実装より SQL の問題を作ることだったりしますw
最後に
詳細な使い方については note に書いているので見ていただけたら幸いです。
https://note.mu/usabdelah/n/n0b7f8fd30ed5Qdash で学んだことを活かして実務で SQL を書き、
データの可視化をやっていく人が増えたらいいなと思っています。ぜひ、Qdash で SQL の問題を解いてみてください。
- 投稿日:2019-05-23T19:41:12+09:00
rails hands on
rails で Web アプリを作ってみよう!
Web アプリを作って、動かして、触って、デプロイしてみよう!
事前準備
docker
,bundler
はインストールしておいてねdocker
- 公式
- Mac の人は
bundler
- 公式
- Mac の人は
他
docker-compose.yml
Dockerfile
dockerをローカルにコピー
TODO: curl でダウンロードできるようにするやってみよう!
$ mkdir rails_sample && cd rails_sample $ cp -a ~/Download/Dockerfile ~/Download/docker-compose.yml ~/Download/docker . remove `Gemfile.lock` in Dockerfile $ bundle init $ docker-compose run --rm web bundle exec rails new . -d mysql --skip-testここで今日のゴールを
https://rails-sample-fot-lt.herokuapp.com/users/sign_in
(今日はログインやらんけど)ログインあり&デプロイありの、ハンズオンやりたいと思う人!
希望あれば日程調整しましょう
3時間ぐらい
うまくいけば30分edit database.yml
pool: <%= ENV.fetch('RAILS_MAX_THREADS') { 5 } %> username: <%= ENV.fetch('MYSQL_USERNAME') { 'root' } %> password: <%= ENV.fetch('MYSQL_PASSWORD') { 'password' } %> host: <%= ENV.fetch('MYSQL_HOST') { '127.0.0.1' } %> port: <%= ENV.fetch('MYSQL_PORT') { 3306 } %>add
Gemfile.lock
in Dockerfile$ docker-compose up $ docker-compose exec web bin/rails g scaffold post content $ docker-compose exec web bin/rails db:migratehands on メモ
$ mkcd rails_sample $ cp -a ~/Download/Dockerfile ~/Download/docker-compose.yml ~/Download/docker .remove
Gemfile.lock
in Dockerfile$ bundle init $ docker-compose run --rm web bundle exec rails new . -d mysql --skip-test create remote repository $ cp -a ~/Download/Gemfile .edit database.yml
database.ymlpool: <%= ENV.fetch('RAILS_MAX_THREADS') { 5 } %> username: <%= ENV.fetch('MYSQL_USERNAME') { 'root' } %> password: <%= ENV.fetch('MYSQL_PASSWORD') { 'password' } %> host: <%= ENV.fetch('MYSQL_HOST') { '127.0.0.1' } %> port: <%= ENV.fetch('MYSQL_PORT') { 3306 } %>add
Gemfile.lock
in Dockerfile$ docker-compose up $ docker-compose exec web bundle install $ docker-compose exec web rails generate simple_form:install $ docker-compose exec web rails haml:erb2haml $ docker-compose exec web rails g annotate:install $ docker-compose exec web bin/rails g scaffold post content $ docker-compose exec web bin/rails g scaffold user name $ docker-compose exec web bin/rails db:migrate $ docker-compose exec web bundle exec rails generate devise:installadd
%p.notice= notice %p.alert= alertin app/views/layouts/application.html.haml
$ docker-compose exec web bundle exec rails g devise:views $ docker-compose exec web rails generate devise user $ docker-compose exec web bin/rails db:migrateadd
before_action :authenticate_user!
in app/controllers/posts_controller.rb and app/controllers/users_controller.rbadd
root to: 'post#show'
route.rbaccess http://localhost:3000/users
heroku deploy
create app in gui
$ heroku login $ heroku git:remote -a rails-sample-fot-lt $ git push heroku master $ heroku addons:create cleardb:ignite $ heroku config | grep CLEARDB_DATABASE_URL mysql://[username]:[password]@[hostname]/[db_name]?reconnect=true $ heroku config:add DB_NAME="[db_name]" $ heroku config:add DB_USERNAME="[username]" $ heroku config:add DB_PASSWORD="[password]" $ heroku config:add DB_HOSTNAME="[hostname]" $ heroku config:add DB_PORT="3306" $ heroku run rake db:migrate
コピー用
DockerfileFROM ruby:2.6.2 RUN apt-get update --fix-missing \ && apt-get -y upgrade \ && apt-get install -qq -y \ nodejs \ mysql-client \ && apt-get autoremove -y \ && apt-get clean all \ && fc-cache -f -v # Add dumb init to process system events RUN wget https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 -O /usr/local/bin/dumb-init RUN chmod +x /usr/local/bin/dumb-init RUN gem update --system RUN gem install bundler WORKDIR /rails_sample COPY Gemfile Gemfile.lock ./ RUN bundle install --jobs=4 --retry=3 COPY . . EXPOSE 3000 # Start the main process. CMD bin/rails server -b 0.0.0.0docker-compose.ymlversion: '3.7' services: db: restart: always image: mysql:latest environment: MYSQL_ROOT_PASSWORD: password ports: - 3306:3306 volumes: - ./docker/mysql/conf:/etc/mysql/conf.d:rw - dbdata:/var/lib/mysql web: build: . depends_on: - db volumes: - .:/rails_sample - "bundle:/usr/local/bundle" environment: - MYSQL_HOST=db command: > bash -c " bundle install --quiet && docker/bin/start rails" ports: - 3000:3000 volumes: bundle: dbdata:docker/mysql/conf/default_authentication.cnf[mysqld] default_authentication_plugin=mysql_native_passworddocker/bin/rails#!/bin/sh docker-compose run --rm backend bin/rails "$@"docker/bin/start#!/bin/sh if [ $# = 0 ]; then echo "usage:" echo " start rails: Start rails server" echo " start rails recreate db: Start rails server recreate db" echo " start sidekiq: Start sidekiq process" echo " start sidekiq-web: Start sidekiq web server" exit 1 fi case "$1" in "rails") bundle exec rails tmp:pids:clear bundle exec rails log:clear tmp:clear bundle exec rails server --port 3000 --binding "0.0.0.0" ;; "rails recreate db") bundle exec rails tmp:pids:clear bundle exec rails db:reset bundle exec rails db:migrate bundle exec rails log:clear tmp:clear bundle exec rails server --port 3000 --binding "0.0.0.0" ;; "rails migrate db") bundle exec rails db:migrate ;; "sidekiq") bundle exec sidekiq ;; "sidekiq-web") bundle exec rackup --host "0.0.0.0" --port 9292 lib/sidekiq_web/config.ru ;; esac
- 投稿日:2019-05-23T19:08:46+09:00
Ruby最新版の挙動をRSpec+Guardで試した時の環境構築メモ
はじめに
Rubyのバージョンが上がったときなどにサクッと挙動を確かめられるよう書いた自分用のメモです
(ちなみにbrewやRubyをインストールする時間を除けば3分で構築できました)今回利用したツールの各バージョン
- macOS 10.13.6
- brew 2.1.3
- rbenv 1.1.2
最新Rubyインストール
インストールできるRubyのバージョンリストを最新にする
brew update && brew upgrade ruby-buildインストール可能な一覧を見てバージョンを決める
rbenv install -l... 2.7.0-dev ...指定したバージョンのインストール
rbenv install 2.7.0-dev
作業場所用意
ここで「sample」という作業ディレクトリを作り
以下の作業はこの中で行いますmkdir ~/sample cd ~/sampleインストールしたバージョンに切り替える
rbenv local 2.7.0-dev ruby -v #=> ruby 2.7.0dev (2019-05-22 trunk ca435ed04a) [x86_64-darwin17]RSpec + Guardインストール
まずはbundlerインストール
gem install bundler bundler -v #=> Bundler version 2.1.0.pre.1Gemfile新規作成
bundle init # Gemfileが生成される
Gemfileに必要なgem追記
Gemfile# 以下追記 gem "rspec" gem "guard" gem "guard-rspec"gemインストール
.bundle/
にインストールすることにしますbundle config set path .bundle # ちなみに --path .bundleは非推奨になるらしい bundle install今回は以下のバージョンがインストールされました
- rspec (3.8.0)
- guard (2.15.0)
- guard-rspec (4.7.3)
RSpec準備
bundle exec rspec --initGuard準備
bundle exec guard init
テストコード作成
> spec/my_spec.rb
spec/my_spec.rbrequire 'spec_helper' RSpec.describe 'MySample' do describe 'methodメソッド' do subject { 123.method(:to_s) } it { expect(subject.class).to eq(Method) } it { expect(subject.call).to eq('123') } it { expect(subject.()).to eq('123') } end describe 'メソッド参照演算子' do subject { 123.:to_s } it { expect(subject.class).to eq(Method) } end endGuard起動
bundle exec guard
とりあえずenter押せば全テストケースを実行してくれます。
あとはlib/my_spec.rbを保存するたびにテストコードが走るはずです。
- 投稿日:2019-05-23T18:50:02+09:00
【Sass】導入と使い方
はじめに
ポートフォリオを作るにあたりcssを書こうと思ったのですが、
sassというものがあると知ったので導入しました。
途中、エラーが出たところもまとめます。sassとは何か
sassの導入
私はmacを使っているのでRubyの導入では何もしてません。
sassインストール
Sassを使ってCSSを爆速コーディング!Sassの導入方法と使いかた。に書いてある通り、
下記コマンドを実行するが$ gem install sass ERROR: While executing gem ... (Gem::FilePermissionError) You don't have write permissions for the /Library/Ruby/Gems/2.3.0 directory.エラー...
gem installでpermissionエラーになった時の対応方法
こちらの記事の現状確認と同じコマンドを実行すると、全く同じ結果が返ってきました。なので私もrbenvというやつを入れます。(rubyのバージョン管理をしてくれるものなのかな..)
記事の通り、最新版のrubyをインストールしたので、私の場合は2.6.3です。$ rbenv install 2.6.3 $ rbenv versions * system (set by /Users/hoge/.rbenv/version) 2.6.3この後からは先ほどの記事とは違うことを行いました!
記事では、rbenvでインストールしたrubyのバージョンをglobalにしていますが、
他のアプリに影響を与えたくないので今回はlocalで利用します。$ cd ver2.6.3のrubyを使いたい作業ディレクトリ $ rbenv local 2.6.3 $ rbenv versions system (set by /Users/hoge/.rbenv/version) * 2.6.3その後パスを通します。
~/.bash_profileにeval "$(rbenv init -)"
を追記します。パスを更新したいので、
$ source ~/.bash_profile $ ruby -v ruby 2.6.3できました!
今回はglobalでなくlocalにしているので、
rbenv local 2.6.3
コマンドを実行したディレクトリ下でのみこのバージョンが適応されます。今度こそSassインストール
$ gem install sassできた...
使い方
Sassを使ってCSSを爆速コーディング!Sassの導入方法と使いかた。
こちらの記事の実際に使ってみるを参考にしました!
私はscssにしました。参考にしたサイト(ありがとうございます><)
これからはcssはSassで書こう。
Sassを使ってCSSを爆速コーディング!Sassの導入方法と使いかた。
gem installでpermissionエラーになった時の対応方法
rbenvでバージョンがうまく切り替わらなかった時にやったこと使ってみて
cssで書くよりもきれいに書けるのと、みやすいのでこれからもガンガン使っていきたいです!
参考になるサイトがたくさんあって助かりました。ありがとうございます。ポートフォリオサイトを少しだけ更新しました。
FontAwsomやtwitterタイムラインを載せたので、手順やメモをまた投稿しようと思います。
- 投稿日:2019-05-23T17:30:09+09:00
【自分用】railsでhello, world!するまでの備忘録
Railsインストールからhello, world!出力までのもくじ
- rbenvを使ってRubyとRuby on Railsをインストール ※前提として、Command line tools をターミナルからインストール済
xcode-select --install
- コードを編集するのに必要なテキストエディタをインストール
- hello, world!を出力するだけの単純アプリの作成
1.rbenvを使ってRubyとRuby on Railsをインストール
1-1.Homebrewをインストール
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"1-2.rbenvをインストール
まずはrbenvをインストール
brew update brew install rbenv
rbenvのインストールが完了したら、rbenvにパスを通します
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile1-3.rbenvを使ってRubyをインストール
下記コマンドでrbenvでインストール可能なRubyのバージョンを確認
rbenv install -l実際にコマンド打つとこんな感じ↓
※実際にはもっと表示されます現在の安定版を確認するならwww.ruby-lang.orgにアクセスすると良いです。
※スクショは2019年5月23日時点での安定板なので最新の安定板は↑のリンクに実際にアクセスして確認してください。現在の安定板の確認をしたらrbenvを使ってRubyをインストール
rbenv install 2.6.3
1-4.デフォルトのRubyを設定
rbenv global 2.6.31-5.Railsのインストール
gem install rails
2.コードを編集するのに必要なテキストエディタのインストール
Atomエディタ使ってる人多い印象なのでAtom.ioからダウンロード。
3.hello, world!を出力するだけの単純アプリの作成
3-1.プロジェクトで使うディレクトリ
environment
を作成今回のプロジェクトで使うディレクトリ
environment
を作成し、environmentディレクトリに移動。mkdir environment cd environment3-2.移動先のディレクトリ
environment
でアプリケーションの作成下記コマンドの_5.1.6_のところではrailsのバージョンを明示的に指定)。
rails _5.1.6_ new hello_app``` Traceback (most recent call last): 2: from /Users/masaki-sakamoto/.rbenv/versions/2.6.3/bin/rails:23:in `<main>' 1: from /Users/masaki-sakamoto/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems.rb:302:in `activate_bin_path' /Users/masaki-sakamoto/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems.rb:283:in `find_spec_for_exe': can't find gem railties (= 5.1.6) with executable rails (Gem::GemNotFoundException)コマンド実行したらGemNotFoundExceptionというエラーが発生しましたが、下記コマンドを実行したら解消され無事
hello_app
の作成完了。gem install rails -v 5.1.63-3.rails sコマンドでhello, world!を出力
作成したhello_appのディレクトリに移動し、
rails s
コマンドを実行。rails sアプリケーションを表示するには、ローカルサーバーの場合http://localhost:3000/をブラウザで開きます。
※Ctrl+Cを押すとサーバーを終了できる
実際に開くとこんな感じ↓
スクショ
用語まとめ
後日追記予定
参照リンク
- 投稿日:2019-05-23T16:08:05+09:00
【初心者向け】実務未経験がプルリクエスト時レビュアーに指摘されたこと-コミット・RSpec編-
はじめに
実務未経験の自分がエンジニアスクールでレビューを頂いた時に、
おそらく現場でも指摘されるであろう項目をまとめていきます。前回は、コード・文法編をまとめました。
【初心者向け】独学では気づきにくい!実務未経験がプルリクエスト時レビュアーに指摘されたこと-コードお作法編-まとめきれていない部分もありますので、随時追記していきます。
特に、独学でRails等を学んでいる方の参考になれば幸いです。1. コミットでの注意
わかりやすく、綺麗なコードを書くことは心がけているに、雑なコミットで残してませんか?
私が独学で勉強していた頃は、正直疎かにしてました。
しかし、プルリクエストでレビューしてもらう際やチーム開発では、理解しやすいコミットを残す必要があります。
特にコレが正解!というのはありませんが、指摘されたことを踏まえてまとめていきます。1-1. 1つのコミットで複数の機能を追加するのは避けよう。(意図を理解しづらくなる)
一気に複数の機能を実装して、1つのコミットにまとめると見る側が意図を理解しづらくなります。
$ git commit -m "ログイン機能、ユーザー編集機慧能、画像投稿機能およびRspecテストを追加"のようにしてしまうと、
メッセージ的にもコードを確認するにしても分かりづらい状況になります。
コミットをどのように分けるかは、常に意識する必要があります。1-2. 理解しやすいコミットメッセージ
コミットメッセージには、端的に理解しやすいメッセージで残す必要があります。
- どういう目的で
- 何を
- どうしたのか(追加・修正・更新・削除など)
をコミットメッセージに残せると見る側も意図を理解しやすそうです。
とはいえ、チーム・プロジェクトによりルールがあると思われますので注意が必要。
個人的には以下のURLで紹介されていた書き方が分かりやすいかなと感じました。参考URL: 誰にとってもわかりやすいGitのコミットメッセージを考える
1-3. 不要なファイルは除外or削除しよう
自動生成されるけど不要なファイルは事前に必要かどうかを考えましょう。
そして、本番環境で不要な.env
(環境変数)などのファイルは、事前に.gitignore
に記述して除外しておきましょう。
不要なファイルがコミットされれば、自分・レビュアー共に見づらいプルリクエストになってしまう。2. RSpecの準備編<導入後>
Gemfilegroup :development, :test do gem 'rspec-rails' gem 'factory_bot_rails' endで、
bundle install
後に準備すると良いものをまとめます。
基本設定などは、[Qiita] Ruby on Rails のテストフレームワーク RSpec 事始めなどがオススメです。2-1. 結果を見やすくする
通常何も設定せずにRSpecテストをすると
... Finished in xx seconds 3 examples, 0 failures
テストに失敗していないことは分かりますが、詳細が分かりにくい状態に。
そんな時は、
.rspec
にformat documentation
を入れて結果を見やすくすると良い。
※個人的にもレビューをして頂いている方にも見やすいテスト結果になります。.rspec--require spec_helper --format documentation例えば、このように出力されます。
Sample::HomeController Home Controller indexの機能テスト sample/に正常にアクセスできる Sample::ProductsController Prodcut Controller showの機能テスト products/showに正常にアクセスできる @productが取得できている Finished in xx seconds 3 examples, 0 failures
2-2. FactoryBotを設定しておく
RSpecでFactoryBotを使う場面があると思います。
何も設定をしない状態では、let!(:product) { FactoryBot.create(:product) }FactoryBotを毎回書く必要があります。
これでは、作業効率的にあまり良くないので、rails_helper.rb
定義しておくと良いです。spec/rails_helper.rbRSpec.configure do |config| config.include FactoryBot::Syntax::Methods end見た目もすっきりして、呼び出せるようになりました。
let!(:product) { create(:product) }詳しい設定方法などは、こちらの記事がオススメです。
参考URL: RailsアプリへのRspecとFactory_botの導入手順3. RSpecのお作法編
RSpecを書いていく上で指摘されたお作法についてまとめています。
3-1. テストの文言を考える
機能単体テスト(feature test)で考えれば、
- featureは「どのような機能」
- scenarioは「ユーザーから見たサービスの挙動」
ということを踏まえて文言を考える。
例)feature '商品の詳細ページを見ることが出来る' do scenario '詳細ページにアクセス時、商品名や価格などの情報が表示される' do end scenario "関連商品をクリック時、商品詳細ページへ移動する" do end end適当な文言設定をすると分かりにくいテストになり、確認する側も意図を理解するのに時間がかかります。
参考URL:
使えるRSpec入門・その4「どんなブラウザ操作も自由自在!逆引きCapybara大辞典」
使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」3-2. 検査するDOM(HTML)の範囲を絞る
within
を使うことで、対象範囲を指定することができます。
これにより正確に意図したテストを実行することができます。
例は以下になります。# id="add_to_cart"で探せるようにする <div id="add_to_cart" class="btn-area"> <%= link_to cart_page_path do %> <div class="btn btn-primary btn-block"> カートへ入れる <i class="fa fa-angle-right" aria-hidden="true"></i> </div> <% end %> </div>scenario "カートを入れるをクリック時、買い物カゴページへ移動する" do # id="add_to_cart"の範囲を指定したテストをする within "#add_to_cart" do click_on "カートへ入れる" end #現在のページがカートページであることを確認 expect(page).to have_current_path cart_page_path end参考URL:
Capybaraチートシート#スコープを切る3-3. RSpecを設置するディレクトリを考える
分かりやすいディレクトリ構成にすると良いでしょう。
例えば、
app/controllers/products_controller.rb
に対応するRSpecは、
rspec/requests/products/products_controller_spec.rb
が分かりやすい。RSpecテストのファイルが多くなってくると、一目でファイルを探すのに苦労する場面も。
分かりやすいディレクトリ構成にすることで、ストレスを少しは軽減できると思います。まとめ
今回は、コミット・RSpecで注意された点をまとめました。
まだ、細かい点などもありますので、まとめ次第追記いたします。
RSpecについては、独学で学習している頃は苦手意識があり敬遠していましたが、
指摘されることで少しずつ理解が深まってきた印象です。現場等でエンジニアをやられている方で、本記事に間違い等ございましたら、
大変恐縮でありますがご指摘いただければと存じます。
よろしくお願いいたします。RSpecの勉強に使用した著書:
「Everyday Rails - RSpecによるRailsテスト入門」
- 投稿日:2019-05-23T15:04:35+09:00
Rails5でMySQLのid以外にbigint + primary key + auto increment する。(migration)
やり方
調べたところRails4の頃の情報しか見当たらず、漁ると
auto_increment オプションが搭載されたことにたどり着く。
cerate_tableでの:idに続けざまに書くことで対応可能となるらしい。
以下は、PKをcompany_idにした会社マスタのサンプルである。
/db/migrate/example.rbdef change create_table :m_company, primary_key: "company_id", id: :bigint, comment: "会社ID", auto_increment: true, default: nil, force: true, comment: '会社マスタ' do |t| ## t.bigint :company_id, null: false, comment: '会社ID' ※←ここには書かない t.string :name, null: false, comment: '会社名' t.text :detail, comment: '内容' t.datetime :created_at, null: false, comment: '作成日時' t.datetime :updated_at, null: false, comment: '更新日時' end end以下となる。
mysql> desc m_company; +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | company_id | bigint(20) | NO | PRI | NULL | auto_increment | | name | varchar(255) | NO | | NULL | | | detail | text | YES | | NULL | | | created_at | datetime | NO | | NULL | | | updated_at | datetime | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+あとから変えたい場合は、change_columnで入る
こんな感じ。rollbackできるようにupとdownで書く
/db/migrate/example.rbdef up change_column :m_company, :company_id, :primary_key, auto_increment: true end def down change_column :m_company, :company_id, :bigint execute "ALTER TABLE m_company DROP PRIMARY KEY;" end問題 コメントが入らない
create_tableでPKを作成してしまうと、テーブルのコメントはかけてもPKカラムのコメントが入らない。(comment:オプションが被るから)
ので、
/db/migrate/example2.rbdef up create_table :m_company, primary_key: "company_id", id: :bigint, auto_increment: true, default: nil, force: true, comment: '会社マスタ' do |t| t.string :name, null: false, comment: '会社名' t.text :detail, comment: '内容' t.datetime :created_at, null: false, comment: '作成日時' t.datetime :updated_at, null: false, comment: '更新日時' end change_column :m_company, :company_id, comment: "会社ID" end def down # change_column :m_company, :company_id, comment: nil ※コメントだけ追加ならばこれ drop_table :m_company endこれでコメントも追加できる”が”、schema.rbを確認するとわかるように
change_columnの内容がcreate_tableにマージされてしまっているのがわかる。ゆえに、db:setupをした場合は、PKのキーにコメントが入らないためdb:migrateをすることをお勧めする。
参考資料
- 投稿日:2019-05-23T13:23:40+09:00
Rails5でMySQLのid以外にbigint + primary key + auto increment する。(migration)
やり方
調べたところRails4の頃の情報しか見当たらず、漁ると
auto_increment オプションが搭載されたことにたどり着く。
cerate_tableでの:idに続けざまに書くことで対応可能となるらしい。
以下は、PKをcompany_idにした会社マスタのサンプルである。
/db/migrate/example.rbdef change create_table :m_company, primary_key: "company_id", id: :bigint, comment: "会社ID", auto_increment: true, default: nil, force: true, comment: '会社マスタ' do |t| ## t.bigint :company_id, null: false, comment: '会社ID' ※←ここには書かない t.string :name, null: false, comment: '会社名' t.text :detail, comment: '内容' t.datetime :created_at, null: false, comment: '作成日時' t.datetime :updated_at, null: false, comment: '更新日時' end end以下となる。
mysql> desc m_company; +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | company_id | bigint(20) | NO | PRI | NULL | auto_increment | | name | varchar(255) | NO | | NULL | | | detail | text | YES | | NULL | | | created_at | datetime | NO | | NULL | | | updated_at | datetime | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+あとから変えたい場合は、change_columnで入る
こんな感じ。rollbackできるようにupとdownで書く
/db/migrate/example.rbdef up change_column :m_company, :company_id, :primary_key, :bigint, comment: "会社ID", auto_increment: true, default: nil end def down change_column :m_company, :company_id, :integer, comment: nil, auto_increment: false end問題 コメントが入らない
create_tableでPKを作成してしまうと、テーブルのコメントはかけてもPKカラムのコメントが入らない。(comment:オプションが被るから)
ので、
/db/migrate/example2.rbdef up create_table :m_company, primary_key: "company_id", id: :bigint, auto_increment: true, default: nil, force: true, comment: '会社マスタ' do |t| t.string :name, null: false, comment: '会社名' t.text :detail, comment: '内容' t.datetime :created_at, null: false, comment: '作成日時' t.datetime :updated_at, null: false, comment: '更新日時' end change_column :m_company, :company_id, comment: "会社ID" end def down # change_column :m_company, :company_id, comment: nil ※コメントだけ追加ならばこれ drop_table :m_company endこれでコメントも追加できる”が”、schema.rbを確認するとわかるように
change_columnの内容がcreate_tableにマージされてしまっているのがわかる。ゆえに、db:setupをした場合は、PKのキーにコメントが入らないためdb:migrateをすることをお勧めする。
参考資料
- 投稿日:2019-05-23T13:11:52+09:00
実務未経験からRails開発に途中参加した際の環境構築
はじめに
実務未経験から内定をいただいた企業のrailsでの開発に途中参加することになり、環境構築を行う中で躓いた部分があったため振り返り用として記録します。
環境
- プログラミングスクールにてRuby、Railsの環境構築済み
- データベースはMySQLを使用
- GitHubアカウント登録済
- Homebrew、rbenvインストール済み
- mac OS使用
前提
- 与えられた情報はGitHubのリポジトリのみ
- ローカル環境で起動できることを目標とする
やったこと
GitHubリポジトリの共有
1.プライベートリポジトリを共有するためGitHubに登録しているアドレス又はアカウント名を伝える
2.GitHubのリポジトリへ招待され参加する
3.ローカルリポジトリの作成開発環境構築
1.Ruby、Rails等のバージョンを開発環境に合わせる
Ruby、Railsのバージョンなどは 「Gemfile」 で確認をします
Gemfileruby '2.5.0' gem 'rails', '~> 5.2.0' gem 'pg', '>= 0.18', '< 2.0' gem 'sass-rails', '~> 5.0'ここではRubyのバージョンを合わせます
自分のPCにインストールしているバージョンを確認$ rbenv install --list Available versions: 1.8.5-p52 1.8.5-p113 :下記コマンドで変更したいバージョンを指定
インストールしていた場合$ rbenv local 2.6.0インストールしていない場合
$ rbenv install 2.6.0バージョンも合わせ、いざ Gemをインストール
$ bundle installそしたらこんなエラーが…
何やらpgがインストールされてないとか?An error occurred while installing pg (1.1.3), and Bundler cannot continue. Make sure that `gem install pg -v '1.1.3' --source 'https://rubygems.org/'` succeeds before bundling.pgってなんだというところから検索し…データベースがPostgreSQLであることがは判明!!
こちらを参考にインストールターミナルでコマンドを打ち
$ sudo gem install pg -v '1.1.4' --source 'https://rubygems.org/'またしてもエラー…
エラー内容は忘れましたがこちらを参考にし解決(恐らく同じエラーでした)$ brew install postgresql2.PostgreSQLも無事インストールできたので再度Gemをインストール
$ bundle install3.データベース作成
$ bundle exec rake db:create4.マイグレーションファイルの実行
$ bundle exec rake db:migrate5.PostgreSQLを起動
$ postgres -D /usr/local/var/postgres6.サーバーを起動
$ rails sこれで無事にローカル環境構築完了!!
※手順としては前後している可能性がありこれが正しいとは限りませんのでご了承ください
おわりに
プログラミング初心者として検索していく中で、同じような状況の人の手助けになればと思い記事にしました。
やり方としてはエラーに遭遇しながら手探り状態で調べて進めたため進め方おかしいぞとなるかもしれません。参考
https://qiita.com/nasutaro211/items/d69a5e0b883293537b7e#_reference-a0cf0f3d167d682de2dc
https://qiita.com/youcune/items/5b783f7fde45d0fd4b35
https://qiita.com/yh2020/items/8be3087004d100fe752b
- 投稿日:2019-05-23T10:59:47+09:00
Rails Tutorial(2週目)-4-
4章はチェリー本に書いてあることがほとんどだったので、また別でまとめようと思います。
アクセサーの作成
attr_accessorは内部的に次のような処理を行っています。
(1)引数のシンボルすべてに対して以下の処理を繰り返す。
(2)シンボルで指定された名前のメソッドを定義する。そのメソッドはシンボルの名前の先頭に「@」を付加したインスタンス変数の値を取り出す。
(3)シンボルで指定されたメソッド名の後ろに「=」を付加した名前のメソッドを定義する。そのメソッドは引数を1つ取り,その値をシンボルの名前の先頭に「@」を付加したインスタンス変数に設定する
attr_accessor によってクラス外からも、インスタンス変数を読み込んだり、変更したり操作できるようになる。
ユーザー名とメールアドレス (属性: attribute) に対応するアクセサー (accessor) をそれぞれ作成します。アクセサーを作成すると、そのデータを取り出すメソッド (getter) と、データに代入するメソッド (setter) をそれぞれ定義してくれます。具体的には、この行を実行したことにより、インスタンス変数@nameとインスタンス変数@emailにアクセスするためのメソッドが用意されます。
- 投稿日:2019-05-23T10:56:50+09:00
【Ruby + AWS】Amazon EC2インスタンスでLINE Bot Server構築してみた
はじめに
こんにちは。ここ最近ですが、仕事でLINE Botを作ることになりましたので、必要な設定を共有できればと思います。
なお、この記事ではあくまで概念とLINE Bot Serverを構築するまでの準備のレベルを書こうと思うので、あえてBot Server部分のコードは省略します(というか、書き始めたばかりなので新規に埋め込んだコードがほとんどない)。追記
よくよく考えたら、概念図のポンチ絵、左部分おかしいですね、、、
LINEのネイティブ・WebアプリケーションがあってそこにユーザとBotがいるので、本来は入れ子にするべきでしたね。後日、修正します。LINE Botの概念図
手書きのポンチ絵なのて、字が下手な部分はご愛嬌...
なお、このポンチ絵は以下の3つの資料を参考に書きました。https://developers.line.biz/ja/docs/messaging-api/overview/
https://developers.line.biz/ja/docs/messaging-api/getting-started/
https://developers.line.biz/ja/docs/messaging-api/building-bot/当初、弊社のWebアプリケーション用のサーバとは別にLINE PFがアクセスするエンドポイント用のサーバを用意する必要があったので、スクリプト言語で書く必要もないかなと考えGoでやろうかと言っていましたが、それほど大規模なアクセスを想定していないこと、既存のアプリケーションと一旦統合するような設計を採る事にしたため、RubyでBot Serverを作る事にしました。
環境の確認
- OS: Amazon Linux AMI release 2018.03
- Nginx: 1.14.1
- Ruby: 2.4.6
Route 53でコールバック用に使うレコード名を登録 || セキュリティグループの設定
上記のLINE PF(プラットフォーム)がコールバック用のエンドポイントとなるURLにアクセスできるようにレコード名を登録してあげます。また、グローバルにアクセスできるようにSecurity Groupの設定も行って下さい。
EC2インスタンス上でLINE Bot Serverを設定
Bot Server検証用の環境を構築しようとした矢先に気づいたのですが、LINE Botではコールバック用のURLは
HTTP over SSL
しか対応していない事が発覚し、検証環境でもSSL証明書を導入する必要が出てきました。そのため、EC2インスタンス単体で証明書をインポートする機構が必要だったため、今回はLet's Encryptで導入する形を採りました。SSL証明書の導入(Let's Encrypt)
基本的には、下記の部分のコマンドの引用です。
https://certbot.eff.org/lets-encrypt/centosrhel6-nginx
- certbot-autoの導入
% wget https://dl.eff.org/certbot-auto % sudo mv certbot-auto /usr/local/bin/certbot-auto % sudo chown root /usr/local/bin/certbot-auto % sudo chmod 0755 /usr/local/bin/certbot-auto
- 証明書の発行
% sudo /usr/local/bin/certbot-auto --nginx certonly --debug
- NGINXをリバースプロキシとして設定し、SSL証明書をインポート
server { listen 80; server_name ***.***.***; location / { root /var/www/html; index index.html index.htm; } } server { listen 443; ssl on; server_name ***.***.***; ssl_certificate /etc/letsencrypt/live/***.***.***/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/***.***.***/privkey.pem; location / { proxy_set_header X-Real-IP $remote_addr; proxy_pass http://127.0.0.1:3000; } }% sudo service nginx restart
RubyによるBot Serverの構築
LINEリポジトリから公式に提供されているhttps://github.com/line/line-bot-sdk-rubyというRuby用のBot Kitをインストールします。
なお、Bot Kitは、他にも多くの言語をサポートしている模様ですので、基本的なLINE Botの作り方は採用する言語に合わせてBot Kitを用意すればOKです。echo botによる動作確認
各Bot Kitリポジトリのexamplesディレクトリ配下にサンプルコードが用意されています。今回は、echobotでユーザメッセージをそのまま鸚鵡返しするBot Serverを採用し、動作確認を行います。
https://github.com/line/line-bot-sdk-ruby/tree/master/examples/echobot
echo Botによる動作確認が取れました。
まとめ
これまた、設定部分の所しかかけていませんが、これからどんどんコードを書いていこうと思います。
因みに、line-bot-sdkの事を、Bot Kitって言っているのは、プラモデルを作るのと同じように、「部品が用意されていて、それを組み合わせて静的なモデルを完成させる」感覚になっているので、ライブラリというよりツールキット(Bot用だからBot Kit)という言い方しています。
まぁ、そんな与太話はどうでもいいと思うので、中身を詳細に書き次第、改めて記事を書いていきます。
それではまた。参考文献
- 投稿日:2019-05-23T10:19:48+09:00
Rails hidden_fieldの渡し方、受けとり方
渡し方
値を指定する場合はvalueを使う。
第一引数にオブジェクト名、第二引数部分にvalueで受け渡す値を指定する。text.html.erb<%= f.hidden_field :unique_key, :value => params[:unique_key] %>受け取り方
valueで渡した値をモデルのインスタンスの属性に格納している場合、以下のようになる。
text_controller.rb@introduce = Follow.find_by(unique_key: params[:follow][:unique_key])Followモデルのunique_keyカラムの値を受け取る場合。
参考
Ruby on Rails - hidden_fieldの使い方
https://qiita.com/azusanakano/items/5849a7ca74be58d195b7
f.hidden_fieldとhidden_field_tagの使い方【Ruby on Rails】
https://sakurawi.hateblo.jp/entry/hidden_field
- 投稿日:2019-05-23T09:07:25+09:00
Railsアプリケーションをデプロイ&ロールバックするCapistranoコマンド
環境
$ cat /etc/system-release Amazon Linux AMI release 2018.03 # プロジェクトのディレクトリ内にて $ vim Gemfile.lock capistrano (3.11.0) unicorn (5.5.0) $ rbenv versions * 2.6.2 (set by /usr/local/rbenv/version) $ bin/rails -v Rails 5.2.3はじめに
開発環境やステージング環境などデプロイ先によって、設定ファイル名はそれぞれ
staging.rb
やdevelopment.rb
になると思います。
今回はproduction.rb
という本番環境の設定ファイルを使用して、デプロイ・ロールバックするという前提で話を進めます。production.rbserver 'localhost', user: 'banri', roles: %w{ app web db } set :rails_env, :production set :unicorn_rack_env, "#{fetch(:rails_env)}" set :deploy_to, '/var/www/hogehoge(アプリケーション名)/production' set :repo_url, 'git@github.com:banri/hogehoge.git' set :branch, :masterデプロイ?
デプロイの疎通確認?
$ bundle exec cap production deploy:check以下のような結果になれば、デプロイ疎通OKです。
$ bundle exec cap production deploy:check 00:00 git:wrapper 01 mkdir -p /tmp ✔ 01 banri@localhost 0.751s Uploading /tmp/git-ssh-Hogehoge-local-banri.sh 100.0% 02 chmod 700 /tmp/git-ssh-Hogehoge-local-banri.sh ✔ 02 banri@localhost 0.754s 00:02 git:check 01 git ls-remote git@github.com:banri/hogehoge.git HEAD 01 Warning: Permanently added 'github.com,XX.XX.XXX.XX' (RSA) to the list of known hosts. 01 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx HEAD ✔ 01 banri@localhost 2.833s 00:05 deploy:check:directories 01 mkdir -p /var/www/hogehoge/production/shared /var/www/hogehoge/production/releases ✔ 01 banri@localhost 0.706s 00:05 deploy:check:linked_dirs 01 mkdir -p /var/www/hogehoge/production/shared/log /var/www/hogehoge/production/shared/tmp/pids /var/www/hogehoge/production/shared/tmp/cache /var/www/hogehoge/production/shared/tmp/sockets /var/www/hoge… ✔ 01 banri@localhost 0.745s 00:06 deploy:check:make_linked_dirs 01 mkdir -p /var/www/hogehoge/production/shared/config ✔ 01 banri@localhost 0.760sCapistranoのデプロイはSSHを使用します。接続ができずデプロイの疎通に失敗した場合は、以下のようなエラーを吐きます。
cap aborted! SSHKit::Runner::ExecuteError: Exception while executing as banri@localhost: Authentication failed for user banri@localhost Caused by: Net::SSH::AuthenticationFailed: Authentication failed for user banri@localhostSSHのセットアップなどに関しては、Connecting to GitHub with SSHを参考にしてください。
デプロイの実行???
$ bundle exec cap production deploy:checkCapistranoの公式ドキュメントによると、上記コマンド1発で以下のコマンドが順番に実行されているそうです。
$ bundle exec cap production deploy:starting - デプロイスタート+全てのデプロイ準備ができているかの確認 $ bundle exec cap production deploy:started - custom tasksへのデプロイフックの作成開始 $ bundle exec cap production deploy:updating - 新リリースに伴うサーバーのアップデート → ここではcurrentディレクトリに同期されていない状態 $ bundle exec cap production deploy:updated - デプロイフックのアップデート $ bundle exec cap production deploy:publishing - 新リリースの公開 $ bundle exec cap production deploy:published - デプロイフックの公開 $ bundle exec cap production deploy:finishing - デプロイ完了 $ bundle exec cap production deploy:finished - デプロイフック作成完了
deploy:updating
のコマンド入力後、/releases
以下を確認するとアプリケーションのバージョンが変わっていないことが分かります。
変わっていない場合は、本日の日付が入ったソースコードのディレクトリが存在しません。$ cd /var/www/hogehoge/production/releases $ ls -tl total 20 drwxrwxr-x 16 banri banri 4096 Mar 15 05:57 20190315033559 - 最終更新のファイル名が本日の日付になっていないことを確認 drwxrwxr-x 15 banri banri 4096 Jan 12 03:58 20190112061458 drwxrwxr-x 14 banri banri 4096 Aug 3 2018 20180803054816 drwxrwxr-x 15 banri banri 4096 Jul 4 2018 20180704091354 drwxrwxr-x 14 banri banri 4096 Jul 4 2018 20180704082634ロールバック?
1つ前のリリース状態へロールバック?
$ bundle exec cap production deploy:rollbackロールバックも同様に、上記コマンド1発で以下のコマンドが順番に実行されているそうです。
$ bundle exec cap production deploy:starting $ bundle exec cap production deploy:started $ bundle exec cap production deploy:reverting - 旧リリースへサーバーの巻き戻し $ bundle exec cap production deploy:reverted - デプロイフックの巻き戻し $ bundle exec cap production deploy:publishing $ bundle exec cap production deploy:published $ bundle exec cap production deploy:finishing_rollback - ロールバック完了 $ bundle exec cap production deploy:finished特定のリリース状態にロールバック???
ROLLBACK_RELEASE=
の後に、リリースのディレクトリ名を指定するだけです。$ bundle exec cap production deploy:rollback ROLLBACK_RELEASE=リリースのディレクトリ名(日付) 例えば以下のような感じです。 $ bundle exec cap production deploy:rollback ROLLBACK_RELEASE=20190112061458参考
- 投稿日:2019-05-23T08:09:40+09:00
Rails6 のちょい足しな新機能を試す22(filter_attributes 編)
はじめに
Rails 6 に追加されそうな新機能を試す第22段。 今回のちょい足し機能は、
filter_attributes
(filter_attributes=
メソッド)編です。
Rails 6.0 では、 filter_attributes で指定された model の attribute は[FILTERED]
と表示されるようになります。Ruby 2.6.3, Rails 6.0.0.rc1 で確認しました。Rails 6.0.0.rc1 は
gem install rails --prerelease
でインストールできます。$ rails --version Rails 6.0.0.rc1Rails プロジェクトを作る
$ rails new rails6_0_0rc1 $ cd rails6_0_0rc1User model を作ります
$ bin/rails g model User name sensitive $ bin/rails db:create db:migrateconfig/initializers/filter_parameter_logging.rb を編集する
sensitive を
[FILTERED]
にするためにfilter_parameter_logging.rb
を編集します。config/initializers/filter_parameter_logging.rbRails.application.config.filter_parameters += [:password, :sensitive]irb で確認する
irb で User モデルを作成して、確認すると、 sensitive の値が
[FILTERED]
となっていることがわかります。bash-4.4# bin/rails c Running via Spring preloader in process 50 Loading development environment (Rails 6.0.0.rc1) irb(main):001:0> user = User.new(name: 'rails', sensitive: 'sensitive') => #<User id: nil, name: "rails", sensitive: [FILTERED], created_at: nil, updated_at: nil>
pp
を実行した場合も[FILTERED]
で表示されます。irb(main):002:0> pp user #<User:0x0000556be6e41c48 id: nil, name: "rails", sensitive: [FILTERED], created_at: nil, updated_at: nil> => #<User id: nil, name: "rails", sensitive: [FILTERED], created_at: nil, updated_at: nil>User model を編集する
filter_parameter_logging.rb
から:sensitive
を削除して、user.rb
でfilter_attributes=
メソッドを使います。config/initializers/filter_parameter_logging.rbRails.application.config.filter_parameters += [:password]app/models/user.rbclass User < ApplicationRecord self.filter_attributes += [:sensitive] end再度 irb で確認する
irb で User モデルを作成して、確認すると、 sensitive の値が
[FILTERED]
となっていることがわかります。bash-4.4# bin/rails c Running via Spring preloader in process 50 Loading development environment (Rails 6.0.0.rc1) irb(main):001:0> user = User.new(name: 'rails', sensitive: 'sensitive') => #<User id: nil, name: "rails", sensitive: [FILTERED], created_at: nil, updated_at: nil>
pp
を実行した場合も[FILTERED]
で表示されます。irb(main):002:0> pp user #<User:0x0000556be6e41c48 id: nil, name: "rails", sensitive: [FILTERED], created_at: nil, updated_at: nil> => #<User id: nil, name: "rails", sensitive: [FILTERED], created_at: nil, updated_at: nil>filter_parameters で指定した場合と model の filter_attributes で指定した場合の違い
Rails.application.config.filter_parameters
で指定した場合は、全てのモデルでその attribute が[FILTERED]
で表示されます。(Rails.application.config.filter_attributes
で設定されているものが、filter_attributes
に反映されます。)
filter_attributes
で指定した場合は、指定した model の属性だけが[FILTERED]
になります。基本的には、
Rails.application.config.filter_parameters
で指定した方が漏れがなくて良いと思います。試したソース
試したソースは以下にあります。
https://github.com/suketa/rails6_0_0rc1/tree/try022_filter_parameters追記
正規表現による attribute の指定も可能になってます(
/sens/
を指定するとsensitive
が[FILTERED]
になる)。参考情報
- 投稿日:2019-05-23T01:18:17+09:00
RSpecでlet(:foo)を再定義したい場合
RSpecを利用していて、
let(:foo)
なfoo
の再定義がしたくなったときに少々困ったののまとめ
let
再定義
let
の再定義はRSpecではよく行うと思います。RSpec.describe "Hoge.hoge" do subject { Hoge.hoge(foo) } let(:foo) { 100 } it { expect { subject }.not_to raise_error } context "when foo is not a number" do let(:foo) { "foo" } it { expect { subject }.to raise_error(ArgumentError) } end end
let(:foo)
で定義されているfoo
はまるで変数のように見える何かで、評価はit
の実行時に行われます。困る場合
外で定義した
foo
を利用してfoo
を再定義しようとすると困ります。RSpec.describe "Hoge.hoge" do subject { Hoge.hoge(foo) } let(:foo) { 100 } it { expect { subject }.not_to raise_error } context "when foo is negative" do let(:foo) { foo * -1 } # これ it { expect { subject }.to raise_error(ArgumentError) } end endこれをやろうとすると、
foo
が再帰的に評価されてstack level too deep.
と言われて死にます。「そんな
let
書くなよ」という話もあるのですが、こういうことをしたくなった理由はshared_examples
でした。
shared_examples
の例strings_converter_spec.rbRSpec.describe StringsConverter do let(:converter) { StringsConverter.new } let(:items) { ["rock", "paper", "scissor"] } subject { converter.run(items) } it_behaves_like "a strict-typed Converter" endintegers_converter_spec.rbRSpec.describe IntegersConverter do let(:converter) { IntegersConverter.new } let(:items) { [100, 200, 300] } subject { converter.run(items) } it_behaves_like "a strict-typed Converter" endstrict_converter_behaviour.rbRSpec.shared_examples "a strict-typed Converter" do describe "#run" do subject { converter.run(items) } it "is implemented" { expect { subject }.not_to raise_error(NotImplementedError) } context "when argument `items` include other types" do # ここでitemsを it_behaves_like 元の定義に基づいて再定義したい let(:items) { items + [nil] } it { expect { subject }.to raise_error(ArgumentError) } end end endここでは各
Converter
にわたす配列の要素の型は各specファイルで定義しつつ、共通のふるまいだけを切り出そうとしています。
処理する配列にnil
が含まれている場合にArgumentError
をraise
することを、その直前でGreenになるような配列に最低限の改変(+ [nil]
)を行った場合を作成することでテストしようとしています。が、循環参照で死にます。なぜダメなのか
context
やdescribe
はクラス定義を行っています。context
がネストされると、内側で定義されたcontextクラスは外側のものを継承します。
そしてlet()
はおおよそdefine_method()
のエイリアスです。describe "some Foo" do let(:name) { "hoge" } describe "when name is fuga" let(:name) { "fuga" } end endは
class SomeFoo define_method :name { "hoge" } class WhenNameIsFuga < SomeFoo define_method :name { "fuga" } end endっぽくなります。
つまり
let(:foo) { foo }
と書いてしまうと同じクラスの中で自分自身を最初に見つけるので、無限に再帰が起きることになります。
記述形式から期待するようなfoo = foo + 1
とは全く挙動が異なるのがポイントでしたどうすればいいのか
let
が変数定義ではなく動的なメソッドであるit_behaves_like
で最低でも一つ間にクラス生成を挟んでいて、外側を継承しているつまり
let
の中で外側のcontextのものを参照するためにはsuper
が使えるということになります。strict_converter_behaviour.rbRSpec.shared_examples "a strict-typed Converter" do describe "#run" do subject { converter.run(items) } it "is implemented" { expect { subject }.not_to raise_error(NotImplementedError) } context "when argument `items` include other types" do # super を呼んで定義済み配列GET~! let(:items) { super + [nil] } it { expect { subject }.to raise_error(ArgumentError) } end end endと思いきや、今度は
implicit argument passing of super from method defined by define_method() is not supported. Specify all arguments explicitly.などと怒られます。
define_method
内でsuper
する場合は明示的にarityを指定する必要があるので、super()
にして解決です。context "when argument `items` include other types" do # super() で引数がないことを示す let(:items) { super() + [nil] } it { expect { subject }.to raise_error(ArgumentError) } endまとめ
let
はdefine_method
describe
expect
はクラス定義describe
の内外は継承の関係内側の
define_method
から外側のdefine_method
を利用するにはsuper
を使えばいい
super
には引数明示が必要- 引数なしなら
super()
そんなコードを書かない
- 投稿日:2019-05-23T01:14:52+09:00
【Ruby】配列を操作するメソッドをまとめてみた
ary.each_slice(N) #配列を任意の要素数の配列に分割
配列から奇数、偶数番目の要素を取り出す
odd = ary.each_slice(2).map(&:first) even = ary.each_slice(2).map(&:last)https://qiita.com/ddgg7755/items/ed7db4b342b783620b41
要素の削除
delete
配列の要素を削除する。
a = [1, 2, 2, 3, 3, 3] a.delete(2) print a # [1, 3, 3, 3]delete_at
指定位置の要素を削除
a = ["a", "b", "c", "d", "e"] a.delete_at(3) print a # ["a", "b", "d", "e"]slice!
配列から指定範囲の要素を削除する
配列.slice!(削除開始位置, 削除する長さ)a = ["a", "b", "c", "d", "e"] a.slice!(1, 3) print a # ["a", "e"]要素の取り出す
firstとlast
firstは最初の要素、lastは最後の要素を配列から取り出す。
https://qiita.com/wai-doi/items/6aed16ad4bbaeb446c7farr = [0, 1, 2, 3, 4] arr.first #=> 0 arr.last #=> 4[]との違いは?
&:メソッド名
表記を使えるので、mapメソッドをシンプルに書ける。
また、レシーバがnilの場合は&.でエラーを回避できます。nil[0] #=> NoMethodError: undefined method `[]' for nil:NilClass nil.first #=> NoMethodError: undefined method `first' for nil:NilClass nil&.first #=> nil条件を満たす要素を取り出すor削除
https://mickey24.hatenablog.com/entry/20110227/ruby_array_select_reject_partition
select (select!)
ブロック内の評価がTRUEになる要素を配列で返す
a = [1, 3, 4, 7, 9, 13] a.select{|e| e % 3 == 0} #=> [3, 9]reject (reject!)
ブロックの評価結果がTRUEとなる要素を除いた配列を返す
a = [1, 3, 4, 7, 9, 13] a.reject{|e| e % 3 == 0} #=> [1, 4, 7, 13]partition
ブロック内の評価がTRUE、FALSEになる要素で分けて、配列を返す。
a = [1, 3, 4, 7, 9, 13] a.partition{|e| e % 3 == 0} #=> [[3, 9], [1, 4, 7, 13]]