- 投稿日:2020-06-23T23:47:18+09:00
update_attributes is deprecated and will be removed from rails 6.1
- 投稿日:2020-06-23T23:31:50+09:00
【Rails】 本番環境MySQLデータを開発環境に入れた後に消す方法
はじめに
本番環境にMySQLのデータを開発環境に入れる時には特にエラーもなくインプットすることができたのですが、消す時になってエラーが発生してハマってしまいました。
少し珍しいケースかもしれませんが、他の方の参考になればと思いまとめることにしました。関連リンク
そもそも本番環境のMySQLのデータをどうやって開発環境に入れるのかという記事は下記をご参照ください。
- EC2からMySQL(RDS)接続後にローカルMySQLにデータを入力する方法
エラー
開発環境でDB自体を削除するコマンドを実行したところ、、、
$ rails db:dropエラー
ActiveRecord::ProtectedEnvironmentError
が出ました。。。このエラーの意味は、
本番環境のDBを操作しようとしているが問題ないですか?
という警告のようなもので、環境変数を入れると操作を続けることができるよ。と言ってます。
そもそも開発環境なんですけど、なんで本番環境と出るんですか??
rails aborted! ActiveRecord::ProtectedEnvironmentError: You are attempting to run a destructive action against your 'production' database. If you are sure you want to continue, run the same command with the environment variable: DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bin/rails:4:in `<main>' Tasks: TOP => db:migrate:reset => db:drop => db:check_protected_environments (See full trace by running task with --trace)結論
先に結論から書いてしまいますが、
Rails5では MySQLに環境変数を格納しており、本番環境のデータをそのまま開発環境に入れたことにより、MySQLの環境変数に本番環境の変数が格納されてしまったため、上記のエラーがでてしまいました。
なので、解決する方法としては、MySQLの環境変数を本番環境のものから開発環境のものに書き換えればいいということです。
解決手順
MySQLに接続します。
$ mysql -h db -u root -p存在するデータベースを確認します。
$ show databases;対象のデータベースを指定します。
$ use *******;データベースないのテーブルの一覧を表示します。
$ show tables;テーブル一覧の中に
ar_internal_metadata
があると思います。
この中に、環境変数を格納しています。+---------------------------------------------------+ | Tables_in_scm_development | +---------------------------------------------------+ | ar_internal_metadata | | ... | +---------------------------------------------------+ar_internal_metadataの中身をみてみると、
$ select * from ar_internal_metadata;見つけました
production
の文字を。+-------------+-------------+---------------------+---------------------+ | key | value | created_at | updated_at | +-------------+-------------+---------------------+---------------------+ | environment | production | 2020-01-10 09:37:29 | 2020-01-10 09:37:29 | +-------------+-------------+---------------------+---------------------+この
production
をdevelopment
へ修正します。$ update ar_internal_metadata set value='development'もう一度、ar_internal_metadataの中身をみてみると、
$ select * from ar_internal_metadata;環境変数は
development
に変更できました。+-------------+-------------+---------------------+---------------------+ | key | value | created_at | updated_at | +-------------+-------------+---------------------+---------------------+ | environment | development | 2020-01-10 09:37:29 | 2020-01-10 09:37:29 | +-------------+-------------+---------------------+---------------------+MySQLから抜けて
$ exitもう一度、DBを削除するコマンドを実行。すると成功しました!
$ rails db:dropまとめ
つらつらと手順を書いたので、人によっては理解しづらいかもしれませんが、困っている誰かの役に立てばなーと思います。
参考
- 本番環境のデータをローカルのDBに投入したら UnknownMigrationVersionError と ProtectedEnvironmentError (Rails 5)
- 投稿日:2020-06-23T23:09:23+09:00
RailsでHerokuにデプロイしたときに一部ページだけ500エラーとなるとき
マイグレーションファイルは慎重に作成し、ミスったらやり直すくらいの覚悟じゃないとHerokuにpushして
heroku run rails db:migrate
したときに沼にハマるよという話。発生している問題
ローカル環境ではキチンと動くのに、(SQLite->Postgresへの対応などの基本的な設定を済ませてから)Herokuにデプロイするも、一部のページだけが500(Internal Server Error)となる。フロントでは「We're sorry, but something went wrong.」なので、404の「The page you were looking for doesn't exist.」とは違って内部的なエラーが発生している。
heroku logs --tail
でログを見ても以下の500エラーと書かれただけで何が原因か全然分からないかった。2020-06-23T09:27:34.223359+00:00 app[web.1]: [8ee3a40d-5258-46f4-8742-48c47f28b01f] Category Load (1.2ms) SELECT "categories".* FROM "categories" 2020-06-23T09:27:34.474847+00:00 heroku[router]: at=info method=GET path="/categories/1/show" host=my-app.herokuapp.com request_id=8ee3a40d-5258-46f4-8742-48c47f28b01f fwd="27.81.17.54" dyno=web.1 connect=1ms service=263ms status=500 bytes=1827 protocol=https
結論
汚いマイグレーションファイルを残したままpushして
heroku run rails db:migrate
していないか疑え!以下の記事の【1】と同じだった。
https://qiita.com/kaorioka09jm/items/9167ba77d1edf7addac2ローカル開発中にDB作りを試行錯誤したことが原因
Herokuにデプロイした全ページが500とかなら
heroku run rails db:migrate
してないなど他の理由もあるが、一部のページだけ表示されない場合はDBのマイグレーションが上手くいっていない場合が多いようだ。結局、ローカルのマイグレーションファイルを削除したり、作り直したりしても、一度Herokuにpushしてしまったマイグレーションファイルがあると、データベースをResetしてもDestroyしても、そこから
heroku run rails db:migrate
してもデータベースは綺麗にならない。そのため筆者の場合はHerokuからアプリを削除して再度pushし直す羽目になった。
マイグレーションファイルの注意点
- マイグレーションファイルは一度しか
rails db:migrate
できない- 生成される
schema.rb
を直接編集しちゃダメ(と思われる)- テーブルの削除なども都度マイグレーションファイルを作ってやること
そのため以下のようなマイグレーションファイルの生成は慎重に行う必要がある。もし間違ってカンマを入れたり本来integerのデータ型を間違ってtextに指定してしまったなどだけで、変なマイグレーションファイルが生成される。
// 例 rails g migration CreatePostCategoryRelations post_id:integer category_id:integer // 間にカンマを入れたり、コロンの位置が違ったり、integerの綴りが違ったりと間違えがち
それを挽回するために別のマイグレーションファイルを作って‥なんてやってローカルでDBをぐちゃぐちゃ構築しても、それをpushした後に
heroku run rails db:migrate
を実行すると過去のマイグレーションファイルを順に実行するのでおかしくなる。今回はPosticoの使用により、DBの中のあるテーブルの
category_id
カラムがStringになっていたことに気付けたので、Heroku側のDB生成が上手くいってないことに気付けた。DBがおかしいと気付くには、
rails db:migrate
した際のログをめんどうでもちゃんと読んで確認するのも役立つと思う。
- キチンと標準のテーブル+マイグレーションファイルで指定したテーブルが作成されているか?
- 各テーブルのカラムのデータ型は正しいか?
テーブルの削除
Heroku上に正しいマイグレーションファイルをpushするには、まずローカルのマイグレーションファイルを綺麗にする必要がある。しかし、間違った記述のあるマイグレーションファイルを削除し、正しいマイグレーションファイルを作成して
rails db:migrate
しても、以下のように怒られて上書きはできない。rails aborted! StandardError: An error has occurred, this and all later migrations canceled: SQLite3::SQLException: table "post_category_relations" already existsそのためテーブルの削除用のマイグレーションファイルを作成して
rails db:migrate
し、再度新たなテーブル作成用のマイグレーションファイルを作成してrails db:migrate
する必要がある。$ rails generate migration RemoveMyTable20200623XXXX_remove_my_table.rbclass RemoveMyTable < ActiveRecord::Migration[6.0] def change drop_table :my_table end endhttps://qiita.com/kanuu/items/a9223712ee0ff8d19d56
その後、テーブルの削除などに使った余分なマイグレーションファイルを削除する。こうして綺麗なマイグレーションファイルだけが残ったので、これをまっさらなHerokuにpushしてから
heroku run rails db:migrate
をしてやると綺麗なデータベースができる。考えたこと
SQLiteとPostgreSQLの互換性の問題ではないか
Herokuでは SQLite が使えないので、production環境だけ PostgreSQL を使用するのはHerokuで最初につまづくポイントだが、これの変更によって使えないメソッドがあるのではと考えた。
が、そんなことはなく、そもそもマイグレーションファイルとはSQLを書かずに、かつ言語の種類(SQLiteかPostgreSQLか等)によらずにDBを操作するためのものである。
今回はControllerの以下の
includes
やwhere
がPostgreSQLでは使えないのでは、といった馬鹿な勘違いをしてしまった‥orz.categories_controller.rbdef show @posts = Post.includes(:categories).where(post_category_relations: { category_id: @category }) end※Gemのpgloaderを使うなどの記事を見つけたが、それはMySQLのデータをPostgreSQLのデータに移行するものであって、メソッドを変換とかではない。
push後のWarningされてる部分に問題があるのではないか
pushした後に以下のWarningが出るが今回は無関係。またこれらは、どれも特別な使い方をしない限りは、初心者は無視していい警告だ。
remote: ###### WARNING: remote: You set your `config.assets.compile = true` in production. remote: You set your `config.active_storage.service` to :local in production. remote: We detected that some binary dependencies required to remote: No Procfile detected, using the default web server.マイグレーションファイルの理解を深めるのに役立ちそうな記事
そもそもマイグレーションとは何なのか?
https://qiita.com/sobameshi0901/items/f5823fec20e2dd78d9c4ロールバックという手法もあるらしい?
https://qiita.com/params_bird/items/3d503b5c9f8097df147a
- 投稿日:2020-06-23T21:53:26+09:00
Railsチュートリアル(第4版)メモ 第6章
Railsチュートリアル(第4版)の個人メモ
気になった部分、忘れそうな部分を記述。
- Ruby 2.6.1
- Rails 5.1.6
前章の最後 (5.4) でUsersコントローラを作成した。そのつづき。
6〜12章にかけて、ユーザ認証の各機能について作成していく。
6章ではこのうち、ユーザのデータモデル、保存について扱われている。※ おわび
ナレッジになりきれていないメモをQiitaに上げるのが違うような気がしてきたが、
記事として所感を上げれば、それなりに反応があり、勉強にもなったため、お目汚しにはなりますが何卒ご容赦を。
そして最近Rails書いてないのだが下書が埋まってきたので放流。6章 ユーザーのモデルを作成する
Railsでは認証を実装するための仕組みが既に整っているが、サービスごとに認証には多くのカスタムが必要になる。
このため、車輪の再発明にはなるが、方法を知っていればサードパーティ製の認証も実装しやすくなるので、Railsチュートリアルでは車輪を再発明している。6.1 Userモデル
Railsは、データモデルとして扱うデフォルトのデータ構造を
Model
(MVCのM) と呼ぶ。
このModelとのやり取りにはRailsデフォルトではActive Record
というものが使われる。
これはSQLを意識せずにCRUDや構築を行ってくれるもの。6.1.1 データベースの移行
データベースを永続化するためにUserモデルを作成。
Usersコントローラ作成時と同様、$ rails g
する。注意として、
コントローラは 複数形Users
モデルは 単数形User
とするのが慣習。
$ rails g model User name:string email:stringDBで使う属性(DBでいうカラム名)と、型を
:
を挟んで渡す。諸々生成されるが、
db/migrate/
にはタイムスタンプ_create_モデル名s.rb
というファイルができる。
ここでDB作成のための情報が定義される。db/migrate/タイムスタンプ_create_users.rbclass CreateUsers < ActiveRecord::Migration[5.0] def change create_table :users do |t| t.string :name t.string :email t.timestamps end end endidとタイムスタンプについては、特に指定なしでも自動で用意される。
クラス名の部分を見ると、ActiveRecord::Migration[5.0]
を継承しているらしい。
(Railsチュートでは5.0だが、小生の環境は5.1の表記)
timestamps
は、タイムスタンプに係る2つのカラム [created_at
,updated_at
] を作成してくれる。mysqlだとこんなかんじだろうか。
mysqlCREATE DATABASE User; USE Users; CREATE TABLE users( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(300), email VARCHAR(300), created_at TIMESTAMP NOT NULL CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP );sql書くたびに大文字or小文字 許さないおじさんが発生しそうだな、とビクビクしながら書いている(前職にもいた)。
正直、今の御時世、すべて小文字でも問題ないんだとおもっている。
ちなみに前職では日付はvarchar()で書いてうわなにをするやめろマイグレーションを適用。
友人曰く、複数人開発で特に気を遣わんと爆死するコマンドだから、と念を押された。気をつけよう。
DB側はバージョン管理されてるわけではない。$ rails db:migrate
6.1.2 modelファイル
演習
RailsコンソールでUser.new
をし、どのような継承関係に有るのか確認した。
Userクラス
<ApplicationRecord
<ActiveRecord::Base
<Object
<BaseObject
6.1.3 ユーザーオブジェクトを作成する
railsコンソールのサンドボックスオプション
を使うと、DBへの変更を終了時にすべてロールバックしてくれる。
$ rails console --sandboxこの中での実験。
モデルを生成した際にuserクラスが生成され(app/model/
)、これがActiveRecord
から継承されている。以下使ったメソッド
valid?
: 有効性(Validity)の確認
save
: 保存
保存した際、create_at
,update_at
にタイムスタンプが押される。
戻り値に、保存ができたかどうかのbool値が帰ってくる。
create
: User.new ではメモリ内に生成するだけだったが、生成と同時に保存する。演習
User.create
user.name
ActiceSupport::timeWithZone6.2 ユーザーを検証する
6.2.1 有効性を検証する
要はSQLでのカラム型指定みたいな話
Double
とかBoolean
は入らんとか。
以下4点
- 存在性 (presence)
- 長さ (length)
- フォーマット (format)
- 一意性 (uniqueness)
所感
- usersテーブルに削除フラグって要るような気がする。後で追加するのか?
- dbのmigrateファイル、いっつも書くidとかをよしなにやってくれるのもだし、varcharとかで文字数指定しなくて良いのだけでも楽。
- dbのmigrateファイル、変更が時系列で残ってくれるのがとても安心感ある。前職ではDBに変更掛けたときのSQLすら遺してなかった。
- 投稿日:2020-06-23T20:52:20+09:00
【Cookieとセッションの違い】Railsチュートリアル 8章と9章では何をしているのか
はじめに
Rails チュートリアル8章、9章では主にログイン機能の実装をしていますが、
sessionやcookieなど聞き慣れない用語がいきなり出てきたりして難しいと思います。私自身、結構混乱してしまう部分もあったので、図を用いて整理してみました。
まずCookieとセッションの違い
8章と9章の違いを理解する上で、まずCookieとセッションの違いを整理します。
Cookieとは
CookieとはWebサーバがブラウザにデータを一時的に保存し、アクセスしてきたクライアントにデータを保持させる仕組みのことです。
以下図のように、クライアントがWebサーバにアクセスすると、WebサーバがブラウザにCookieを保存します。
以降、クライアントがWebサーバにアクセスする際にはこのCookieも一緒に送ります。Cookieはブラウザを閉じても保持され、有効期限は任意に設定できます。
セッションとは
セッションとはHTTPなどステートレス(状態を保持できない)なプロトコルを使っている場合でも
ステートフル(状態を保持できる)な振る舞いを実現できるようにする方法です。例えば、本来であればHTTPでは「ユーザのログイン状態」を保持できませんが、
セッションを用いることで「ユーザのログイン状態」を保持して クライアント⇔Webサーバで通信することができます。セッションの実装には様々なやり方がありますが、Rails(のデフォルト設定)ではCookieによって実装しています。
具体的には以下図のように、セッションを維持するための情報をCookieに保存してクライアント⇔Webサーバで通信を行います。
セッションはブラウザを閉じると破棄されてしまいます。
8章では何をしているか
8章ではセッションIDを用いたログイン機能を実装しています。
以下コマンドにより、セッション情報としてユーザIDを一時的に保存しています。
session[:user_id] = user.idこれにより、以降は
①クライアントがセッション情報を含んだCookieをサーバに送る
↓
②サーバが保有しているセッション情報と照合
↓
③照合できれば既にログインしているユーザとして認識というステートフルな通信を実現できます。
ブラウザの開発ツールから、実際にセッション情報を送っているのが確認できます。
値がユーザIDそのものではなくランダムな文字数列になっているのは、railsが自動でセッション情報を暗号化してくれているからです。
また、このセッション情報は有効期限が「セッション」となっており、ブラウザを閉じると消去されてしまいます。9章では何をしているか
9章ではセッションを用いず、Cookieのみでログイン機能やその拡張機能を実装しています。
(厳密にはセッションも併用していますが、8章との違いを強調するためにこのような表現をしています。)8章とは違い、セッション情報ではなく、Cookieに「ユーザID」と「記憶トークン」を格納します。
加えて「記憶トークン」をDBに登録しておき、それを用いて永続的なステートフル通信を実現しています。「記憶トークン」をDBに登録する際は、ハッシュ関数で暗号化して「記憶トークンダイジェスト」として保存しています。
なので、
ユーザから送られてきた記憶トークンのハッシュ値
⇔DBに保存されている記憶トークンダイジェスト
を比較することでユーザ状態を確認しています。
(これはパスワード認証の時と同じです)これらのフローを図で表すと以下の通りです。
以下コマンドによってCookieに「ユーザID」と「記憶トークン」を格納しています。
cookies.permanent.signed[:user_id] = user.id cookies.permanent[:remember_token] = user.remember_token
permanent
メソッドを使うとCookieの期限が20年となります。
signed
メソッドを使うことで署名付きクッキーを使用でき、ユーザIDを暗号化できます。ブラウザの開発ツールからCookieの状態を確認することができます。
remember_tokenに「記憶トークン」が格納されています。
user_idに「ユーザID」が暗号化されて格納されています。
(どちらも有効期限が20年)もし
signed
メソッドを使わない場合、クッキー内の情報は以下の通りになります。記憶トークンはログインするたびに更新されますが、ユーザIDは頻繁に更新されるものではないので、
そのままCookieに保存しているのは何だか不安です。。。そのため
signed
メソッドによって暗号化しています。まとめ
8章と9章では同じログイン機能を実装してますが、認証情報をやり取りする方法が違いました。
8章 ⇒ セッションを用いた認証。
ブラウザを閉じると消えてしまう。9章 ⇒ Cookieを用いた認証。
ブラウザを閉じても認証情報を保持できる。
しかし、記憶トークンをDBに保存したり、署名付きCookieを使うといった対応が必要となる。以上、何かの参考になれば幸いです。
参考資料
「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
今さら聞けないセッションとCookie、ログイン・ログアウト(Rails編)
翔泳社 出版「情報処理安全確保支援士 2019年版」 上原孝之 著
- 投稿日:2020-06-23T20:47:36+09:00
【Rails】CSVエクスポート機能の実装
目標
開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina前提
下記実装済み。
実装
1.
application.rb
を編集application.rbrequire_relative 'boot' require 'rails/all' require 'csv' # 追記 Bundler.require(*Rails.groups) module Bookers2Debug class Application < Rails::Application config.load_defaults 5.2 end end2.コントローラーを編集
books_controller.rbdef index @book = Book.new @books = Book.all # 追記 respond_to do |format| format.html format.csv do |csv| send_users_csv(@books) end end end # 追記 def send_users_csv(books) csv_data = CSV.generate do |csv| header = %w(ID 登録日 投稿者 タイトル) csv << header books.each do |book| values = [book.id, book.created_at, book.user.name, book.title] csv << values end end send_data(csv_data, filename: '本一覧情報') end① CSVファイルのヘッダーを設定する。
header = %w(ID 登録日 投稿者 タイトル) csv << header② CSVファイルの内容を設定する。
books.each do |book| values = [book.id, book.created_at, book.user.name, book.title] csv << values end③ CSVファイル名を設定する。
filename: '本一覧情報'3.ビューを編集する。
books/index.html.slim/ 追記 = link_to 'CSVエクスポート', books_path(format: :csv), class: 'btn btn-success'
- 投稿日:2020-06-23T19:06:05+09:00
git pushで毎回ユーザー名とパスワードを入力を回避する方法 - SSH接続
Cloud9から
git push
するのに
毎回ユーザー名とパスワードを要求されるをなんとかしたくて調べてみた
(以下記事作成者に感謝)git パスワード を毎回聞かれる問題の解決方法 - Qiita
一度ローカル環境のターミナルで設定してみて
Cloud 9からpush
してみるも認証がうまく行かず鍵の登録はデバイスごとにする必要があります
ローカル環境で設定済みでも、
同じ手続きを再度Cloud9上で行うとSSH接続可能になりました認証鍵の仕組みは把握していましたが
鍵?という方はこちらGitHubでssh接続する手順~公開鍵・秘密鍵の生成から~ - Qiita
SSHの仕組みについては
- 投稿日:2020-06-23T18:51:41+09:00
【ERROR メッセージ表示】rails 部分テンプレートでいつでも使える 簡易版
【ゴール】
errorメッセージの表示
【メリット】
■ UX向上
■ 部分テンプレートの理解度向上【開発環境】
■ Mac OS catalina
■ Ruby on Rails (5.2.4.2)
■ Virtual Box:6.1
■ Vagrant: 2.2.7【実装】
アプリケーション作成
※touch はカレントディレクトリ内でfile作成するコマンド
mac.terminal$ rails new error_test $ cd error_test $ rails g scaffold Item name:string texte:text amount:integer $ rails db:migrate $ cd app/views/layouts $ touch _error_messages.html.erbモデル追記
※DB保存時の条件
※バリデーション = 保存時の制限 を追加models/item.rbclass Item < ApplicationRecord validates :name, presence: true validates :text, presence: true validates :amount, presence: true endビュー追記
※パーシャル化し、凡庸性UP
※「layputs/_error_messages.html.erb」に入れる事で
バリデーションを貼っていれば全てのモデルに使用可能に!!!!layputs/_error_messages.html.erb<% if model.errors.any? %> <div class="alert alert-warning"> <ul> <% model.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %>※追加する
Items/_form.html.erb<%= render 'layouts/error_messages', model: f.object %>※scaffold で作成の場合は上記は不要
各 _form のviewにて下記コード記載の為(scaffold超便利ですね)/_form.....<% if item.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(item.errors.count, "error") %> prohibited this item from being saved:</h2> <ul> <% item.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %>以上です。お好みでどうぞ!!!
【合わせて読みたい】
■エラーメッセージに関して
https://qiita.com/ryuuuuuuuuuu/items/1a1e53d062bff774d88a■hidden_field
https://qiita.com/tanaka-yu3/items/0d454c5ef80f8267f09d■アプリケーション作成
https://qiita.com/tanaka-yu3/items/3fe1ed2852c6513d3583
- 投稿日:2020-06-23T18:05:43+09:00
Rails6の自分流環境構築手順
cloud9で開発している方向けです。
ネットで調べると他にも方法が出てくるので、この方法が合わなかった場合は別の方法を参照してください。
①普遍的なRails5チュートリアルの環境構築方法
$ printf "install: --no-document \nupdate: --no-document\n" >> ~/.gemrc $ gem install rails $ rails new アプリ名しかし、これでrails sをするとエラーが出てしまいます。
②serverをubuntuサーバに変える
Amazon Linuxサーバーで開発していた人はそのプロジェクトを削除し、新しくubuntuサーバーで作り直してください。
③yarnのインストールとwebpackerのインストール
次のようにコマンドを入力します
$ npm install -g yarn $ rails webpacker:install④ちょこっとタイピング
config/environments.development.rbconfig.hosts = nilこれでrails sすればうまくいく...はず
- 投稿日:2020-06-23T17:15:38+09:00
Railsアプリに独自ドメインを与えてAWSに上げても表示されない問題
「自分のアプリを独自ドメインにしてAWSに上げたろー」
ということで以下の記事を参考に自分のアプリに独自ドメインを付与しました。
https://mel.onl/onamae-domain-aws-route-53/しかし3日待っても全く表示されない。AWSの紹介ページが表示されるだけ・・・
そこで色々調べた結果、Nginxの設定が必要であるとわかった。Nginxの設定
EC2で
[USERNAME|~]$ cd /etc/nginx/conf.d/ [USERNAME|conf.d]$ sudo vi 〇〇.conf (#自分のアプリケーション名)〇〇.confで
server_name 〇〇.com;(#アプリの独自ドメインに変更してください)保存して終了。再起動する。
[USERNAME|〇〇(アプリ名)]$ sudo nginx -s reloadこれで行けるはず!
参考文献
https://qiita.com/naoki_mochizuki/items/5a1757d222806cbe0cd1#nginx%E3%81%AE%E8%B5%B7%E5%8B%95
- 投稿日:2020-06-23T16:40:42+09:00
【RSpec devise_token_auth 】ユーザー認証トークンを渡す方法
はじめに
devise_token_authを使用してユーザー認証をrequest specに書く際に時間がかかったので、他に同じ様なエラーで詰まっている方のお役に立てれば幸いです。
前提
Ruby:2.6.5
Rails:6.0.3.1テストはRSpecを使用。
ユーザー認証にdevise_auth_token
を使用しています。失敗するspec
shops_request_spec.rbRSpec.describe "Api::V1::Shops", type: :request do describe "GET api/v1/shops" do let!(:shops) { create_list(:shop, 10) } context "認証済みのユーザーの場合" do it "一覧を表示できる" do get '/api/v1/shops' expect(response.status).to eq(200) expect(json.size).to eq(10) end end endこれだとユーザー認証ができずに401のエラーコードが出てテストがパスしません。
ユーザー認証トークンの渡し方
create_new_auth_token
でトークンを作り、get '/api/v1/shops'にheadersを追加します。
※因みにトークンの認証はuid
access-token
client
をheadersに返してユーザー認証をしています。shops_request_spec.rbRSpec.describe "Api::V1::Shops", type: :request do describe "GET api/v1/shops" do let!(:shops) { create_list(:shop, 10) } context "認証済みのユーザーの場合" do let(:auth_headers) { create(:user).create_new_auth_token } it "一覧を表示できる" do get '/api/v1/shops', headers: auth_headers expect(response.status).to eq(200) expect(json.size).to eq(10) end end endこの様にかけば、ユーザー認証が成功します!!
参考記事
2番目の記事はやり方は違いますが、同じくdevise_auth_tokenでのユーザー認証のやり方を記載した記事なので、すごく参考になると思います!!
おわりに
今年駆け出したばかりのエンジニアなので、何か間違っている点あればコメント等お願いします。
- 投稿日:2020-06-23T16:06:30+09:00
Docker+Rails+Vueの環境を迷わず作成するステップ
最近勉強したDockerを使って、railsとVueの環境構築をしてみました。
いろいろ検索してやってみたものの、多くのエラーと向き合う日々を迎えることに...(それでもだいぶ理解は深まった?)この記事では
- とにかく開発環境だけ欲しい
- 自分の忘備録
を主な対象として、最速でDokcer+Rails+Vueの環境を作成するステップをご紹介します?!
(多分エラーは出ないはず。。。)STEP1. 4つのファイルを作成しよう
まずは作業するフォルダ(ディレクトリ)に
- Dockerfile
- docker-compose.yml
- Gemfile
- Gemfile.lock
の4つのファイルを作成します。内容はそれぞれ以下のようにします!
DockerfileFROM ruby:2.5.3 RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - && apt-get update && \ apt-get install -y nodejs --no-install-recommends && rm -rf /var/lib/apt/lists/* RUN apt-get update -qq && apt-get install -y build-essential libpq-dev RUN apt-get update && apt-get install -y curl apt-transport-https wget && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && apt-get install -y yarn RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - RUN apt-get install -y nodejs npm && npm install n -g && n 10.17.0 RUN yarn add node-sass RUN mkdir /app WORKDIR /app COPY Gemfile /app/Gemfile COPY Gemfile.lock /app/Gemfile.lock RUN bundle install COPY . /appdocker-compose.ymlversion: '3' services: web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/app ports: - 3000:3000 depends_on: - db tty: true stdin_open: true db: image: mysql:5.7 volumes: - db-volume:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: password volumes: db-volume:Gemfilesource 'https://rubygems.org' gem 'rails', '5.2.3'作業しているディレクトリで
touch Gemfile.lock
を実行すると、からのGemfile.lockが作成されます。?バージョンやdbのパスワードなどはよしなにご変更ください〜。
STEP2. rails newをする
今回はdockerコンテナ上でrailsアプリを作成するので、コマンドラインにそのまま
rails new
を打つのは正しくありません。
(僕のPCはローカルにrailsを入れていないため、rails new
を打っても「そのコマンド知りませんけど?」って怒られます。)dockerコンテナ上でコマンドを実行したい場合は
docker-compose run
コマンドをつかえばOKです?。下記コマンドを実行します。
docker-compose run web rails new . --force --database=mysql --webpack=vue --skip-coffee
このコマンドにより、
- dbはMySQLを明示的に指名
- Vueを後入れしなくて済む(後入れでエラーが結構出た記憶)
- coffee使わないので、coffee関連のファイルを作成しない
という付加価値をつけた状態で、rails new しています。
?あと2ステップ!
STEP3. database.ymlを作成する
STEP2の読み込みが完了したら、config/database.ymlが作成されているはず。
このファイル内にある「default」の内容を少し書き換えます。config/databese.ymldefault: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: password ←docker-compose.ymlで指定したdbのパスワード host: db ←docker-compose.ymlのservicesで指定したdbの名前STEP4. docker-compose up --build
ここまでできたら、
docker-compose up --build
を実行します!少し時間がかかりますが、読み込みが終わったあとにローカルホストにアクセスしてみると、「Yay! You’re on Rails!」の画面が表示されましたか?
もしそうなら成功です!だがしかしBut。。。?
僕の場合は、「ERROR -- : Unknown database 'app_development' (ActiveRecord::NoDatabaseError)」が表示されました。僕と同じという方は、
docker-compose exec web rails db:create
をしてあげればOK!
docker-compose down
をした後に、再度
docker-compose up --build
をすれば立ち上がるはずだぞ!お疲れ様でした?最後に
コロナ禍でWebエンジニア転職を頑張っていますが、railsポートフォリオだけだとお祈りしかされません。
AWSの冗長構成でインフラ構築しててもお祈りです。そこでRails+VueのRESTfulAPIを使ったアプリ(いわゆるSPA)を追加で作ったところ最終面接までは行けるようになりましたが、それでもやっぱり大変です。
もしWebエンジニア転職が大変だぁという方が読んでくれていたら、これだけは言いたいです。
諦めずに頑張ろうね!!!!以上、お粗末様でした。
- 投稿日:2020-06-23T15:16:25+09:00
Rails フリマアプリ payjpを使った購入機能の実装
なにこれ
某スクールのカリキュラムでフリマアプリを開発しました。
そこで購入機能を実装したので、payjpの導入〜商品購入までの流れを備忘録として書きます。
細かく解説はしないで、ざっと流れを説明する記事です。
コードに縦棒が混じってますが、ご了承下さい。payjpをインストール
gem 'payjp'
をbundle installしますユーザーのカード情報を保存するためのcardsテーブルを作成
なぜこのテーブルを作るのか
payjpはセキュリティの観点で、payjp側でカード番号などを管理する仕組みになっており、
開発者側の環境では暗号化されてます。
暗号化されたカード情報は保存する必要があるためです。db/migrate/20200615032616_create_cards.rb| class CreateCards < ActiveRecord::Migration[5.2] | |:--| | def change | | create_table :cards do |t| | | t.references :user ,foreign_key: true, null: false | | t.string :customer_id, null: false | | t.string :card_id, null: false | | t.timestamps | | end | | end | | end |次にアソシエーションを組みます。
app/models/card.rb| class Card < ApplicationRecord | |:--| | belongs_to :user, optional: true | | end |ルーティングを設定します。
今回はカード一覧、カード新規登録、カード作成、カード削除をするので、4つ設定します。
商品が購入した時に呼び出されるアクションが欲しいので、posts(商品投稿)にpayアクションを追加しています。
pay/:idで「どの番号の商品か」と言うのを分からせてます。
例)post.id[1]で購入が押されたらパラメーターでpost.id[1]が送られる
それで該当商品を購入済み状態に変更できます!routes.rb| resources :cards, only: [:index, :new, :create, :destroy] | | resources :posts do | | collection do | | post 'pay/:id'=> 'posts#pay' | | end | | end |次にcredentials.yml.encにpayjpのシークレットキーの情報を追加します。
credentials.ymlの説明は省略します。credentialsを編集できるようにするためには、どのエディタで編集するのかをあらかじめ設定する必要があります。
まずは、ターミナルからVSCodeを起動できるよう設定を行います。
VSCodeで、「Command + Shift + P」を同時に押してコマンドパレットを開きます。
続いて、「shell」と入力しましょう。
メニューに、「PATH内に'code'コマンドをインストールします」という項目が表示されるので、それをクリックします。この操作を行うことで、ターミナルから「code」と打つことでVSCodeを起動できるようになりました。
以下のコマンドでcredentials.ymlを開きます。EDITOR='code --wait' rails credentials:edit開いたら以下の内容を記述。
SK_test_XXXXXXの内容は、payjpに会員登録後に「API」という項目から確認できます。credentials.ymlpayjp: PAYJP_SECRET_KEY: sk_test_XXXXXXXXXXXXXXXXX追加したらタブの✗を押して保存します。
control + K だと保存されないです。cardsコントローラーを作成、編集します。
app/controllers/cards_controller.rbclass CardsController < ApplicationController skip_before_action :verify_authenticity_token before_action :set_payjp_key, except: :new def index if current_user.card.present? @cards = Card.where(user_id: current_user.id) end end def new end def create if params[:payjp_token] customer = Payjp::Customer.create(card: params[:payjp_token]) @card = Card.new(user_id: current_user.id, customer_id: customer.id, card_id: customer.default_card) @card.save redirect_to cards_path end end def destroy card = Card.find(params[:id]) customer = Payjp::Customer.retrieve(card.customer_id) customer.delete card.delete redirect_to cards_path end private def set_payjp_key Payjp.api_key = Rails.application.credentials.payjp[:PAYJP_SECRET_KEY] end endcreateアクションの
if params[:payjp_token]
は後述しますが、
パラメーターで[:payjp_token]というデータを送っております。
customer = Payjp::Customer.create(card: params[:payjp_token])
でpayjpのサーバーと通信してるみたいです。
通信した結果を変数customerに代入してる。といった流れです。
@card = Card.new(user_id: current_user.id, customer_id: customer.id, card_id: customer.default_card)
これでカードの新規登録を行います。内容は暗号化されたものですprivateの中のset_payjp_keyメソッドとは?
Payjp.api_key = Rails.application.credentials.payjp[:PAYJP_SECRET_KEY]
この記述で、Payjp.api_keyという変数?に、先程追加したcredentials.ymlの中身を呼び出してます。
この記述がないと、createアクションでpayjpのサーバーを呼び出すことができず、エラーが起きます。beforeアクションで
skip_before_action :verify_authenticity_token
とあります。
これは超重要で、端的に言うと「これがないとpayjpにハッシュ(データ)を送ることができません。」サーバーサイドの準備は終わったので、次にビューを触っていきます。
application.html.hamlにscriptを追加してpayjpを読み込ませます。app/views/layouts/application.html.haml%body %script{src: "https://js.pay.jp/", type: "text/javascript"} = render 'layouts/notifications' = yield次にカードの新規登録ページを作成します。
クラスは個人で変更して下さい。
%formを使っている理由は、payjpのjsを呼び出すためです。
form_withを使うやり方が分かりませんでした。app/views/cards/new.html.haml.show-main__registration-field %form.card-form{method: :post, action: "/cards", id: "chargeForm"} .show-main__registration-field--text クレジットカード情報登録 .show-main__registration-field__container .show-main__registration-field__container__number %label.show-main__registration-field__container__number--text カード番号 %span.form-require 必須 %input{type: "text", placeholder: "半角数字のみ", class: "show-main__registration-field__container__number--input", id: "card-num-input"} .show-main__registration-field__container__expiration %label.show-main__registration-field__container__expiration--text 有効期限 %span.form-require 必須 .show-main__registration-field__container__expiration--input %select#month-select %option{value: ""} -- %option{value: "1"}01 %option{value: "2"}02 %option{value: "3"}03 %option{value: "4"}04 %option{value: "5"}05 %option{value: "6"}06 %option{value: "7"}07 %option{value: "8"}08 %option{value: "9"}09 %option{value: "10"}10 %option{value: "11"}11 %option{value: "12"}12 %select#year-select %option{value: ""} -- %option{value: "2021"}21 %option{value: "2022"}22 %option{value: "2023"}23 %option{value: "2024"}24 %option{value: "2025"}25 %option{value: "2026"}26 .show-main__registration-field__container__security %label.show-main__registration-field__container__security--text セキュリティコード %span.form-require 必須 %input{class: "show-main__registration-field__container__security--input", id: "security-code-input", name: "security-code", type: "text", placeholder: "カード背面4桁もしくは3桁の番号"} .show-main__registration-field__container__security--information %span.show-main__registration-field__container__security--information-link =link_to root_path do %i.fas.fa-question-circle カードの裏面の番号とは? %input#add-card-btn{type: 'submit', value: "クレジットカードの登録", class: "show-main__registration-field__container--submit"}先程formで送信したデータをcontrollerに送れる形式である
payjp_token
に変更する処理をjsでします。
このあたりは正直公式のコピペなので、解説できないです。
「こういうもの」としか受け取れないです。
パブリックキーはがっつり本文に書いちゃってokです。
正しいテストカードの情報じゃないとif (status === 200) {
によってエラーが出るようになってます。ちなみに、カードのテスト番号は、以下です
カードナンバー【4242424242424242】
有効期限【12/21】
名前【YUI ARAGAKI】card-form.js$(function () { // パブリックキーを書いてpayjpと通信できる状態にする Payjp.setPublicKey('pk_test_62873b159b61e41f8452494b'); // 投稿ボタンを定義 const card_btn = $('#add-card-btn'); if (card_btn != null) { // 投稿ボタンが押されたら発火 card_btn.click(function (e) { e.preventDefault(); $(function () { // カードの情報を定数cardに代入。 const card = { number: $('#card-num-input').val(), exp_month: $('#month-select').val(), exp_year: $('#year-select').val(), cvc: $('#security-code-input').val(), } form = $("#chargeForm") // この記述でtokenを呼び出してます。 Payjp.createToken(card, function (status, response) { if (status === 200) { //成功した場合。statusが200だと通信成功らしいです。 // inputをappendしています valueは生成したデータで。 form.append($('<input name="payjp_token" type="hidden">').val(response.id)); // これでcreateアクションが呼ばれます。 form.submit(); // これが出たらカード情報が登録されます alert("カード情報を登録しました"); } else { // カード情報が正しくないor入力漏れがあるとこちらが表示されます alert("正しいカード情報を入力してください"); } }) }); }); } });次にカード一覧を作成します。
これも公式を移したので解説する部分は少ないです。
payjpは自分でコードを書いたりしないで、公式に頼るのが正解だと思いました。app/views/cards/index.html.haml= render @cardsapp/views/cards/_card.html.haml= link_to "削除する", card_path(card), method: :delete, class: 'btn', data: { confirm: '削除してよろしいですか?' } - customer = Payjp::Customer.retrieve(card.customer_id) - @default_card_information = customer.cards.retrieve(card.card_id) = "**** **** **** " + @default_card_information.last4 - exp_month = @default_card_information.exp_month.to_s - exp_year = @default_card_information.exp_year.to_s.slice(2,3) = exp_month + " / " + exp_year次は商品詳細ページでpayjpを使った購入リンクを作成します。
postsコントローラーのpayアクションを呼び出す記述をしています。
scriptは公式。app/views/posts/show.html.haml= form_tag(action: :pay, method: :post) do %script.payjp-button{:src => "https://checkout.pay.jp", :type => "text/javascript" ,"data-text" => "購入する" ,"data-key" => "pk_test_62873b159b61e41f8452494b"}コントローラーを記述をします!
cahrgeまで全て公式に書いてあります。
@post.updateでboolean型に指定したpurchasedというカラムをtrueにしてます。
つまり、購入済みの状態にしています。posts_controller.rbdef pay @post = Post.find(params[:id]) Payjp.api_key = Rails.application.credentials.payjp[:PAYJP_SECRET_KEY] charge = Payjp::Charge.create( amount: @post.price, card: params['payjp-token'], currency: 'jpy' ) @post.update(purchased: true) redirect_to root_path, notice: '購入しました!' end以上でpayjpのカード登録〜商品購入までの流れは終了です!
レビュー機能をつけるなら、カラムの設定とかテーブル追加したり色々やると思いますが、
自分たちのチームは必須実装を終わらせると言う目的だったので、そこらへんは触ってないです!
追加実装までやるチームはすごいと思いました。
- 投稿日:2020-06-23T12:53:01+09:00
マイグレーション データ型は何が適しての??
マイグレーションで実現できること
テーブル作成
テーブル削除
カラム追加
カラム名変更
カラムのデータ型変更
カラム削除マイグレーションファイル作成
マイグレーションファイルは モデルを作成した時 に一緒に作成される。
さらに マイグレーションファイル単体 で作成することも可能。ターミナルrails g model [モデル名] [属性名:データ型 属性名:データ型・・・] [オプション] #単体で生成する場合 rails g migration マイグレーション名上記のコマンドを実行することで、db/migrateフォルダの中にマイグレーションファイルが作成される。
データ型は何が適してるの??
オフィシャル情報 日本語でざっくり概要 primary_key プライマリキー string 文字列(1〜255文字) text 長い文字列(1〜4294967296文字) integer 整数(4バイト) bigint 整数(8バイト) float 浮動小数 decimal 精度の高い少数 numeric 数値 datetime 日時 time 時間 date 日付 binary バイナリーデーター boolean Boolean型 似ているけど違うものはどうするのか
文字を扱う場合、stringとtextどちらが適しているか
stringは、255文字までしか扱うことが出来ないため、状態や時期によっては、256文字以上になる可能性のあるデータを扱う場合はtextを使うことをおすすめします。
名前やメールアドレス、社名などの文字情報は、stringで取り扱い、本文や備考などの文章情報はtextを使うのが一般的です。enumを扱う場合、stringとintegerどちらが適しているか
hashのintegerをマッピングできるのがenumなので、enumで扱う予定のカラムをstringにしたらそもそもenumを取り入れる意味がないし、機能しないですね。ということを冷静に考えて、enumで扱う予定のカラムのデータ型はintegerが適しています。idを扱う場合、 integerとbigintどちらが適しているか
idは、将来的にユーザーが増えると膨大な桁数になる可能性があります。Rails5.1からidカラムがデフォルトでbigintになっていることも踏まえて、基本的にはbigintが適していると考えて良いでしょう。いずれも、現状と一致させるという考え方よりは、将来的に「入らない!」という状況になる可能性が少しでもあれば大きめの箱を用意する、という考え方で選定すると安心です。
補足
Rails modelの命名規約
Railsでは、modelに対応するデータベースのテーブル名はmembersのように複数形になります。
しかし、modelのクラス名は、Memberのように頭が大文字の単数形になる。
また、modelを作成する時は、「rails g model member」のようにmemberを小文字始めても大丈夫です。
また、例えばmember_imageと指定してもMemberImageとしても、MemberImageモデル(テーブル名はmember_images)が作成されます。
ただし、membersのように複数形にすることは厳禁です。Membersモデルが作成されてしまいます。modelは必ず単数形で作成しましょう。
- 投稿日:2020-06-23T12:35:50+09:00
[Git] ファイルがどのbranchに含まているか検索する
謎のmigrationがあるためgit log全体を検索
対象のファイルが含まれるコミットを発見$ git log --all -- 'db/migrate/2020323*' commit d178513009038b0d6473de95a685c9402da14123 Author: Cozy <dummy-mail@gmail.com> Date: Fri Mar 27 18:20:29 2020 +0900 〇〇のcolumn名変更あった。glob対応してるのが嬉しいね
git branch
でコミットが含まれるbranchを検索して発見$ git branch -a --contains d178513009038b0d6473de95a685c9402da14123 remotes/origin/feature/dummy-feature-branchこれにて一件落着 ?
- 投稿日:2020-06-23T11:56:01+09:00
AWS☆☆☆☆ デプロイまでの道のり4-最終章(短いバージョン、全4回)
1)背景
第4回目の最終章です。
自身のポートフォリオをデプロイしました。最後の作業としてドメインの紐つけをします。
AWS関連手順記事はすごく多いので、ここでは備忘録も含めて、非常に端的に手順を記載します。2)環境
項目 内容 OS.Amazon Linux AMI release 2018.03 Ruby v2.5.1 Ruby On Rails v5.2.4.3 MySQL v5.6 Unicorn v5.4.1 3)内容
以下設定で65分程度かなと思います。(段取りが分かっていれば、30分)
※【ローカルマシン】指定以外は、全てAWSでの作業になります。(1)お名前ドットコムからドメインを取得(20分)
同サイトからドメインを契約します。ここについては割愛いたします。
(2)Nginxの導入と設定(20分)
- yumパッケージを活用してNginx(webサーバ)を導入する
- Nginxのconfigファイルを設定する
- Nginxのパッケージ権限の付与(/var/lib/nginx)
- Unicorn設定ファイルの変更(Nginxを経由して処理を行うために設定)
(3)AWS-Route53の設定(10分)
- ホストゾーンの新規作成
- 新規レコードセットに同ElaspicIPを登録する
(4)お名前ドットコムの設定(15分)
- AWSで新規に割り当てられたNSレコードをネームサーバ名として登録する
- DNS設定(ElaspicIPと、ドメインの紐付けを行う)
(2)Nginx設定2(10分)
- 登録したドメイン名を同設定ファイルに設定する。
これで完了です。
指定のドメインにアクセスすると、NGINXを介してUnicornが起動しているrailsアプリを参照することが出来ます。
正直簡単です。出来るだけ難しく書かないように端的に記載しました。
以上です。
- 投稿日:2020-06-23T11:55:19+09:00
webpacker周りの修正
webpacker3, rails5.2のアプリをクローンしたときにwebpacker周りのエラーに見舞われて直した時の自分用の備忘録です。
これを直した後、webpacker5.1.1、rails6にあげました。
Cannot find module 'babel-plugin-syntax-dynamic-import'
https://github.com/rails/webpacker/issues/1923
pry-doc verisonup
08:35:35 web.1 | from bin/rails:4:in `<main>' 08:35:35 web.1 | ruby/2.7.1 isn't supported by this pry-doc version 08:35:35 web.1 | exited with code 1 08:35:35 system | sending SIGTERM to all processes 08:35:40 system | sending SIGKILL to all processes nosappunoMacBook-Pro@nosappu ~/desktop/ruby/designcase_hp$ bundle update pry-docuninitialized constant Pry::Command::ExitAll (NameError)
bundle update pry-byebughttps://github.com/pry/pry/issues/2121
undefined method `new_ostruct_member' for #Config::Options (NoMethodError)
https://qiita.com/tttkkkkk/items/f54adc8b7e48dea45e98
Uncaught Error: Module parse failed: Unexpected token (2:0)
File was processed with these loaders:
* ./node_modules/vue-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.https://github.com/symfony/webpack-encore/issues/321
https://github.com/webpack/webpack/issues/8656
↑より
package.jsonに"acorn": "^6.0.5"Module Error (from ./node_modules/vue-loader/lib/index.js):vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.
未解決
https://qiita.com/kazutosato/items/c0e508f15b9a03f3dd6b
これみてみたCannot find module 'postcss-cssnext'
rails webpacker:installwebpack4以上だと自動的にpostcss.config.jsが作られるらしい
Rails & Webpacker環境でPostCSSを使う
postcss githubgemfileでwebpackerのバージョンをあげていたのでwebpackerのinstallをし直さなければいけなかった
gem 'webpacker', '~> 5.0'yarn add postcss-cssnextpostcss.config.jsmodule.exports = { plugins: [ require('postcss-import'), require('postcss-flexbugs-fixes'), require('postcss-preset-env')({ autoprefixer: { flexbox: 'no-2009' }, stage: 3 }), require('postcss-cssnext') #追加 ] }
【保存版】Rails 5 Webpacker公式ドキュメントの歩き方+追加情報
Rails5 / webpacker を heroku で動かす
Rails6でWebpackerの導入(Uikit・foreman)
なんかよくわかんないけど最初webpackerバージョンあげようとしたらこれにつまずいてこれもみてた
UglifyJsPlugin
は4からは書かなくてもやってくれるらしい
Webpack 4 - How to configure minimize?
- 投稿日:2020-06-23T11:23:56+09:00
【CircleCI】GitHubへプッシュ時に自動デプロイする際の手順
今まで自動デプロイは「capistrano」を使用していましたが、毎回コードを修正するたびにローカルでmasterマージして、「bundle exec cap production deploy」を実行していました。
今回はcircleCIを使用し、masterマージされたら自動でサーバーへSSHしてコードをデプロイするように実装してみました。
以下、実装の際の流れや詰まった部分の解説をまとめていきます!- 開発環境
- ruby : 2.5.1
- rails : 2.4.2.3
- circleCI : 2.1
※ dockerは今回使用していません。
.circleci/config.ymlの設定
①最初にcircleCIで使うconfig.ymlの設定をローカルでしていきます。
circleCIの設定は、該当リポジトリのルート直下に.circleciと言うフォルダを作り、その中のconfig.ymlで行います。
- config.ymlに以下を追記。
config.ymlversion: 2.1 orbs: ruby: circleci/ruby@0.1.2 jobs: deploy: machine: enabled: true steps: - add_ssh_keys: fingerprints: - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" #SSHするサーバの秘密鍵を登録後、ハッシュ化されているfingerprintsをコピペする。 - run: ssh -p $SSH_PORT $SSH_USER@$SSH_HOST "/var/www/リポジトリ名/deploy-me.sh" workflows: version: 2.1 deploy: jobs: - deploy: filters: branches: only: master
- ルート直下に「deploy-me.sh」ファイル作成後、下記を記入。
deploy-me.sh#!/bin/bash cd /var/www/リポジトリ名/ && git pull以下、解説します。
①こちらで自動デプロイの設定をしており、masterマージしたら自動的にデプロイされる仕組みになっている。
②「- add_ssh_keys:」以下には、HOST(IPアドレス)と秘密鍵を登録した際、ハッシュに変換されたfingerprintsをコピペしてくる。これによりSSHするサーバーの秘密鍵を登録できる。
③「- run: ssh -p ~ 」で、設定した鍵 + 設定した環境変数によりsshし、サーバーにログインする。その後、「“/var/www/rails/soup/deploy-me.sh”」によりプルリクしたらgit pullするように設定している。
④workflows以下の設定により、masterブランチ以外ではデプロイを実行しないようにしている。cirecleCI導入・自動デプロイしたいリポジトリの追加
①まずcircleCIのHP(https://circleci.com) にいき、新しくアカウント登録(sign up)をします。GitHubのアカウントを持っていたらすぐに連携でき、アカウント登録が可能です。
②ログイン後、「Add Projects」を選択し、今回自動デプロイしたいアプリやサイトのリポジトリを追加していきます。
追加するには該当のリポジトリの「Set Up Project」をクリックします。③上記で設定したconfig.ymlをコピペし、「Add Manually」で登録していく。 この際、秘密鍵の登録はまだできていないです。後に登録していきます。
④「Start Building」を選択。今回対象となるリポジトリを追加していきます。
追加後、エラーになっていると思いますがそれは秘密鍵や環境変数の設定が済んでいないからです。そちらの情報を追加していきます。秘密鍵の登録
①ダッシュボード「Pipelines」の右上にある「Project Settings」をクリック。
②「SSH Keys」を選択します。一番下に「Additional SSH Keys」があるため、こちらにローカルの秘密鍵の情報を登録していきます。
③「ADD SSH Key」をクリック。「Hostname」はデプロイ先のIPアドレスを入力します。
④「Private Key*」に秘密鍵を入力するために、ローカルで「.ssh」ディレクトリに入り、lsキーを使って秘密鍵があることを確認します(id_rsa等)。こちらをcatで見ていきます。表示された情報を全てコピペし、「Private Key*」に貼り付けます。この際、「-----BEGIN RSA PRIVATE KEY-----」なども全て含めます。
⑤「Add SSH Key」を押し、無事に通れば設定完了です。エラーが出る場合、pem形式で秘密鍵を登録していないか、秘密鍵の情報が新しい形式のため非対象エラーになっている可能性があります。私の場合は後者のエラーが発生しました。
私は下記のサイトを参考にしてエラーを解消しました。
https://blog.adachin.me/archives/11554
秘密鍵を旧式に更新してから行ったことをまとめました。
https://qiita.com/akk_ayy/items/61215e89cfcf680d1c94⑥最後に、ハッシュ化されている fingerprints をコピペし、config.ymlの該当部分にペーストします。
環境変数の設定
①「Project Settings」下の「Environment Variables」を選択します。
②「Add Variable」を選択。デプロイ先のポート情報とユーザー名、ホスト名を登録していきます。
- SSH_PORT
- SSH_USER
- SSH_HOST
これで環境変数の設定が完了しました。③ローカルで設定した内容でSSHログインができるか確かめていきます。
ssh -p ポート ユーザー名@ホスト名 -i ~/.ssh/秘密鍵の名称これでログインでき、
/var/www/リポジトリ名/deploy-me.shこれを叩いてgit pullが実行できたら自動デプロイの準備ができています!
自動デプロイを実行
テストデータをmastarマージし、自動デプロイできているか確認。
この際、circleCIがSUCCESSになっていたら成功です!お疲れ様でした!参考サイト
https://blog.adachin.me/archives/10997
https://qiita.com/tatane616/items/8624e61473a9957d9a81
https://www.tweeeety.blog/entry/2018/02/09/195345
- 投稿日:2020-06-23T09:31:31+09:00
【質問】rails db:migrateを実行してDEPRECATION WARNING:エラーの解決方法
初めて質問させていただきます。
プログラミング初心者です。バージョン:Rails 5.2.4.3
いいね機能を作成のためモデル名Favoritesを作成後
]$ rails db:migrateを実行したところ下記エラーが出ましたエラー文:
DEPRECATION WARNING:Passing the environment's name as a regular argument is deprecated and will be removed in the next Rails version. Please, use the -e option instead. (called from at /home/vagrant/work/Bookers2-favorites/bin/rails:9)
config.eager_load is set to nil. Please update your config/environments/*.rb files accordingly:
- development - set it to false
- test - set it to false (unless you use a tool that preloads your test environment)
- production - set it to true
Traceback (most recent call last):
155: from bin/rails:3:in<main>'
load'
154: from bin/rails:3:in
153: from /home/vagrant/work/Bookers2-favorites/bin/spring:15:in<top (required)>'
require'
152: from /home/vagrant/.rbenv/versions/2.5.7/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in
151: from /home/vagrant/.rbenv/versions/2.5.7/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:inrequire'
'
150: from /home/vagrant/.rbenv/versions/2.5.7/lib/ruby/gems/2.5.0/gems/spring-2.1.0/lib/spring/binstub.rb:11:in
149: from /home/vagrant/.rbenv/versions/2.5.7/lib/ruby/gems/2.5.0/gems/spring-2.1.0/lib/spring/binstub.rb:11:inload'
'
148: from /home/vagrant/.rbenv/versions/2.5.7/lib/ruby/gems/2.5.0/gems/spring-2.1.0/bin/spring:49:in
・
・
・試したこと:
①$rails c -e test下記サイトのエラー文と同じようなので試した後再度、rails db:migrateを実行しましたが同じエラーが出て解決できておりません。
https://qiita.com/sukebeeeeei/items/cf0ccb6f7e8b4e8a775b②$ rails db:migrate:status
database: /home/vagrant/work/Bookers2-favorites/db/development.sqlite3
Status Migration ID Migration Name
up 20200528092619 Devise create users
up 20200528122108 Create books
up 20200530074646 Add user id to books
up 20200601075848 Add profile image id to users
up 20200601090934 Add introduction to users
up 20200601094853 Rename opinion column to books
down 20200622230047 Create favorites初めて質問させていただいております。何か不足な情報や書き方が至らないところがあるかと思いますが、よろしくお願いします。
- 投稿日:2020-06-23T06:48:42+09:00
rails知識メモ[自動で読み込みされるもの]
起動時に自動で読み込まれるもの
- Rails本体およびその設定(/config/配下)
- Gemfileによって自動requireされるように指定されているもの
定数を介して自動で読み込み、development環境では自動再読み込みがされるもの
- /app/配下
https://railsguides.jp/initialization.html
https://railsguides.jp/autoloading_and_reloading_constants.html
- 投稿日:2020-06-23T04:00:02+09:00
deviseを利用してRailsアプリケーションに認証機能を作る
はじめに
- deviseはRailsアプリケーションに簡単に認証機能を追加することができるgemです。deviseはwardenというRackミドルウェアのラッパーで、実際の認証はwardenが行っています(そのため、実装の詳細を知りたい場合はwardenの実装をまず見る必要があるみたいです)。
Railsチュートリアルでは認証機能をスクラッチで作成していますが、実際のRailsアプリケーションではこのdeviseを利用して認証機能を作成することがデファクトスタンダードとなっているようです。
今回は自分の勉強のため、deviseを利用してRailsアプリケーションに認証機能を追加する方法を整理したいと思います。なお内容はこちらの記事をほぼ踏襲しています。謝謝
なお以下の実装はすべてこちらのリポジトリにあります。
環境
- Ruby on Rails 5.2.4.3
- Ruby 2.6.4
deviseのインストール
1.Gemfileを編集
# Devise gem 'devise'2.bundle install
$bundle installdeviseの設定
1.以下のコマンドを実行
$ rails g devise:install create config/initializers/devise.rb create config/locales/devise.en.yml =============================================================================== Depending on your application's configuration some manual setup may be required: 1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb: config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } In production, :host should be set to the actual host of your application. * Required for all applications. * 2. Ensure you have defined root_url to *something* in your config/routes.rb. For example: root to: "home#index" * Not required for API-only Applications * 3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example: <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> * Not required for API-only Applications * 4. You can copy Devise views (for customization) to your app by running: rails g devise:views * Not required * ===============================================================================デフォルトURLを設定
config/development.rbRails.application.configure do ~~中略~~ config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } endrootページを作成
ここはスキップして、任意のページをrootページに設定しても大丈夫です。
$rails g controller StaticPages index
route.rbRails.application.routes.draw do root 'static_pages#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endflashメッセージを設定
app/views/layouts/application.html.erbを編集
<!DOCTYPE html> <html> <head> <title>DeviseRails5</title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> <%= yield %> </body> </html>deviseのviewを作成
$ rails g devise:views invoke Devise::Generators::SharedViewsGenerator create app/views/devise/shared create app/views/devise/shared/_error_messages.html.erb create app/views/devise/shared/_links.html.erb invoke form_for create app/views/devise/confirmations create app/views/devise/confirmations/new.html.erb create app/views/devise/passwords create app/views/devise/passwords/edit.html.erb create app/views/devise/passwords/new.html.erb create app/views/devise/registrations create app/views/devise/registrations/edit.html.erb create app/views/devise/registrations/new.html.erb create app/views/devise/sessions create app/views/devise/sessions/new.html.erb create app/views/devise/unlocks create app/views/devise/unlocks/new.html.erb invoke erb create app/views/devise/mailer create app/views/devise/mailer/confirmation_instructions.html.erb create app/views/devise/mailer/email_changed.html.erb create app/views/devise/mailer/password_change.html.erb create app/views/devise/mailer/reset_password_instructions.html.erb create app/views/devise/mailer/unlock_instructions.html.erb
Userモデルを作成
rails g devise User上記のコマンドで以下のマイグレーションファイルが生成されます。
db/migrate/20200622180124_devise_create_users.rb# frozen_string_literal: true class DeviseCreateUsers < ActiveRecord::Migration[5.2] def change create_table :users do |t| ## Database authenticatable t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: "" ## Recoverable t.string :reset_password_token t.datetime :reset_password_sent_at ## Rememberable t.datetime :remember_created_at ## Trackable # t.integer :sign_in_count, default: 0, null: false # t.datetime :current_sign_in_at # t.datetime :last_sign_in_at # t.inet :current_sign_in_ip # t.inet :last_sign_in_ip ## Confirmable # t.string :confirmation_token # t.datetime :confirmed_at # t.datetime :confirmation_sent_at # t.string :unconfirmed_email # Only if using reconfirmable ## Lockable # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts # t.string :unlock_token # Only if unlock strategy is :email or :both # t.datetime :locked_at t.timestamps null: false end add_index :users, :email, unique: true add_index :users, :reset_password_token, unique: true # add_index :users, :confirmation_token, unique: true # add_index :users, :unlock_token, unique: true end endデフォルトではdatabase_authenticatable、registerable、recoverable、rememberable、 validatableがオンになっているようです。
app/models/user.rbclass User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable end今回はデフォルトのまま作成しますが、オプションで10個のモジュールから好きなものを有効化できます。
モジュール 概要 Database Authenticatable サインイン中にユーザーの信頼性を検証するために、パスワードをハッシュしてデータベースに保存します。認証は、POST要求またはHTTP基本認証の両方で実行できます。 Omniauthable OmniAuth(https://github.com/omniauth/omniauth)サポートを追加します。 Confirmable 確認手順が記載された電子メールを送信し、サインイン時にアカウントが既に確認されているかどうかを確認します。 Recoverable ユーザーのパスワードをリセットし、リセットの指示を送信します。 Registerable 登録プロセスを通じてユーザーのサインアップを処理し、ユーザーが自分のアカウントを編集および破棄できるようにします. Rememberable 保存されたCookieからユーザーを記憶するためのトークンの生成とクリアを管理します. Trackable サインイン数、タイムスタンプ、IPアドレスを追跡します。. Timeoutable 指定した期間アクティブでなかったセッションを期限切れにします。 Validatable 電子メールとパスワードの検証を提供します。 これはオプションであり、カスタマイズできるため、独自の検証を定義できます。 Lockable 指定された回数のサインイン試行の失敗後にアカウントをロックします。 メールまたは指定した期間の後にロックを解除できます マイグレーションを実行します
$ rake db:migrate
Viewを編集
ヘッダーを追加します
app/views/layouts/application.html.erb
<!DOCTYPE html> <html> <head> <title>DeviseSampleApp</title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <header> <nav> <% if user_signed_in? %> <%= link_to 'プロフィール変更', edit_user_registration_path %> <%= link_to 'ログアウト', destroy_user_session_path, method: :delete %> <% else %> <%= link_to 'サインアップ', new_user_registration_path %> <%= link_to 'ログイン', new_user_session_path %> <% end %> </nav> </header> <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> <%= yield %> </body> </html>その他
deviseが提供するヘルパーメソッド
user_signed_in?ユーザがログインしているかどうかを確認できます。
current_userログインしているユーザにアクセスできます。
user_session
セッションにアクセスできます。
サインアップ後のリダイレクト先を変更
app/controllers/application_controller.rbclass ApplicationController < ActionController::Base def after_sign_up_path_for(resource) edit_user_registration_path #ここを編集して任意のページに飛ばせる end endサインアップ後、以下のページにリダイレクトするようになりました。
ログイン後のリダイレクト先を変更
app/controllers/application_controller.rbclass ApplicationController < ActionController::Base def after_sign_in_path_for(resource) edit_user_registration_path #ここを編集して任意のページに飛ばせる end endコールバック関数
(ここは正確にはよくわかっていませんが)
- deviseが呼んでくれるコールバックはafter_fetchだけらしいので(要出典)、その他のコールバックを呼びたいときはwardenのインターフェイスを直接呼び出す必要があります。
参考文献