- 投稿日:2021-01-17T21:58:58+09:00
ページネーション機能(kaminari)
はじめに
現在ポートフォリオ制作中の初学者です。
kaminariを導入してページネーション機能を実装したので備忘録です。1. gemをインストール
Gemfilegem 'kaminari'ターミナル% bundle install2. コントローラーで定義
events_controller.rbdef index @events = Event.page(params[:page]).per(10) endpageとperいうメソッドがkaminariで定義されたメソッドです。
perメソッドの引数にどれだけのレコードが表示されたらページを増やすかを指定できます。3. ビューファイルを編集
events/index.html.erb<%= paginate @events %>表示したいビューファイルに記述。
以上です!
ページネーションの見た目を変える
kaminariで表示させるページネーションはビューの中でcssを当てる事は出来ない。
ので以下方法。ターミナル% rails g kaminari:views defaultapp/viewsフォルダにkaminariを追加。
フォルダの中にページネーションの部分のhtmlが記述されているので、そこで変更する。cssのフレームワークのデザインを適用させる場合
bootstrapなどのcssのフレームワークを使っている場合、表示やデザインが崩れる場合があるので
defaultの部分をそれぞれのフレームワークの名前に指定する。
bootstrap4を使っている場合は下記のコマンド。ターミナル% rails g kaminari:views bootstrap4このコマンドを実行し、ビューファイルを作成すると何も編集しなくてもそれぞれのフレームワークのスタイルに最適化される。
kaminariを日本語化する
デフォルトで英語表記になっているため、日本語表記に変更するためには
config/localesフォルダにkaminari_ja.ymlというファイルを作成し、下記のようなコードを書く。config/locales/kaminari_ja.ymlja: views: pagination: first: "« 最初" last: "最後 »" previous: "‹ 前" next: "次 ›" truncate: "..."参考
- 投稿日:2021-01-17T20:24:04+09:00
汎用性◯『戻る』ボタン
- 投稿日:2021-01-17T20:13:09+09:00
[Docker+Rails]Railsサーバー起動失敗の対処方法
はじめに
サーバー起動しようと思った時に下記エラーログが出力されます。
A server is already running. Check /app/tmp/pids/server.pid.原因
前回のRailsサーバー起動時に作成された
server.pid
ファイルが残っているのが原因。解決方法
色々サイトで調べてみたところ3つ存在するはず。
①ターミナル再起動
参考:A server is already running 対処方法【Rails】
②server.pidファイルを削除
エラーが発生する度に、
/app/tmp/pids/server.pid
ファイルを削除する。
確実な方法ですが、面倒臭いですね…③サーバー起動時に自動でserver.pidファイルを自動で削除する(推奨)
これが一番、楽な方法だと思います。
docker-compose.yml
ファイルのcommand
部分を次の通り設定する。docker-compose.ymlcommand: bash -c "rm -f tmp/pids/server.pid ; bundle exec rails s -p 3000 -b 0.0.0.0"
- 投稿日:2021-01-17T17:25:13+09:00
seeds.rbなどでActiveStorageを使って大量の画像をアップロードする際に発生する SQLite3::BusyException の対処法
発生する問題
Railsの
rails db:seed
を実行すると、以下のようなエラーが起きる場合がある。$ rails db:seed rails aborted! ActiveRecord::StatementInvalid: SQLite3::BusyException: database is locked /path-to-your-app/db/seeds.rb:69:in `<main>'エラーが発生するコード例
エラーが発生した周辺のコードは次のようになっている。
# ... User.destroy_all 100.times do |n| user = User.create!( email: "sample-#{n}@example.com", password: 'password', name: Faker::Name.name ) image_url = Faker::Avatar.image(slug: user.email, size: '150x150') # ActiveStorageを使ってavatarを設定 user.avatar.attach(io: URI.parse(image_url).open, filename: 'avatar.png') end # ...加えて、このアプリケーションではSQLite3を使っている。
default: &default adapter: sqlite3 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 development: <<: *default database: db/development.sqlite3エラーが発生する原因
このエラーは以下の2つの要因で引き起こされる。
- ActiveStorageを使っているため、画像のアップロードや削除が非同期で行われる
- SQLite3は並行処理に弱い(参考)
User.destroy_all
をしたときは既存のデータに対して画像の削除処理が非同期で実行される。既存のデータが大量にあると、データベースに対して読み込みや書き込みのクエリが並行して発行される。
user.avatar.attach
も同様に非同期で画像のアップロード処理が行われる。上のコード例では100件のユーザーデータを作成しようとしたため、やはりデータベースに対して読み込みや書き込みのクエリが並行して発行される。SQLiter3が並行処理に耐えきれなくなると、SQLite3::BusyExceptionが発生する。
エラー回避策
SQLite3の性能上の制約を考慮し、画像の削除処理やアップロード処理を同期的に行うようにする。具体的には以下の2行を
config/seeds.rb
に追加する。+ActiveStorage::AnalyzeJob.queue_adapter = :inline +ActiveStorage::PurgeJob.queue_adapter = :inline User.destroy_all 100.times do |n| user = User.create!( email: "sample-#{n}@example.com", password: 'password', name: Faker::Name.name ) image_url = Faker::Avatar.image(slug: user.email, size: '150x150') user.avatar.attach(io: URI.parse(image_url).open, filename: 'avatar.png') end
ActiveStorage::AnalyzeJobはアップロード時に、ActiveStorage::PurgeJobは削除時にそれぞれ利用されるActiveJobのクラスである。
このqueue_adapter
を:inline
に変更することで、画像のアップロードや削除を同期的に実行できる。参考 https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/InlineAdapter.html
動作確認環境
- Rails 6.1.0
- Ruby 3.0.0
- SQLite3 3.32.3
- 投稿日:2021-01-17T17:24:05+09:00
Railsで簡単にサイトの雛形を作る
サマリ
サイトをたくさん作れるようになりたいけど、どうやろうか?という疑問が浮かんだ。
そこで、いろんなチュートリアルサイトを見たけど、Railsでつかうscaffoldという機能が便利そうだったから、その実施をやってみる。プロジェクトの立ち上げ
Ruby と Railsの導入
まずは、rubyとRailsをPCにセットアップする。
以下の記事を参考に実施した。(Mac)【完全版】MacでRails環境構築する手順の全て
上記の記事を参考にして一通りのインストールを行う。振り返っての注意点だが、なるべく過去1年間に投稿された記事をなるべく参考にしたほうがいいと思う。
それ以上前だと、os自体のバージョンアップをまたいだりとうまく動かない可能性が出てくる。Railsプロジェクトの実行
$ rails new scaffold_sample $ cd scaffold_sample $ rails generate scaffold user name:string age:integerこんな感じで入力すると、ユーザーモデルを備えたviewやcontrollerが一通りできる。
画面の操作も可能なので、何をやっていけばいいか?は結構わかりやすいかも。
次からは、こんなサイトを作れるように色々やっていこうかな。
ハロワ求人検索
ハロワまとめサイト
ハローワーク検索サイト
- 投稿日:2021-01-17T16:58:27+09:00
初心者向け! Rails6+CircleCI+Capistrano+AWS(EC2)で自動デプロイ
はじめに
先日、ポートフォリオ作成後、AWSにCapistranoとCircleCIを使ってCIツールによる自動デプロイを実装できたので、備忘録として残しておこうと思います。
なお、前述したとおり備忘録としてなので参考になる保証はありません。
前提
・Railsアプリが作成できていること
・EC2にCapistranoで自動デプロイを実現できていること以上の条件に当てはまる場合にのみCIツールによるCapistranoの自動デプロイを行います。
開発環境
ローカル
・Rails6
・MySQL5.6.50
・Docker
・docker-compose本番
・EC2
・RDS(MariaDB)
・Unicorn
・Nginx
・Capistrano本願環境にはDockerとdocker-composeは用いていません。
手順
①CircleCIにEC2にログインするための秘密鍵を設定する
②.circleci/config.ymlにssh接続の記述をし、ログインできるか確かめる
③githubのmasterブランチにmergeもしくはpushしたときにCapistranoによるデプロイを行う1)CircleCIにEC2ログインの秘密鍵を設定する
多くの人はここで詰まる事が多く、筆者自身も2時間くらいつまりました。
まず、どの鍵が必要なのかがわからないということでつまります。
必要なのは、ssh
からEC2へログインする時に使うキーペア
と呼ばれる鍵です。インスタンスを作成する時に
pemファイル
形式でダウンロードする秘密鍵をCircleCIにも登録します。ここで1つ注意点があり、CircleCIで使えるのは
pem形式のみ
ということです。
OPENSSH
形式の場合はpem形式
にする必要があるので下記の記事を参考に実行してみてください。(筆者の場合は最初からpem形式だったため、この辺は詳しくないので。。。)ということなので、ターミナルの
ssh
ディレクトリに移って、以下のコマンドを実行します。ターミナル.ssh % cat XXXXXXXXXXXXX.pem # ご自身のEC2にログインする際のキーペアすると以下のように非常に長い暗号が出力されます。
ターミナル-----BEGIN RSA PRIVATE KEY----- WWIEXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # まだまだありますが割愛 -----END RSA PRIVATE KEY-----%これを
-----BEGIN RSA PRIVATE KEY-----
から-----END RSA PRIVATE KEY-----%
までコピーします。もしくは以下のような方法で一括コピーも可能です。
ターミナル.ssh % pbcopy < ~/.ssh/XXXXXXXXX.pemこのコマンドを使うことで先ほどの長い暗号をコピーすることができます。
1-2)CircleCIにキーペア登録
CircleCIのprojectに移り、project settingにを開きます。(右上の歯車アイコンをクリック)
すると以下のように設定画面に遷移するので、メニューバーの
SSH Keys
を選択して、鍵を設定します。
ページが切り替わったら、スクロールして以下の
Add SSH Key
をクリックしましょう。
クリックすると以下のようになるので、
Hostname
とPrivate Key
を入力して、Add SSH Key
をクリックします。
Hostname
にはElasticIP
を入れてもいいですが、筆者の場合は独自ドメインを取得していたためwww.myapp.com
のような形で記入しました。続いて
Private Key
には、先ほどコピーした暗号を貼り付けます。
しばらくすると、元の画面に戻ると思います。すると、
Fingerprint
なる項目に数字と文字と「:」の文字列が存在していると思います。それをコピーしてメモなどに保存しておきましょう。CircleCI(GUI)での設定は以上です。
2).Circlci/cofig.ymlの記述
次にCircleCIでSSH接続できるか確認します。
以下のように存在している記述のsteps:
- checkout
の下などに記述を加えます。
筆者の場合はCapistranoの前はHerokuとCIパイプラインを構築してたため記述を加え、git push
しました。.circleci/config.yml- add_ssh_keys: fingerprints: "XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX"この記述を加え確認しましょう。
以下のように成功していたらOKです。
3)githubのmasterブランチにmergeもしくはpushしたときにCapistranoによるデプロイを行う
ここからが実際に、CIツールによるCapistrano自動デプロイの実装です。
まずこちらが成功したコードです。
.circleci/config.ymlversion: 2.1 orbs: ruby: circleci/ruby@1.1.0 jobs: build: docker: - image: circleci/ruby:2.6.5-node-browsers environment: BUNDLER_VERSION: 2.1.4 steps: - checkout - run: gem install bundler -v 2.1.4 - run: name: Which bundler? command: bundle -v - ruby/install-deps deploy: docker: - image: circleci/ruby:2.6.5-node-browsers environment: BUNDLER_VERSION: 2.1.4 steps: - checkout - ruby/install-deps - add_ssh_keys: fingerprints: "XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX" - deploy: name: Capistrano deploy command: bundle exec cap production deploy workflows: version: 2.1 build-deploy: jobs: - build - deploy: requires: - build filters: branches: only: master筆者が参考にしたのは参考文献にもある記事と公式ですが、難しかったです(笑)
1つずつ解説すると、dockerのimageは自分のrubyのバージョンに合わせ、bundlerの自分のバージョンに合わせるような記述をしました。
まず
job
としてコードチェックのためのbuild
を行い、bundlerのインストールするようにします。そして
deploy job
ではCapistranoを走らせるようにして、どのSSHに接続するかを指定しています。
これが先ほど設定したり、記述したadd_ssh_keys:
という記述に当たります。その下のコマンドで実際にCapistranoが走るという構図になっています。
そして
workflows
ではonly: master
としてmasterブランチにpushもしくはmergeがあった場合に行うように設定しています。詳しい説明は下記の記事や、記事内で参考にしていた文献に書いてありますので、そちらの方も合わせて読むとより理解しやすいと思います。
結構、苦労しましたが、なんとか実装できました。
皆さんも頑張ってください。参考文献
- 投稿日:2021-01-17T16:32:46+09:00
InfiniteScrollとkaminariで無限スクロールを作る
完成系
開発環境
rails 6.0.2 ubuntu(wsl) InfiniteScroll 4.0.1事前準備
- 投稿一覧
- 投稿一覧のデモデータ
- kaminariの導入
手順
infinite-scrollの導入
ここからダウンロードしてください。
CDNを使ってもokです。
自分はvendor/assets/javascripts/
に置きました。(場所はどこでも良いです。)
ここの読み込む場所が違うとエラーになりました。
//= require_tree .
の真下に置くと良いと思います。application.js//= require infinite-scroll.pkgd.min
無限スクロールを実装
talk.js$(document).on('turbolinks:load', function () { if ($("nav ul.pagination a[rel=next]").length) { $('.talk-cards').infiniteScroll({ path: "nav ul.pagination a[rel=next]", append: ".talk-cards .card-index", hideNav: "nav ul.pagination", history: false, scrollThreshold: false, button: ".loadmore-btn", status: ".page-load-status", }); }; });公式サイトを見るのが一番良いと思いますが、オプションの説明しておきます。
path
:次に読み込むページのURLの指定(必須)
append
:読み込んだ次ページの内容のうち、追加する要素の指定。ここを間違るとレイアウト崩れたりする。
history
:urlを変更し、履歴を残すか。false
なら固定のurlになる。
hideNav
:非表示にするnavigationを指定する。
scrollThreshold
:スクロールで自動で読み込むか。false
なら読み込まない。
button
:ページをロードするためのボタン要素の指定。
status
:読み込み中や全部読み込んだ後に表示するもの指定。部分テンプレートと投稿一覧のビュー
cssはこちらを参考にしてください。
talks/_infinitescroll.html.slim.loadmore-btn-wrapper.p-0.d-flex button.loadmore-btn.btn.active.mx-auto さらに表示 .page-load-status style="display: none" .infinite-scroll-request .loader-ellips span.loader-ellips__dot span.loader-ellips__dot span.loader-ellips__dot span.loader-ellips__dottalks/index.html.slim.talk-cards - @talks.each do |talk| .card.mx-auto.card-index .card-body .card-title.text-muted.user-info #省略 = link_to simple_format(h(talk.content), {}, sanitize: false, wrapper_tag: "div"), talk = paginate @talks = render "infinitescroll"終わりに
もし間違がありましたら、編集リクエスト又はコメントお願いします。
上手く行かない場合は、developer toolsを使って頑張ってください。参考文献
- 投稿日:2021-01-17T15:40:00+09:00
0から Ruby on Rails の環境構築【macOS】 (Homebrew のインストールから Rails のインストールまで)
【macOS】 Ruby on Rails 6.1 環境構築 (Ruby 3.0)
本記事はRuby on Railsの環境構築を初心者の方でも迷わずできるように解説した記事です。
Ruby on Railsは、広範囲にわたる開発で使用されています。日本のスタートアップでも採用されていることが多く、食べログやnote、会計ソフトのfreeeなどもRuby on Railsによって開発されています。
そんなRuby on Railsですが、2019年8月にバージョン 6.0.0 がリリース、2020年12月にはバージョン 6.1.0 がリリースされました。また、Ruby自体も2020年12月にバージョン3.0にメジャーアップデートされ新しい機能が追加されています。
本記事では、Ruby 3.0とRuby on Rails 6.1.1 の環境構築方法を説明していきます。
環境
- macOS (Windowsには対応していません)
- Windowsの方向けにCloud9を使った環境構築の記事も公開しています。
- Terminalはbashを使用しています
- zsh の場合は一部動作しない箇所があります
Homebrewをインストール
ソフトウェアの導入を簡単にするため、macOS用のパッケージ管理システムであるHomebrewをインストールします。
次のリンク先からHomebrewをインストールします。
リンク先にアクセスすると次のページが表示されます。
「インストール」の見出しの下にあるスクリプトの行をmacOSのターミナルにコピー&ペーストします。
ターミナルで実行するとHomebrewのインストールが開始されます。
インストールには数分~10分ほどかかります。途中で何度かパスワードを要求されるので、使用しているパソコンのパスワードを入力してください。
Homebrewのインストール後に、無事にインストールされたかどうかを確認します。
インストール後の確認は、ターミナルを起動して次のコマンドを入力します。
brew -v
入力をしたら
enter
キーを押して、コマンドを実行します。コマンドが実行されると、次のような画面になります。
Homebrew 2.7.1 Homebrew/homebrew-core (git revision 9adfd; last commit 2021-01-05) Homebrew/homebrew-cask (git revision 3d3c93; last commit 2021-01-05)「Homebrew 2.7.1」とバージョンが表示され、Homebrewがインストールされたことが確認できました。
(執筆時は「2.7.1」と表示されましたが、「2.7.2」などと表示されると最新版がインストールされたことになります)
rbenvのインストール
次に、Rubyのバージョンを簡単に切り替えられるrbenvをインストールします。
それでは、ターミナルで次のコマンドを入力して実行してください。
brew install rbenv
コマンドを実行後に、実際にrbenvがインストールされているかを確認します。
次のコマンドを入力して、インストールしたrbenvのバージョンを確認します。
rbenv --version
コマンドを実行すると、次のようにバージョン情報が表示されます。
rbenv --version rbenv 1.1.2
この表示では「
rbenv 1.1.2
」とバージョン情報が表示されています。rbenvがインストールされたことを確認できました。
rbenvにPATHを通す
rbenvコマンドを利用するために、rbenvにPATHを通します。
「PATHを通す」とは、コマンドの実行ファイルの場所を確認するために指定することです。
rbenvコマンドのPATHを通すために、次の3つのコマンドを用意しました。
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile echo 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi' >> ~/.bash_profile source ~/.bash_profileこれらのコマンドを1行ずつ入力して、実行します。
まずは最初のコマンドです。
スクリプトを
.bash_profile
に追加します。echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
>> ~/.bash_profile
でスクリプトを.bash_profile
に追加しました。次に、2番めのコマンドを入力して実行します。
echo 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi' >> ~/.bash_profileこのコマンドを追加することで、ターミナル起動時にrbenvを自動的に起動させます。
最後に、
source
というコマンドを使って追加した内容を反映します。source ~/.bash_profile
.bash_profile
に追加した内容を反映できました。これでrbenvコマンドを利用するのに必要なPATHが通りました。
Rubyの環境構築
次にRubyをインストールします。
Rubyをインストールする前に、インストールできるRubyのバージョンを確認します。
先ほどインストールしたrbenvを使って次のコマンドを入力してください。
rbenv install -l
コマンドを実行すると、最新の安定版のバージョンが一覧で表示されます。
rbenv install -l 2.5.8 2.6.6 2.7.2 3.0.0 jruby-9.2.13.0 maglev-1.0.0 mruby-2.1.2 rbx-5.0 truffleruby-20.2.0 truffleruby+graalvm-20.2.0 Only latest stable releases for each Ruby implementation are shown. Use 'rbenv install --list-all' to show all local versions.
※ インストール可能なrubyのバージョンを全て表示するには、上記の実行結果にあるように
rbenv install -l
というコマンドを実行しますバージョン番号を見ると、執筆時点(2021年1月)の安定版の最新バージョンは「3.0.0」なので、3.0.0をインストールします。
参考:Ruby ダウンロード
もし最新バージョンが表示されない場合は、rbenvとruby-buildを最新版にする必要があります。
参考:rbenv Upgrading with Homebrew
それでは、次のコマンドを入力してRuby 3.0.0 をインストールします。
rbenv install 3.0.0
コマンドを実行するとインストールを開始します。インストール完了まで数分間かかることがあります。
これでRubyがインストールされました。
ローカルで使うRubyのバージョンを指定
さらにローカルで使うRubyのバージョンを指定するために、以下のコマンドを実行します。
rbenv local 3.0.0
これでローカルでRubyの3.0.0のバージョンが使用されます。
このように
local
を使うと、プロジェクトごとにRubyのバージョンを指定できます。PC(サーバー)内で同じバージョンを共通して使う場合は、
local
ではなくglobal
を使います。次に、Rubyのバージョン情報を確認します。次のコマンドを入力します。
ruby -v
コマンドを実行すると、次のようにバージョンが表示されます。
ruby -v ruby 3.0.0p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19]
指定した「3.0.0」と表示されました。これで指定したRubyのバージョンが確認できました。
Bundlerをインストール
Rubyをインストールしたら、次にBundlerをインストールします。
RubyではGemというライブラリを使いパッケージを管理しています。
Gemコマンドで簡単にインストールやアンインストールができますが、複数のGemを使うとGem同士で依存関係が生まれ、バージョン違いによる不具合が出てきます。
そこで、BundlerでGemのそれぞれのバージョンを正確に追跡し管理して、Rubyプロジェクトに一貫した環境を提供します。
それではBundlerをインストールしましょう。以下のコマンドを入力します。
gem install bundler
コマンドを実行するとインストールが始まります。
インストールされたBlundlerのバージョンを確認しましょう。
次のコマンドを入力します。
bundler -v
コマンドの実行後、次のように表示されます。
bundler -v Bundler version 2.2.3
「version 2.2.3」とバージョン情報が表示されました。
これでBlundlerがインストール済みであることを確認できました。
yarnをインストール
次にyarnをインストールします。
yarnはJavaScriptのライブラリの利用に必要なパッケージマネージャです。
yarnと互換性のあるnpmというパッケージマネージャもあります。しかし、Rails6ではWebpackerが標準になったことにより、yarnが必要です。
それでは、yarnのインストールを行いましょう。
次のコマンドを入力します。
brew install yarn
Homebrewのコマンドを実行すると、yarnがインストールされます。
yarnが実際にインストールされたかを確認するために、次のコマンドを入力します。
yarn -v
コマンドを実行すると、次のように表示されます。
yarn -v 1.22.10
ここでは「
1.22.10
」と表示されました。バージョン情報が表示されていれば、yarnがインストールされたことが確認できます。Ruby on Railsのインストール
いよいよ、Railsをインストールします。
Railsのインストール時に「
-v バージョン番号
」とバージョンを指定してインストールできます。今回はバージョン「
6.1.1
」をインストールします。次のコマンドを入力します。
gem install rails -v 6.1.1
コマンドを実行すると、インストールを開始します。インストールの完了までに数分かかることがあります。
Railsのバージョンを確認
Railsをインストールしたら、Railsのバージョンを確認するために次のコマンドを入力します。
rails -v
コマンドを実行すると、次の画面が表示されます。
rails -v Rails 6.1.1
「
Rails 6.1.1
」と表示されました。これで無事にRuby on Railsのインストールが完了しました。
※ 本記事はTechpitの教材を一部修正したものです。
参考
- 投稿日:2021-01-17T13:47:02+09:00
データベースとモデルの関係性(基礎)
データベースに関連するファイルについて
目的:エラー解決のためには、モデルファイルとマイグレーションファイルの役割の違いをしっかりと理解しないといけないと思いこの記事を書きました。
現在:ポートフォリオ作成最終段階ですが、理解できてないことがまだまだたくさんあり、基礎理解が足りていないことに気付き、基礎を固めながら仕組みから理解しているという状況です。
モデルファイルの役割
データベースへのアクセス権限を示すためのファイルです。
記述されているモデルとアソシエーション(関連付け)は、モデル通しのデータベースへのアクセス権限を示しているということになる。なぜ、このデータは取り出せないのか?を理解するためには、データーベースへのアクセス権限の記述されている、モデルファイルを見ると分かる。そして、理解への第一歩になる。
マイグレーションファイルの役割
データの内容を保管するために必要な情報を記述しているファイルです。
データを受け渡しの際は、ファイルに記述されているテーブル名(クラス)・カラム名を指定します。なぜ、テーブル名(クラス)を指定するのか?
- カラムの条件に合わせた情報を格納したい場合、格納しているデータを取り出す際には、クラスを指定してから、カラム名を指定しなければならない。
日常生活に置き換えてみると、「〇〇クラスの山田さん」と言わずに、「全体の前で山田さんと叫んでいる」ような状況になってしまうからです。まとめ
両方を合わせて理解する
データベースからのデータの受け取りの仕組みの基礎理解ができるようになる。
- モデルファイル:使用したいデータ同士でデータベースの権限を持っているのか?
- マイグレーションファイル:データベースに保管しているテーブルは、どの情報を保持しているのか
関連性を持っていなモデルとモデル
- データベース間のやりとりはできないためリレーションを作成する必要がある。
- データをそれぞれ取り出し、インスタンス変数を作成する必要がある。
ついでに
MVCのフェーズ理解
- model:データを取得、データを保管、データを取得、データを渡す
- controller:view・modelから情報を取得、view・modelが取得したい情報を渡す、view・modelが取得したい情報を受け取り渡す
- view:modelの情報をcontrollerから取得
アウトプットを公開することのメリット(感想)
自分の理解は本当にあっているのか?と何度も思いながら書くことで、知識定着ができました。
また、誰かの役に立つ記事になったのか分かりませんが、ブログで公開するアウトプットをすることで、深く理解でき、伝える力のトレーニングをすることもできました。
読んでくださった方、ありがとうございました。
間違いがありましたらご遠慮なくコメントの方よろしくお願いします。
- 投稿日:2021-01-17T12:26:26+09:00
[Rails]ぱんくずリスト機能について
はじめに
今度はぱんくず機能を実装復習しましたのでまたすぐ実装できるように
記していきたいと思います。
実装していきます。
ぱんくず機能とは
現在どこのページにいるのかを視覚的にわかりやすくした表示できる機能ことです。
物語の「ヘンゼルとグレーテル」のなかで、ヘンゼルとグレーテルの二人が森の中で道に迷わないように歩きながら来た道の目印にぱんくずを落としていったことから"ぱんくず機能"で、gemの名前が「gretel」なのだそうです。
可愛いですね
ちなみに、ヘンゼルは男の子の方でグレーテルは女の子です。
実装
「gretel」というgemを「Gemfile」に記述し
Gemfilegem 'gretel'インストールします。
bundle installこちらを入力すると「config」ディレクトリの下に「breadcrumbs.rb」ファイルが生成されます。
rails g gretel:installconfig/breadcrumbs.rb
設定ファイルを編集します。
config/breadcrumbs.rb# crumb "現在のページ(表示させるページにも記述)" do # link "ぱんくずリストでの表示名", "アクセスしたいページのパス" # parent "親要素のページ(前のページ)" crumb :pics do link "Home", root_path end crumb :advises do link "相談一覧", advises_path parent :pics end crumb :new_advise do link "相談新規投稿", new_advise_path parent :advises end crumb :show_advise do link "相談詳細", advise_path parent :advises endviewファイル
オプションの「pretext」を使い
文字を入力するとその文字が出力されます。「separator」を使い
"›"
を記入すると「 > 」 が出力されます。application.html.erb<p><%= breadcrumbs pretext: "You are here: ", separator: "›" %></p>1.
pics/index.html.erb<% breadcrumb :pics %>2.
advise/index.html.erb<% breadcrumb :advises %>このように出力されます。
3.
advises/new.html.erb<% breadcrumb :new_advise %>このように出力されます。
4.
advises/show.html.erb<% breadcrumb :show_advise, @advise %>このように出力されます。
表示されました!!
まとめ
初めてnewファイルやshowファイルにぱんくず機能を実装したので少し時間がかかりましたが
無事実装することができました!!自分がどこにいるかが把握できて便利ですね。
オプションも他にもあるようなのでまた違うのもしてみたいと思います。
ちなみに
こちらではこのように書かれています。
Forum:パンくずリストの設置場所はページの上、それとも下?グーグルのジョン・ミューラー氏にツイッターでフォロワーが質問した。
ミューラー氏はこう答えた。
どこに設置しても構わない。
個人的なアドバイスをするなら、ユーザーインターフェイス要素をページに追加するときは使いやすくすることを推奨する(そうでなければ、追加する意味がないはず)。しかしながら、使いやすいかどうかはサイトによる。そしてサイトのことをいちばんよく知っているのはあなただ。
なるほどー
では本日はこれで終わりたいと思います!!参考
virtualiment:Ruby on Railsでパンくずリストを表示するGem gretelの使い方メモ
githubから詳細が見れます。
GitHub gretelomake
押さえておきたいWeb知識:[Ruby on Rails] appディレクトリとconfigディレクトリを分かりやすく解説します!
- 投稿日:2021-01-17T12:24:20+09:00
devise とdevise token auth を共存させるポイント
routes.rbRails.application.routes.draw do # お客様 devise_for :customers, controllers: { sessions: 'customers/sessions', passwords: 'customers/passwords' } resources :companies, only: [:show, :new, :create, :index] do # お客様登録 devise_for :customers, controllers: { registrations: 'customers/registrations' } end namespace :api do scope :v1 do mount_devise_token_auth_for 'Customer', at: 'customer_auth', controllers: { registrations: 'api/v1/customers/registrations', passwords: 'api/v1/customers/passwords', sessions: 'api/v1/customers/sessions', confirmations: 'api/v1/customers/confirmations' # ログイン /api/v1/customer_auth/sign_in # パスワード変更 /api/v1/customer_auth/password # 認証メール再送信 /api/v1/customer_auth/confirmation } end end ...application_controller.rbclass ApplicationController < ActionController::Base protect_from_forgery with: :null_session, if: -> {request.format.json?} enddeviseを使ってその後に、devise token auth を導入したらActionController::Baseからの引用にしなければ行けなかった。
また、include DeviseTokenAuth::Concerns::SetUserByToken
がないと、before_action :authenticate_customer!
に対して、ヘッダーにclientとaccece-tokenを入れても、認証エラーになってしまいます。api/vi/application_controller.rbmodule Api module V1 # class ApplicationController < ActionController::API # Note: here is not ::BASE class ApplicationController < ActionController::Base include DeviseTokenAuth::Concerns::SetUserByToken protect_from_forgery with: :null_session respond_to :json end end end end
- 投稿日:2021-01-17T10:29:11+09:00
[Rails]テーブルから無作為で1つレコードが欲しい時 .sample使えた。
課題と結論
テーブルから無作為にレコードが欲しいと思ったら普通に .sample使えました。
irb(main):005:0> User.all.sample(1) => [#<User id: 5, name: 'aho'>]地味に知らなかった基礎。
参考情報
ActiveRecord::Relationとは一体なんなのか
https://doruby.jp/users/whale/entries/ActiveRecord--Relation%E3%81%A8%E3%81%AF%E4%B8%80%E4%BD%93%E3%81%AA%E3%82%93%E3%81%AA%E3%81%AE%E3%81%8B
- 投稿日:2021-01-17T09:54:37+09:00
Railsでユーザーフォロー機能を実装する(Ajax使うよ)②
何をしたか
この記事は、こちらの記事の続きです。
▼前回の記事
Railsでユーザーフォロー機能を実装する(Ajax使うよ)①Railsの課題を実施しています。
User
のフォロー機能を実装することになりました。
前回までの記事では、マイグレーションファイルの作成と、モデルファイルへのアソシエーションの定義が終わったので、今回はcontroller
とview
、そしてモデルメソッドを追加していきます。なお、実行環境は以下の通りです。
Rails 5.2.3
Ruby 2.6.0
ゴール
今回のゴールはこんな感じです。ボタンを押すとサクサクと非同期でフォロー/フォロー解除のボタンが現れます。
仕様
この機能の使用は以下の通りです。
- ユーザーは他のユーザーをフォローできる
- 同じユーザーを2回フォローはできない
- ユーザーは自分をフォローできない
データ構造
なぜこうなるのかは、前回の記事を読んでくださいね
非同期ではない実装
まずは、非同期ではない形で実装していきます。
controller
、model
ともにさらっと書いていきますので、詳しく知りたい方はこの辺の記事をご覧になると良いかもしれません。
- Railsで「いいね!」機能を作る - ②「いいね!」のcreateアクション
- Railsで「いいね!」機能を作る - ③「いいね!」を解除できるようにする
- RailsでAjaxで「いいね!」機能を実装する。
controller
controller
の記載は以下の通りです。relationships_controller.rbclass RelationshipsController < ApplicationController def create @other_user = User.find(params[:follower]) current_user.follow(@other_user) end def destroy @user = current_user.relationships.find(params[:id]).follower current_user.unfollow(params[:id]) end end
follow
、unfollow
はモデルメソッドです。後ほど解説します。view
ビューファイルの記述は以下の通りです。なお、装飾のためのクラスは省いています。なお、
user
(それぞれのユーザー)を表す変数がここに表示しているコードの外から渡っているものとします。view- if logged_in? && current_user != user - if current_user.following?(user) = button_to 'フォロー解除', relationship_path(current_user.relationships.find_by(follower: user)), method: :delete - else = button_to 'フォロー', relationships_path(follower: user)
following?
もモデルメソットです。model
user
モデルのモデルメソッドとして、follow
、unfollow
、following?
メソッドを、それぞれ定義します。class User < ApplicationRecord # 前回の記事で定義した部分 has_many :relationships, dependent: :destroy has_many :followings, through: :relationships, source: :follower has_many :passive_relationships, class_name: 'Relationship', foreign_key: 'follower_id', dependent: :destroy has_many :followers, through: :passive_relationships, source: :user # 今回追記したモデルメソッド def follow(other_user) return if self == other_user relationships.find_or_create_by!(follower: other_user) end def following?(user) followings.include?(user) end def unfollow(relathinoship_id) relationships.find(relathinoship_id).destroy! end endなお、このクラスの上方にあるのは、前回の記事で適宜した複雑なアソシエーションです。
非同期ではない通信での実装完了
ここまでで、Ajaxではないフォロー機能は完成しています。デモ用に
redirect_to
で画面を遷移させているので、若干非同期っぽくも見えますが、「フォロー」ボタンを押して画面をリロード後「フォロー解除」ボタンが現れます。Ajaxでの実装
それでは、これを非同期の通信にしていきます。こちらもさらっと書いていますので、どうしてそうなるのかが気になる方は、こちらの記事をご覧ください。
remote: trueでajaxの投稿をPOSTをするよ。
html部分
まずは、ボタン部分は
remote: true
オプションをつけて、パーシャルに切り出します。views/relationships/_follow_button.html.slim= button_to 'フォロー', relationships_path(follower: user), remote: trueviews/relationships/_unfollow_button.html.slim= button_to 'フォロー解除', relationship_path(current_user.relationships.find_by(follower: user)), method: :delete, remote: true# もともとボタンのあったビューファイル - if logged_in? && current_user != user div id="follow-button-#{user.id}" - if current_user.following?(user) = render 'relationships/unfollow_button', user: user - else = render 'relationships/follow_button', user: user
**.js.erb
ファイルを作る動的に呼び出す部分のファイルは、
**.js.erb
ファイルに書き出します。views/relationships/create.js.erb$("#follow-button-<%= @other_user.id %>").html("<%= j(render 'unfollow_button', user: @other_user) %>")views/relationships/destroy.js.erb$("#follow-button-<%= @user.id %>").html("<%= j(render 'follow_button', user: @user) %>")完成!
こちらで完成です^^Ajaxにするのはビューファイルを書き換えるだけで終わりました
シンプルー感想など
フォロー・フォロー解除機能は、データ構造8割!といった感じで、DBとモデルの設計がやたら複雑なんですね〜
しっかり読み解けてよかったです^^
- 投稿日:2021-01-17T09:53:32+09:00
Railsでユーザーフォロー機能を実装する(Ajax使うよ)①
何をしたか
Railsの課題を実施しています。
User
のフォロー機能を実装することになりました。
この機能は前に実装したことはあって、「確かあのアソシエーションが難しいやつ」ぐらいには覚えていました。たまたま、この機能の実装を人に教える機会もありそうだったので、しっかり教えられるように手順を細かく記すことにしました。
ただ、かなりの長文になってしまったので前後編に分けています。この記事ではDB設計〜アソシエーションまでの話をして、続きは下記の記事になります。
Railsでユーザーフォロー機能を実装する(Ajax使うよ)②
なお、実行環境は以下の通りです。
Rails 5.2.3
Ruby 2.6.0
ゴール
今回、作るものはユーザーのフォロー機能です。ボタンを押すと、ユーザーをフォロー、もう一度ボタンを押すと、フォロー解除できます。
また、この機能のために作成したモデルは下記の通りです。
謎すぎる形態をしていますよね
いきなり、上記のモデルに行き着くのは難しいので、ひとつひとつ分解して考えていきます。なお、以下はあくまでも「私はこう考えた」考え方ですので、人によっては他の考え方の方がしっくりくるかもしれません。
実装
分解して考える
まずは、「ユーザー」と「フォロワー」という登場人物を作った方がわかりやすいので、
User
モデルを(頭の中で)User
モデルとFollower
モデルに分解します。この中で、一番簡単そうなUserがたくさんの人をフォローしている状況から考えていきましょう。
has_many: followings, through: :relationshipsというアソシエーションを(頭の中で)仮置きします。ただし、Userモデル = Followerモデルであることは忘れないでください。
上記の関係を、マイグレーションファイルで表すとこうなります。
db/migrate/XXXXXXXX_create_relationships.rbclass CreateRelationships < ActiveRecord::Migration[5.2] def change create_table :relationships do |t| t.references :user t.references :follower, foreign_key: { to_table: :users } t.timestamps t.index [:user_id, :follower_id], unique: true end end end
followers
テーブルは実際には存在しないので、foreign_key: { to_table: :users }
で、「followerを探すときはusersテーブル(のfollower_id)を見てね」とRailsに伝えています。この辺りの実装は、↓この記事が大変参考になりました。
マイグレーションにおいて参照先テーブル名を自動で推定できないカラムを外部キーとして指定する方法
また、同じ人を2回フォローできないように
t.index [:user_id, :follow_id], unique: true
user_id
カラムとfollower_id
のカラムの組み合わせに、重複した値が入らないようにする制約を加えています。アソシエーションの記載
Usersモデル
この時、
User
モデルのアソシエーションの記述は下記のようになります。models/user.rbclass User < ApplicationRecord has_many :relationships, dependent: :destroy has_many :followings, through: :relationships, source: :follower endポイントは、以下の通りです。
has_many :followings
で、アソシエーションに別名をつけるsource: :follower
で、follower
モデルを見てねとRailsに教える若干複雑になってきましたね...
難しそうなところにはリンクも貼りましたので、ひとつづつ読み解いてみてください。ところで、
Follower
モデルなんてないのに、どうやってFollower
モデルを参照するの??という件については、次のRelationship
モデルのアソシエーションをご覧ください。Relationshipモデル
Relationship
モデルの記載内容は下記の通りです。models/relationship.rbclass Relationship < ApplicationRecord belongs_to :follower, class_name: 'User' endこのように記載することで、
Follower
モデルの参照がきたらUser
モデルを参照するようにRailsに伝えています。余談:
source
とclass_name
の違いについてところで、さっきは
source
で別のモデルを参照したのに、今度はなんでclass_name
なの?って思いませんでしたか?(私は思いました)その理由は、こちらに書いてあって、
Rails: difference between :source => ?? and :class_name => ?? in models
- source ...
has_many :****, through: :****
の時に使う- class_name ...
has_many :***
の時に使うだそうです知らなかった!!
確認
ここで、一回きちんとアソシエーションが定義できているか確かめることをお勧めします。私は、こんなふうに確かめました。
$ rails c > user = User.first > user.relationships # => [] > user.relationships.create!(follower_id: 2) # => Relationship のレコードが表示 > user.followings # => フォローしているUser(user_idが2のユーザー)のレコードが表示フォロー中のユーザーのレコードが呼び出されたので、
id:1
のユーザーはid:2
のユーザーをフォローできていると言えます。逆の関係も考える
さて、それでは今度はユーザーがたくさんのフォロワーにフォローされているという、先程どは逆の状況も考えてみたいと思います。
まず、ゴールなのですが、先程の逆の矢印を定義できれば良いです。
具体的に図に書き込んでみます。
follower
がたくさんのuser
をrelationships
を通じて持っている、こんな図が出来上がります。でも、Followerモデルは実際には存在せず、Userモデルとイコールでしたね。
そのため、主語をUserに書き換えてみます。
User
はrelationships
を通じて、followers
をたくさん持っている。
言葉としてはわかりやすいのですが、今度は、頭の中に作ったFollow
モデルが邪魔になってきました。
followers
テーブルを置いたために考えるのが難しくなってきているので、Follow
モデルとUser
モデルを一つにまとめました。だいぶ、一番初めに提示したER図に近づいてきましたね
ついでに、先程の赤い矢印も復活させてみました。
すると、今度はthrough: :relationships
の部分で、名前が重複しているのがわかります。そこで、今度は片方の名前を変えて、
user
はfollower
にフォローされている、と言う意味でpassive_relationships
と名付けました。これで、最初に提示したER図と同じになっています
アソシエーションの記載
Userモデル
では、この関係を実際にモデルに表していきます。
まず、User
モデルはこうなります。models/user.rbclass User < ApplicationRecord has_many :relationships, dependent: :destroy has_many :followings, through: :relationships, source: :follower has_many :passive_relationships, class_name: 'Relationship', foreign_key: 'follower_id', dependent: :destroy # 追記1 has_many :followers, through: :passive_relationships, source: :user # 追記2 endめっちゃ複雑になってきましたねひとつひとつ読みといていくと、まず、追記1の部分は
User
はたくさんのpassive_relationships
を持っています。- この時、参照して欲しいクラスは
Relationship
です。- 外部キーとして
follower_id
を使います。というのを表しています。
次に、追記2の部分は
User
はたくさんのfollowers
を、passive_relationships
を通じて持っています。passive_relationships
は、直前の定義によりRelationship、
クラスを参照するようになっています。複雑すぎて憤死しそうです
ワンステップずつ丁寧に書いたつもりなので、丁寧に読んでみてくださいRelarionshipモデル
最後に、
Relationship
モデルに追記した内容を紹介します。models/relationship.rbclass Relationship < ApplicationRecord belongs_to :user # 追記 belongs_to :follower, class_name: 'User' endこちらは逆にシンプルすぎて心配になるレベルですが、こちらはこれで完了です
確認
ここで、1回確認をしてみます。先程、コンソールでid:1のユーザーがid:2のユーザーをフォローすると言うデータは作りましたので、id:2のユーザーは、id:1のユーザーにフォローされているはずです。
それを、コンソールで試してみます。
$ rails c > user2 = User.second > user2.followers # => id:1のUserのレコードが表示されるuser2をフォローしているユーザーが取得できました!!成功です
to be contenued ...
これからいよいよviewやcontrollerを実装!...となっていくのですが、
ここからは次回に続きます。Ajax出てこないじゃん!と思った方、ごめんなさい。次回に出てきます。。。
▼この話の続編はこちら
Railsでユーザーフォロー機能を実装する(Ajax使うよ)②
- 投稿日:2021-01-17T07:09:58+09:00
【エラー】`cannot load such file -- mime/types/data (LoadError)`
はじめに
payjpをGemfileに記述しbundle installs後rails sをすると大量に文字が羅列され
cannot load such file -- mime/types/data (LoadError)
とういうエラーが出た時の解決したプロセスを記事にしました。
環境やエラーへの辿り着き方で、それぞれ違う解決方法が存在する思いますので、参考程度にしてください〜環境
macOS Catalina バージョン 10.15.7
Homebrew 2.7.1
rbenv 1.1.2
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19]
gem 3.2.4
Bundler version 2.1.4エラー
エラー文
cannot load such file -- mime/types/data (LoadError)
大量に文字が羅列されたエラー分をよく確認するとMIME: :Types
が既に定義されてるという文がありました。確認と考察
gem list
でローカルのgemがどうなってるか確認しました。
mime-types-data
が2バージョン入っていいデフォルトに設定されてる。
むーーこれが悪いのか??いろいろ調べてると、
default
が設定されるには、gem update --default
らいし。
そんなんことした事ないが、このコマンドを打つと、gemの最新バージョンが一度にインストールされ、かつ最新バージョンがデフォルトに設定されてしまうらしい。対応
ひとまず、アンインストールしデフォルトを解除することにしました。
まずはデフォルト解除ターミナルcd #ホームディレクトリへ移動 cd /Users/[ユーザー名]/.rbenv/versions/[バージョン]/lib/ruby/gems/[バージョン] #上記で確認したパスに移動します ls #中を確認します build_info doc gems cache extensions specifications ←この中にdefault設定が記述されています rm -rf specifications/default/ #specificationsのなかのdefaultディレクトリ削除します(これでdefaultが解除されます)
mime-types-data
のアンインストールターミナルgem uninstall mime-types-data bundle install確認します。
gem listpayjpmをGemfileに記述し
bundle install
、rails sをするとサーバーが立ち上がりました!まとめ
今回のエラーはmime-types-dataが原因でした。
本文では記述しておりませんが、調べた事を何も考えずに実行しニ次災害、三次災害が発生し、結果解決までに3日かかってしまいました。
ターミナルでのコマンドはなんの為のもので、どう動くかを理解した上で進める事をおすすめします。参考
https://qiita.com/zQmjRAb73seN5RM/items/ecb9e19ee8f3e9af6018
https://mophie-blog.com/2020/08/17/oops-i-did-gem-update-not-bundle-update-rails-no-work/
- 投稿日:2021-01-17T03:31:48+09:00
2回目以降のデプロイ
前提条件としてご自身のアプリケーションが既にデプロイされている状態とします。
まず、アプリのファイルが変更されていればGitHubでコミット〜マージまで行いましょう!
変更点をHerokuに反映させる
ターミナルに以下のコマンドを打ちましょう
ターミナル% git add . % git commit -m "変更した内容がわかるような説明をここにいれる、日本語でもおk"
リポジトリのプッシュ
ターミナル% git push heroku master
マイグレーションの実行
ターミナル% heroku run rake db:migrate
お疲れ様です、これでエラーが出ていなければ完了です!
もしエラーが出たときの対処、以下のコマンドを実行してヒントを得る
ターミナル% heroku logs --tail --app <<アプリケーション名>>最後まで見ていただいてありがとうございます!誰かの参考になれば幸いです
- 投稿日:2021-01-17T03:20:39+09:00
デプロイする方法
デプロイの方法を自分の備忘録として残しておきます。
GitHubにご自身のアプリがmasterにマージされた状態と言う前提条件で進めます。
まずHerokuと言うサービスを使います
Herokuの新規登録ページ
https://signup.heroku.com/loginここで必要な項目を入力したらメールが届くのでそこに入って以下の入力をしましょう!
※パスワードは英数・数字・記号の3つを含み8文字以上を入力しましょう。なんかこんなやつがでてきたら登録完了⬇︎
下のような画面が出てきたら画面下の「Accept」をクリックしてください⬇︎
Herokuのトップ画面に行けたらおk⬇︎
Herokuの注意点
Herokuは基本的に無料で利用が可能ですが、使用するデータベースの設定がデフォルトでPostgreSQLというRDBMSになっています。
HerokuでMySQLを使用する為にはクレジットカードの登録が必須となっているので、アカウント管理ページのBillingからカード情報を登録しましょう。
クレカの登録
私はMySQLを使いたのでクレカを登録します(別にしない人は飛ばしてください)
以下のスクショの手順で進めましょう
クレジットカードの情報を入力
以下のような画面になれば登録完了!
Heroku CLIのインストール
インストールする前にHerokuにアップしたいディレクトリに移動してください。
今回はprojectディレクトリをアップする手順で説明しますターミナル% brew tap heroku/brew && brew install heroku
Herokuのバージョン確認コマンド↓
% heroku --version heroku/7.40.0 darwin-x64 node-v12.16.2 # こんなやつが出てきたらおk# Herokuへログインするためのコマンド % heroku login --interactive => Enter your Heroku credentials. # メールアドレスを入力し、エンターキーを押す => Email: # パスワードを入力して、エンターキーを押す => Password:Heroku createコマンド
% heroku create アプリ名ちゃんとできたか確認のコマンド⬇︎
% git config --list | grep herokufatal: not in a git directory以外が表示されていれば 次に進みましょう
ClearDBアドオンの追加
ClearDBアドオンとは、MySQLを使うためのツールです。ClearDBというデータベースサービスが提供しているアドオンで、これを追加することにより、HerokuでMySQLを使用できるようになります。
% heroku addons:add cleardb設定の変更
アドオンを追加したけどまだその設定ができていないので以下のコマンドを実行
% heroku_cleardb=`heroku config:get CLEARDB_DATABASE_URL`これでClearDBデータベースのURLを変数heroku_cleardbに格納できました。
% heroku config:set DATABASE_URL=mysql2${heroku_cleardb:5}これでデータベースのURLを再設定できました。
AjaxAppではmysql2というGemを使用しているので、DATABASE_URLの冒頭がmysql2://に変更されていることも確認しておきましょう。credentials.yml.encの中身の確認
以下のコマンドを実行して中身を確認
ターミナル% EDITOR="vi" bin/rails credentials:edit
以下のような画面になったらおk
確認したら「escキー」→「:」→「q」と入力し、「enterキー」を押して credentials.yml.encを閉じる環境変数の設定
heroku configコマンド
Heroku上で環境変数の参照・追加・削除等をする場合に用います。環境変数の追加であればheroku config:set 環境変数名="値"と実行します。そうすることによって、Heroku上で環境変数を追加できます。
以下のコマンドをターミナルで実行
ターミナル% heroku config:set RAILS_MASTER_KEY=`cat config/master.key` % heroku config
以下のような感じになっていたらおk
アプリケーションをプッシュ
以下のコマンド2つを実行してアプリケーションをプッシュ
ターミナル% heroku stack:set heroku-18 -a アプリケーション名
ターミナル% git push heroku master
プッシュが成功したら以下のコマンドでマイグレーションを実行
ターミナル% heroku run rails db:migrate
公開の確認
以下のコマンドでいろいろな設定を確認することができる
ターミナル% heroku apps:info
上記のコマンドで実行したあと、その項目の中にWeb URL: https://....アプリのURL
があるのでそれがWEBで公開されているURLになる
もしそのURLんびアクセスしてエラーが出たら(汗
以下のコマンドを実行してヒントを得る
ターミナル% heroku logs --tail --app アプリ名
「heroku logs アプリ名」のコマンドでも確認できるが、「--tail」オプションを使うことによって最新の10行のログのみを表示してくれるようにする
解説なんて不要だぁ!な、せっかちさん用コマンドのみのまとめ
ログインコマンド
ターミナル% heroku login --interactive
Heroku上で作成
ターミナル% heroku create アプリ名
ClearDBアドオンの追加
ターミナル% heroku addons:add cleardb
設定の変更
ターミナル% heroku_cleardb=`heroku config:get CLEARDB_DATABASE_URL`
データベースの再設定
ターミナル% heroku config:set DATABASE_URL=mysql2${heroku_cleardb:5}中身の確認、確認したら「escキー」→「:」→「q」と入力し、「enterキー」
ターミナル% EDITOR="vi" bin/rails credentials:edit
環境変数の設定
ターミナル% heroku config:set RAILS_MASTER_KEY=`cat config/master.key`
アプリのプッシュ
ターミナル% heroku stack:set heroku-18 -a アプリケーション名
ターミナル% git push heroku master
マイグレーションの実行
ターミナル% heroku run rails db:migrate
設定の確認
ターミナル% heroku apps:info
最後まで見ていただいてありがとうございます!
誰かのお役に立てれば幸いです!
- 投稿日:2021-01-17T02:13:44+09:00
【Rails + Webpacker】assetsの画像を使いたい! Vue.jsで画像を表示できるまで
RailsとWebpackerで開発している時に、画像どうやって読み込むのかなと思って調べてみた記録です。
WebpackerのREADMEをのぞいてみる
WebpackerのREADMEの Paths > resolved を参照してみると、assetsをもつアプリとimagesを共有したいときは、
webpacker.yml
でresolved_paths
と書いて読み込める、とあります。今回はこれに習って実装しています。config/webpacker.ymlresolved_paths: ['app/assets']ただし、コンパイルの速度に影響アリ
以下にあるように…
Please be careful when adding paths here otherwise it will make the compilation slow, consider adding specific paths instead of whole parent directory if you just need to reference one or two modules
でかいディレクトリ単位で読み込むとコンパイルが遅くなる、ということのようです。表示速度を気にする場合は注意したいです。
実装例
webpacker.ymlにpathをかく
上でみたように
webpacker.yml
に記述していきます。今回はassets/images
配下しか必要としていないので、先ほどの注意点も考慮してimagesまでpathを指定してみました。config/webpacker.ymlresolved_paths: ['app/assets/images']Vue.jsで使うには
今回は、Vue.jsのコンポーネントで読み込みたかったので、一緒に書いておきます。
sample.vue<template> <div> <!-- imgタグでsrcに"~"をつけてimportしたファイルを指定する --> <img src="~logo.svg" /> </div> </template> <script> import 'logo.svg'; // ここでimport </script>こうやって書いてみるととってもシンプルですね。
以上、少しでも参考になれば嬉しいです。
- 投稿日:2021-01-17T02:06:34+09:00
Heroku MySQLにクライアントから接続したい
やりたいこと
HerokuのアプリにアタッチしているMySQLへ、MySQL Workbenchなどのクライアントから接続したい
方法
情報を取得する
アプリ名を取得
herokuにデプロイしているアプリケーションの名前を取得します。
この場合はhogehogeというアプリをデプロイしていることとします。
herokuのアプリ名は、ど忘れしてたり、被らないように特殊にしている場合があるのでcliで取得してコピーしましょう。$ heroku list hogehoge fugafuga
アプリの情報を取得
アプリケーションhogehogeの情報を取得します。
アプリケーションに設定されている環境変数が出力されます。
Heroku上にあるアプリケーションにMySQLをアタッチしている多くの場合において、DATABASE_URLは以下のようになっていると思います。$ heroku config -a hogehoge === hogehoge Config Vars CLEARDB_DATABASE_URL: mysql://fizz:buzz@foo.cleardb.com/heroku_barbarbar?reconnect=true DATABASE_URL: mysql://fizz:buzz@foo.cleardb.com/heroku_barbarbar?reconnect=true 以下略MySQLの接続情報を抜粋する
環境変数の値から接続情報のすべてを読み取ることができます。
// 元が以下だとしたら mysql://fizz:buzz@foo.cleardb.com/heroku_barbarbar?reconnect=true // このように読み替える mysql://username:password@host/schema?reconnect=true // つまり以下のようになる MySQLホスト => foo.cleardb.com DB Schema => heroku_barbarbar Username => fizz Password => buzz以上になります。
あとは使っているクライアントに情報を入れて接続してあげるだけです。最後に
HerokuってデフォルトのデータベースがPostgreSQLなんですが、
MySQLに変えることもできます。
僕の場合には仕事、プライベート、開発環境、本番環境問わず、MySQLを使うことが多いため、PostgresからMySQLへ変えてみました。変え方については検索すればいくらでもヒットするのでそちらを。
ちなみにクライアントからアクセスして使ってみた感じだと速度が遅めです。まぁ無料なのでそこは仕方ないですね。
- 投稿日:2021-01-17T00:45:18+09:00
開発環境にRailsをインストール・新規アプリ作成
引用先
RailsチュートリアルRailsをインストール
Rubyドキュメントをインストールしないよう.gemrcファイルを設定
$ echo "gem: --no-document" >> ~/.gemrcRailsをインストールするには、gemコマンドを使います。
Rubyドキュメントのインストールで無駄な時間を使わないよう、コマンドに設定を追加しています。バージョンを指定してRailsをインストール
$ gem install rails -v 6.0.3バージョン6.0.3でインストール
$ rails -v # Rails 6.0.3バージョンの確認(指定してインストールした場合は合っているか確認)
JavaScriptソフトウェアの依存関係を管理するYarnをインストール
$ source <(curl -sL https://cdn.learnenough.com/yarn_install)※警告メッセージがでた場合
======================================== Your Yarn packages are out of date! Please run `yarn install --check-files` to update. ========================================$ yarn install --check-files上記を実行でOK
新規アプリ作成
Railsプロジェクト用のenvironmentディレクトリを作る
$ cd # プロジェクトのホームディレクトリに移動 $ mkdir environment # environmentディレクトリを作成 $ cd environment/ # 作成したenvironmentディレクトリに移動rails newを実行
$ rails _6.0.3_ new <アプリ名>各フォルダの役割
ディレクトリ 用途 app/ モデル、ビュー、コントローラ、ヘルパーなどを含む主要なアプリケーションコード app/assets アプリケーションで使うCSS(Cascading Style Sheet)、JavaScriptファイル、画像などのアセット bin/ バイナリ実行可能ファイル config/ アプリケーションの設定 db/ データベース関連のファイル doc/ マニュアルなど、アプリケーションのドキュメント lib/ ライブラリやモジュール置き場 log/ アプリケーションのログファイル public/ エラーページなど、一般(Webブラウザなど)に直接公開するデータ bin/rails コード生成、コンソールの起動、ローカルのWebサーバーの立ち上げなどで使うRailsスクリプト test/ アプリケーションのテスト tmp/ 一時ファイル README.md アプリケーションの簡単な説明 Gemfile このアプリケーションに必要なGemの定義ファイル Gemfile.lock アプリケーションで使われるgemのバージョンを確認するためのリスト config.ru Rackミドルウェア用の設定ファイル .gitignore Gitに取り込みたくないファイルを指定するためのパターン Bundlerを実行
bundlerとは、gemのバージョンやgemの依存関係を管理してくれるgem。
bundlerを使うことで、複数人での開発やgemのバージョンが上がってもエラーを起こさずに開発できます。Gemfileに使用するgemを記入する
各開発環境によって使用するgemは異なるため必要なgemを記入する。
(例 bootsnap,byebug等)bundleをインストール
$ cd hello_app/ $ bundle installエラーで[bundle update]と出たら、bundle updateを先に実行
ここまでが環境構築となります。
- 投稿日:2021-01-17T00:43:22+09:00
【Ruby on Rails】EC2でwheneverを使ってcrontabを設定する時のハマったことの解決
wheneverというのはRuby on Railsのgemであり、crontabを設定する時によく使われています。
使い方
使い方はGithubホームページに詳しく記載されていますが、主に使うのは下記になります。
Gemfileに追加
Gemfilegem 'whenever', require: falseインストール
bundle exec wheneverize .schedule.rbファイルの内容を確認する
whenever開発環境でcrontabを更新する
whenever --update-crontab --set environment='development'Capistranoに入れる
config/deploy.rbset :whenever_roles, -> { :app }Capfilerequire 'whenever/capistrano'ハマったことなどの解決
EC2では動かない
EC2にデプロイの後、crontabが動かず、ログ確認したらBundleバージョンが間違いなどの問題
job_typeを以下に設定すれば良い
config/schedule.rbset :output, environment == 'development' ? 'log/crontab.log' : '/deploy/apps/<アプリ名/shared/log/crontab.log' job_type :rake, 'export PATH="$HOME/.rbenv/bin:$PATH"; eval "$(rbenv init -)"; cd :path && RAILS_ENV=:environment bundle exec rake :task :output'時間通りに動かない
タイムゾーンが間違い可能性が高いです。
タイムゾーン設定方法は:
config/schedule.rbrequire 'active_support/core_ext/time' def local(time) Time.zone = 'Asia/Tokyo' Time.zone.parse(time).localtime($system_utc_offset) end every 1.day, at: local('6:00 am') do # 日本時間毎朝6時に実行 rake '<task>' endcrontabのログにExecJS::RuntimeUnavailable エラーが出たとき
Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes. (ExecJS::RuntimeUnavailable)Gemfileに
mini_racer
を追加すればいいです。therubyracer
でも大丈夫ですが、Macにはインストールが難しいのでmini_racer
を使います。
- 投稿日:2021-01-17T00:30:50+09:00
ActiveHashの導入目的とアプリへの実装までの簡単な流れ
ActiveHashとは
都道府県名などの変更されないデータをモデルファイル内に直接記述することで、データベースへ保存せずにデータを取り扱うことができるgemです。
ActiveHashを導入する目的
ユーザー情報のような編集されることがあるデータと違って、都道府県名などは変更されないデータなので、データベースにわざわざ保存する必要がありません。
かといってビューに直接都道府県名のプルダウンメニューを作ってしまうと可読性が下がってしまいます。
そこでActiveHashを使ってモデルからデータを呼び出すという方法を採ることでコードの管理がしやすくなります。
また、ActiveHashを導入することで以下のようなプルダウンメニューを作成するときに大いに役立ちます。
プルダウンメニューの実装
住んでいる都道府県を投稿するアプリを使って説明します。
ターミナルrails _6.0.0_ new activehash_app -d mysql rails db:createモデル、コントローラー、ビューを用意します。
モデルを作成
ターミナルrails g model address上記コマンドで生成されたマイグレーションファイルに下記の通り、
name
カラムとprefecture_id
カラムを記述してマイグレートします。
prefecture_id
カラムには、後でActiveHash gemで導入するプルダウンメニューの情報が入ります。2021XXXXXXXXXX_create_addresses.rbclass CreateAddresses < ActiveRecord::Migration[6.0] def change create_table :addresses do |t| t.string :name, null: false t.integer :prefecture_id, null: false t.timestamps end end endターミナルrails db:migrateコントローラーとビューを作成
下記のコマンドでコントローラーに加えて、一覧表示と新規投稿のビューをまとめて作成します。
ターミナルrails g controller addresses index newコントローラーとビュー(
index
とnew
)を以下のように記述します。app/controllers/addresses_controller.rbclass AddressesController < ApplicationController def index @addresses = Address.order("created_at DESC") end def new @address = Address.new end def create @address = Address.new(address_params) if @address.valid? @address.save return redirect_to root_path else render "new" end end private def address_params params.require(:address).permit(:name, :prefecture_id) end endapp/views/addresses/index.html.erb<h1>あなたの住んでいる都道府県は?</h1> <%= link_to "投稿する", new_address_path %> <div> <ul> <% if @addresses %> <% @addresses.each do |address| %> <li> <%= address.name %> <%= address.prefecture.name %> </li> <% end %> <% end %> </ul> </div>app/views/addresses/new.html.erb<%= form_with model: @address, url:addresses_path, local: true do |f| %> <div class="article-box"> あなたの名前と住んでいる都道府県を投稿する <div> <p><%= f.text_area :name, placeholder:"あなたの名前" %></p> <p><%= f.collection_select(:prefecture_id, Prefecture.all, :id, :name, {}, {class:"genre-select"}) %></p> <%= f.submit "投稿する" ,class:"btn" %> </div> </div> <%= link_to "戻る", root_path %> <% end %>ActiveHashの導入
いよいよActiveHashを導入します。
Gemfile
の一番下に下記の記述をして、ターミナルでbundle install
します。Gemfilegem 'active_hash'ターミナルbundle install都道府県のリストを用意するため、prefectureモデルを作成します。
ここで、いつものrails g model :モデル名
コマンドに--skip-migration
というオプションを付けます。
--skip-migration
はマイグレーションファイルの作成をスキップしてくれるオプションです。都道府県に関する情報はデータベースに保存しないためです。ターミナルrails g model prefecture --skip-migration作成した
prefecture.rb
に、以下のように記述します。app/models/prefecture.rbclass Prefecture < ActiveHash::Base self.data = [ {id: 0, name: '--'}, {id: 1, name: '北海道'}, {id: 2, name: '青森県'}, {id: 3, name: '岩手県'}, {id: 4, name: '宮城県'}, {id: 5, name: '秋田県'}, {id: 6, name: '山形県'}, {id: 7, name: '福島県'}, {id: 8, name: '茨城県'}, {id: 9, name: '栃木県'}, {id: 10, name: '群馬県'}, {id: 11, name: '埼玉県'}, {id: 12, name: '千葉県'}, {id: 13, name: '東京都'}, {id: 14, name: '神奈川県'}, {id: 15, name: '新潟県'}, {id: 16, name: '富山県'}, {id: 17, name: '石川県'}, {id: 18, name: '福井県'}, {id: 19, name: '山梨県'}, {id: 20, name: '長野県'}, {id: 21, name: '岐阜県'}, {id: 22, name: '静岡県'}, {id: 23, name: '愛知県'}, {id: 24, name: '三重県'}, {id: 25, name: '滋賀県'}, {id: 26, name: '京都府'}, {id: 27, name: '大阪府'}, {id: 28, name: '兵庫県'}, {id: 29, name: '奈良県'}, {id: 30, name: '和歌山県'}, {id: 31, name: '鳥取県'}, {id: 32, name: '島根県'}, {id: 33, name: '岡山県'}, {id: 34, name: '広島県'}, {id: 35, name: '山口県'}, {id: 36, name: '徳島県'}, {id: 37, name: '香川県'}, {id: 38, name: '愛媛県'}, {id: 39, name: '高知県'}, {id: 40, name: '福岡県'}, {id: 41, name: '佐賀県'}, {id: 42, name: '長崎県'}, {id: 43, name: '熊本県'}, {id: 44, name: '大分県'}, {id: 45, name: '宮崎県'}, {id: 46, name: '鹿児島県'}, {id: 47, name: '沖縄県'} ] include ActiveHash::Associations #ActiveHashに定義されているモジュールを読み込み has_many :address #addressモデルとのアソシエーションを定義 end都道府県のデータを配列にハッシュ形式で入れます。
また、include ActiveHash::Associations
でActiveHashに定義されているモジュールを読み込み、has_many
を記述してAddressモデルとのアソシエーションを定義しています。
ActiveHashのモジュールについては公式GitHubのREADMEとライブラリを参照してください。
address.rb
にも同様に、モジュールを読み込み、belongs_to
でPrefectureモデルとのアソシエーションを定義します。app/models/address.rbclass Address < ApplicationRecord extend ActiveHash::Associations::ActiveRecordExtensions #Activehashに定義されているモジュールを読み込み belongs_to :prefecture #prefectureモデルとのアソシエーションを定義 end上記のアソシエーションを定義することで、先ほど作成した
index.html.erb
でPrefectureモデルに格納した都道府県名にアクセスできるようになりました。app/views/addresses/index.html.erb(再掲)<h1>あなたの住んでいる都道府県は?</h1> <%= link_to "投稿する", new_address_path %> <div> <ul> <% if @addresses %> <% @addresses.each do |address| %> <li> <%= address.name %> <%= address.prefecture.name %><%# アソシエーション定義によってprefecure.rbに格納している都道府県名にアクセスできる %> </li> <% end %> <% end %> </ul> </div>参考資料