20210117のRailsに関する記事は22件です。

ページネーション機能(kaminari)

はじめに

現在ポートフォリオ制作中の初学者です。
kaminariを導入してページネーション機能を実装したので備忘録です。

1. gemをインストール

Gemfile
gem 'kaminari'
ターミナル
% bundle install

2. コントローラーで定義

events_controller.rb
def index
  @events = Event.page(params[:page]).per(10)
end

pageとperいうメソッドがkaminariで定義されたメソッドです。
perメソッドの引数にどれだけのレコードが表示されたらページを増やすかを指定できます。

3. ビューファイルを編集

events/index.html.erb
<%= paginate @events %>

表示したいビューファイルに記述。

以上です!

ページネーションの見た目を変える

kaminariで表示させるページネーションはビューの中でcssを当てる事は出来ない。
ので以下方法。

ターミナル
% rails g kaminari:views default

app/viewsフォルダにkaminariを追加。
フォルダの中にページネーションの部分のhtmlが記述されているので、そこで変更する。

cssのフレームワークのデザインを適用させる場合

bootstrapなどのcssのフレームワークを使っている場合、表示やデザインが崩れる場合があるので
defaultの部分をそれぞれのフレームワークの名前に指定する。
bootstrap4を使っている場合は下記のコマンド。

ターミナル
% rails g kaminari:views bootstrap4

このコマンドを実行し、ビューファイルを作成すると何も編集しなくてもそれぞれのフレームワークのスタイルに最適化される。

kaminariを日本語化する

デフォルトで英語表記になっているため、日本語表記に変更するためには
config/localesフォルダにkaminari_ja.ymlというファイルを作成し、下記のようなコードを書く。

config/locales/kaminari_ja.yml
ja:
  views:
    pagination:
      first: "&laquo; 最初"
      last: "最後 &raquo;"
      previous: "&lsaquo; 前"
      next: " &rsaquo;"
      truncate: "..."

参考

https://pikawaka.com/rails/kaminari

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

汎用性◯『戻る』ボタン

はじめに

どんなページでも使える「戻るボタン」のコードを残しておこうと思い投稿します。

汎用的戻るボタン

  • Rails
  • erb拡張子
  • クラス名はお好みで
  • CSSでクラス名を指定すれば、スタイルを適用可能
<%= link_to '戻る', :back, class:"back-btn" %>

:backの部分が、戻る機能に起因しています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[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.yml
command: bash -c "rm -f tmp/pids/server.pid ; bundle exec rails s -p 3000 -b 0.0.0.0"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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が一通りできる。

画面の操作も可能なので、何をやっていけばいいか?は結構わかりやすいかも。

次からは、こんなサイトを作れるように色々やっていこうかな。
ハロワ求人検索
ハロワまとめサイト
ハローワーク検索サイト

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初心者向け! 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形式だったため、この辺は詳しくないので。。。)

CircleCI + Capistrano + AWS(EC2) + Railsで自動デプロイしてみた

ということなので、ターミナルの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にを開きます。(右上の歯車アイコンをクリック)
171a000a3a3105940bd7d90856926ca8.png

すると以下のように設定画面に遷移するので、メニューバーのSSH Keysを選択して、鍵を設定します。
27f8250132f8c8f66b26738a49dd32dd.png

ページが切り替わったら、スクロールして以下のAdd SSH Keyをクリックしましょう。
ssh.png

クリックすると以下のようになるので、HostnamePrivate Keyを入力して、Add SSH Keyをクリックします。

HostnameにはElasticIPを入れてもいいですが、筆者の場合は独自ドメインを取得していたためwww.myapp.comのような形で記入しました。

続いてPrivate Keyには、先ほどコピーした暗号を貼り付けます。
sshsh.png

しばらくすると、元の画面に戻ると思います。すると、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です。
install.png

3)githubのmasterブランチにmergeもしくはpushしたときにCapistranoによるデプロイを行う

ここからが実際に、CIツールによるCapistrano自動デプロイの実装です。

まずこちらが成功したコードです。

.circleci/config.yml
version: 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があった場合に行うように設定しています。

詳しい説明は下記の記事や、記事内で参考にしていた文献に書いてありますので、そちらの方も合わせて読むとより理解しやすいと思います。

【circleCI】rails5.2/Capistrano/CICD環境によるAWSへの自動デプロイ

結構、苦労しましたが、なんとか実装できました。
皆さんも頑張ってください。

参考文献

公式ドキュメント

CircleCI + Capistrano + AWS(EC2) + Railsで自動デプロイしてみた

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

InfiniteScrollとkaminariで無限スクロールを作る

完成系

2021-01-17 (2).png

開発環境

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__dot
talks/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を使って頑張ってください。

参考文献

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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.0Ruby on Rails 6.1.1 の環境構築方法を説明していきます。

環境

  • macOS (Windowsには対応していません)
  • Terminalはbashを使用しています
    • zsh の場合は一部動作しない箇所があります

Homebrewをインストール

ソフトウェアの導入を簡単にするため、macOS用のパッケージ管理システムであるHomebrewをインストールします。

次のリンク先からHomebrewをインストールします。

Homebrew

リンク先にアクセスすると次のページが表示されます。

image

「インストール」の見出しの下にあるスクリプトの行を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を通す」とは、コマンドの実行ファイルの場所を確認するために指定することです。

参考:PATHを通すとは?(Mac OS X)

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
- RubyGems

それでは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」をインストールします。

参考:railsの全バージョン履歴

次のコマンドを入力します。

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の教材を一部修正したものです。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

データベースとモデルの関係性(基礎)

データベースに関連するファイルについて

目的:エラー解決のためには、モデルファイルとマイグレーションファイルの役割の違いをしっかりと理解しないといけないと思いこの記事を書きました。

現在:ポートフォリオ作成最終段階ですが、理解できてないことがまだまだたくさんあり、基礎理解が足りていないことに気付き、基礎を固めながら仕組みから理解しているという状況です。

モデルファイルの役割

データベースへのアクセス権限を示すためのファイルです。
記述されているモデルとアソシエーション(関連付け)は、モデル通しのデータベースへのアクセス権限を示しているということになる。

なぜ、このデータは取り出せないのか?を理解するためには、データーベースへのアクセス権限の記述されている、モデルファイルを見ると分かる。そして、理解への第一歩になる。

マイグレーションファイルの役割

データの内容を保管するために必要な情報を記述しているファイルです。
データを受け渡しの際は、ファイルに記述されているテーブル名(クラス)・カラム名を指定します。

なぜ、テーブル名(クラス)を指定するのか?

  • カラムの条件に合わせた情報を格納したい場合、格納しているデータを取り出す際には、クラスを指定してから、カラム名を指定しなければならない。
    日常生活に置き換えてみると、「〇〇クラスの山田さん」と言わずに、「全体の前で山田さんと叫んでいる」ような状況になってしまうからです。  

まとめ

両方を合わせて理解する

データベースからのデータの受け取りの仕組みの基礎理解ができるようになる。

  • モデルファイル:使用したいデータ同士でデータベースの権限を持っているのか?
  • マイグレーションファイル:データベースに保管しているテーブルは、どの情報を保持しているのか

関連性を持っていなモデルとモデル

  • データベース間のやりとりはできないためリレーションを作成する必要がある。
  • データをそれぞれ取り出し、インスタンス変数を作成する必要がある。
ついでに

MVCのフェーズ理解

  • model:データを取得、データを保管、データを取得、データを渡す
  • controller:view・modelから情報を取得、view・modelが取得したい情報を渡す、view・modelが取得したい情報を受け取り渡す
  • view:modelの情報をcontrollerから取得
アウトプットを公開することのメリット(感想)

自分の理解は本当にあっているのか?と何度も思いながら書くことで、知識定着ができました。
また、誰かの役に立つ記事になったのか分かりませんが、ブログで公開するアウトプットをすることで、深く理解でき、伝える力のトレーニングをすることもできました。
読んでくださった方、ありがとうございました。
間違いがありましたらご遠慮なくコメントの方よろしくお願いします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]ぱんくずリスト機能について

はじめに

今度はぱんくず機能を実装復習しましたのでまたすぐ実装できるように

記していきたいと思います。

実装していきます。:fire::fire:

ぱんくず機能とは

現在どこのページにいるのかを視覚的にわかりやすくした表示できる機能ことです。

物語の「ヘンゼルとグレーテル」のなかで、ヘンゼルとグレーテルの二人が森の中で道に迷わないように歩きながら来た道の目印にぱんくずを落としていったことから"ぱんくず機能"で、gemの名前が「gretel」なのだそうです。

可愛いですね :bread:

ちなみに、ヘンゼルは男の子の方でグレーテルは女の子です。:couple:

[gem gretel] 詳細

実装

「gretel」というgemを「Gemfile」に記述し

Gemfile
gem 'gretel'

インストールします。

bundle install

こちらを入力すると「config」ディレクトリの下に「breadcrumbs.rb」ファイルが生成されます。

rails g gretel:install

config/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
end

viewファイル

オプションの「pretext」を使い
文字を入力するとその文字が出力されます。

「separator」を使い
"&rsaquo;" を記入すると「 > 」 が出力されます。

application.html.erb
<p><%= breadcrumbs pretext: "You are here: ",
                                      separator: "&rsaquo;" %></p>

1.

pics/index.html.erb
<% breadcrumb :pics %>

2.

advise/index.html.erb
<% breadcrumb :advises %>

このように出力されます。

スクリーンショット 2021-01-17 11.24.09.png

3.

advises/new.html.erb
<% breadcrumb :new_advise %>

このように出力されます。

スクリーンショット 2021-01-17 11.23.24.png

4.

advises/show.html.erb
<% breadcrumb :show_advise, @advise %>

このように出力されます。

スクリーンショット 2021-01-17 11.22.50.png

表示されました!!:sparkles:

まとめ

初めてnewファイルやshowファイルにぱんくず機能を実装したので少し時間がかかりましたが
無事実装することができました!!

自分がどこにいるかが把握できて便利ですね。

オプションも他にもあるようなのでまた違うのもしてみたいと思います。

ちなみに

こちらではこのように書かれています。
Forum:パンくずリストの設置場所はページの上、それとも下?

グーグルのジョン・ミューラー氏にツイッターでフォロワーが質問した。

ミューラー氏はこう答えた。

どこに設置しても構わない。

個人的なアドバイスをするなら、ユーザーインターフェイス要素をページに追加するときは使いやすくすることを推奨する(そうでなければ、追加する意味がないはず)。しかしながら、使いやすいかどうかはサイトによる。そしてサイトのことをいちばんよく知っているのはあなただ。

なるほどー
では本日はこれで終わりたいと思います!!

参考

DoRuby:gretelでパンくずリストを作成

virtualiment:Ruby on Railsでパンくずリストを表示するGem gretelの使い方メモ

githubから詳細が見れます。
GitHub gretel

omake:relaxed:

押さえておきたいWeb知識:[Ruby on Rails] appディレクトリとconfigディレクトリを分かりやすく解説します!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

devise とdevise token auth を共存させるポイント

routes.rb
Rails.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.rb
class ApplicationController < ActionController::Base
    protect_from_forgery with: :null_session, if: -> {request.format.json?}
end   

deviseを使ってその後に、devise token auth を導入したらActionController::Baseからの引用にしなければ行けなかった。
また、include DeviseTokenAuth::Concerns::SetUserByTokenがないと、before_action :authenticate_customer!に対して、ヘッダーにclientとaccece-tokenを入れても、認証エラーになってしまいます。

api/vi/application_controller.rb
module 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 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsでユーザーフォロー機能を実装する(Ajax使うよ)②

何をしたか

この記事は、こちらの記事の続きです。

▼前回の記事
Railsでユーザーフォロー機能を実装する(Ajax使うよ)①

Railsの課題を実施しています。Userのフォロー機能を実装することになりました。
前回までの記事では、マイグレーションファイルの作成と、モデルファイルへのアソシエーションの定義が終わったので、今回はcontrollerview、そしてモデルメソッドを追加していきます。

なお、実行環境は以下の通りです。

  • Rails 5.2.3
  • Ruby 2.6.0

ゴール

今回のゴールはこんな感じです。ボタンを押すとサクサクと非同期でフォロー/フォロー解除のボタンが現れます。

Image from Gyazo

仕様

この機能の使用は以下の通りです。

  • ユーザーは他のユーザーをフォローできる
  • 同じユーザーを2回フォローはできない
  • ユーザーは自分をフォローできない

データ構造

また、DBの設計は下記の通りです。
Image from Gyazo

なぜこうなるのかは、前回の記事を読んでくださいね:relaxed:

非同期ではない実装

まずは、非同期ではない形で実装していきます。
controllermodelともにさらっと書いていきますので、詳しく知りたい方はこの辺の記事をご覧になると良いかもしれません。

controller

controllerの記載は以下の通りです。

relationships_controller.rb
class 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

followunfollowはモデルメソッドです。後ほど解説します。

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モデルのモデルメソッドとして、followunfollowfollowing?メソッドを、それぞれ定義します。

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で画面を遷移させているので、若干非同期っぽくも見えますが、「フォロー」ボタンを押して画面をリロード後「フォロー解除」ボタンが現れます。

Image from Gyazo

Ajaxでの実装

それでは、これを非同期の通信にしていきます。こちらもさらっと書いていますので、どうしてそうなるのかが気になる方は、こちらの記事をご覧ください。

remote: trueでajaxの投稿をPOSTをするよ。

html部分

まずは、ボタン部分はremote: trueオプションをつけて、パーシャルに切り出します。

views/relationships/_follow_button.html.slim
= button_to 'フォロー', relationships_path(follower: user), remote: true
views/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にするのはビューファイルを書き換えるだけで終わりました:relaxed:
シンプルー:sparkles:

Image from Gyazo

感想など

フォロー・フォロー解除機能は、データ構造8割!といった感じで、DBとモデルの設計がやたら複雑なんですね〜
しっかり読み解けてよかったです^^

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsでユーザーフォロー機能を実装する(Ajax使うよ)①

何をしたか

Railsの課題を実施しています。Userのフォロー機能を実装することになりました。
この機能は前に実装したことはあって、「確かあのアソシエーションが難しいやつ」ぐらいには覚えていました。

たまたま、この機能の実装を人に教える機会もありそうだったので、しっかり教えられるように手順を細かく記すことにしました。

ただ、かなりの長文になってしまったので前後編に分けています。この記事ではDB設計〜アソシエーションまでの話をして、続きは下記の記事になります。

Railsでユーザーフォロー機能を実装する(Ajax使うよ)②

なお、実行環境は以下の通りです。

  • Rails 5.2.3
  • Ruby 2.6.0

ゴール

今回、作るものはユーザーのフォロー機能です。ボタンを押すと、ユーザーをフォロー、もう一度ボタンを押すと、フォロー解除できます。

Image from Gyazo

また、この機能のために作成したモデルは下記の通りです。

Image from Gyazo

謎すぎる形態をしていますよね:sweat_smile:
いきなり、上記のモデルに行き着くのは難しいので、ひとつひとつ分解して考えていきます。

なお、以下はあくまでも「私はこう考えた」考え方ですので、人によっては他の考え方の方がしっくりくるかもしれません。

実装

分解して考える

まずは、「ユーザー」と「フォロワー」という登場人物を作った方がわかりやすいので、
Userモデルを(頭の中で)UserモデルとFollowerモデルに分解します。

Image from Gyazo

この中で、一番簡単そうなUserがたくさんの人をフォローしている状況から考えていきましょう。

Image from Gyazo
この場合、Userモデルに対し

has_many: followings, through: :relationships

というアソシエーションを(頭の中で)仮置きします。ただし、Userモデル = Followerモデルであることは忘れないでください。

上記の関係を、マイグレーションファイルで表すとこうなります。

db/migrate/XXXXXXXX_create_relationships.rb
class 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.rb
class User < ApplicationRecord
  has_many :relationships, dependent: :destroy
  has_many :followings, through: :relationships, source: :follower
end

ポイントは、以下の通りです。

若干複雑になってきましたね...:frowning2:
難しそうなところにはリンクも貼りましたので、ひとつづつ読み解いてみてください。

ところで、Followerモデルなんてないのに、どうやってFollowerモデルを参照するの??という件については、次のRelationshipモデルのアソシエーションをご覧ください。

Relationshipモデル

Relationshipモデルの記載内容は下記の通りです。

models/relationship.rb
class Relationship < ApplicationRecord
  belongs_to :follower, class_name: 'User'
end

このように記載することで、Followerモデルの参照がきたらUserモデルを参照するようにRailsに伝えています。

余談: sourceclass_nameの違いについて

ところで、さっきはsourceで別のモデルを参照したのに、今度はなんでclass_nameなの?って思いませんでしたか?(私は思いました)

その理由は、こちらに書いてあって、
Rails: difference between :source => ?? and :class_name => ?? in models

  • source ... has_many :****, through: :****の時に使う
  • class_name ...has_many :***の時に使う

だそうです:smile:知らなかった!!

確認

ここで、一回きちんとアソシエーションが定義できているか確かめることをお勧めします。私は、こんなふうに確かめました。

$ rails c
> user = User.first
> user.relationships
# => []
> user.relationships.create!(follower_id: 2)
# => Relationship のレコードが表示
> user.followings
# => フォローしているUser(user_idが2のユーザー)のレコードが表示

フォロー中のユーザーのレコードが呼び出されたので、id:1のユーザーはid:2のユーザーをフォローできていると言えます。

逆の関係も考える

さて、それでは今度はユーザーがたくさんのフォロワーにフォローされているという、先程どは逆の状況も考えてみたいと思います。

まず、ゴールなのですが、先程の逆の矢印を定義できれば良いです。
具体的に図に書き込んでみます。

Image from Gyazo

followerがたくさんのuserrelationshipsを通じて持っている、こんな図が出来上がります。

でも、Followerモデルは実際には存在せず、Userモデルとイコールでしたね。
そのため、主語をUserに書き換えてみます。

Image from Gyazo

Userrelationshipsを通じて、followersをたくさん持っている。
言葉としてはわかりやすいのですが、今度は、頭の中に作ったFollowモデルが邪魔になってきました。

followersテーブルを置いたために考えるのが難しくなってきているので、FollowモデルとUserモデルを一つにまとめました。

Image from Gyazo

だいぶ、一番初めに提示したER図に近づいてきましたね:grin:

ついでに、先程の赤い矢印も復活させてみました。
すると、今度はthrough: :relationshipsの部分で、名前が重複しているのがわかります。

Image from Gyazo

そこで、今度は片方の名前を変えて、userfollowerにフォローされている、と言う意味でpassive_relationshipsと名付けました。

これで、最初に提示したER図と同じになっています:relaxed:

アソシエーションの記載

Userモデル

では、この関係を実際にモデルに表していきます。
まず、Userモデルはこうなります。

models/user.rb
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 # 追記1
  has_many :followers, through: :passive_relationships, source: :user # 追記2
end

めっちゃ複雑になってきましたね:joy:ひとつひとつ読みといていくと、まず、追記1の部分は

  • Userはたくさんのpassive_relationshipsを持っています。
  • この時、参照して欲しいクラスはRelationshipです。
  • 外部キーとしてfollower_idを使います。

というのを表しています。
次に、追記2の部分は

  • Userはたくさんのfollowersを、passive_relationshipsを通じて持っています。
  • passive_relationshipsは、直前の定義によりRelationship、クラスを参照するようになっています。

複雑すぎて憤死しそうです:joy:
ワンステップずつ丁寧に書いたつもりなので、丁寧に読んでみてください:sweat_smile:

Relarionshipモデル

最後に、Relationshipモデルに追記した内容を紹介します。

models/relationship.rb
class Relationship < ApplicationRecord
  belongs_to :user # 追記
  belongs_to :follower, class_name: 'User'
end

こちらは逆にシンプルすぎて心配になるレベルですが、こちらはこれで完了です:innocent:

確認

ここで、1回確認をしてみます。先程、コンソールでid:1のユーザーがid:2のユーザーをフォローすると言うデータは作りましたので、id:2のユーザーは、id:1のユーザーにフォローされているはずです。

それを、コンソールで試してみます。

$ rails c
> user2 = User.second
> user2.followers
# => id:1のUserのレコードが表示される

user2をフォローしているユーザーが取得できました!!成功です:smile:

to be contenued ...

これからいよいよviewやcontrollerを実装!...となっていくのですが、
ここからは次回に続きます。

Ajax出てこないじゃん!と思った方、ごめんなさい。次回に出てきます。。。

▼この話の続編はこちら
Railsでユーザーフォロー機能を実装する(Ajax使うよ)②

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【エラー】`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がどうなってるか確認しました。

スクリーンショット 2020-12-29 16.06.42.png
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 list

スクリーンショット 2021-01-02 14.39.21.png
バージョンが一つでdefaultが解除されてました。

payjpmを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/

https://qiita.com/Okame-chan/items/39052dc4d4c3cebfb1ee

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

2回目以降のデプロイ

前提条件としてご自身のアプリケーションが既にデプロイされている状態とします。

まず、アプリのファイルが変更されていればGitHubでコミット〜マージまで行いましょう!

変更点をHerokuに反映させる

ターミナルに以下のコマンドを打ちましょう

ターミナル
% git add .   
% git commit -m "変更した内容がわかるような説明をここにいれる、日本語でもおk"       

リポジトリのプッシュ

ターミナル
% git push heroku master 

マイグレーションの実行

ターミナル
% heroku run rake db:migrate  

お疲れ様です、これでエラーが出ていなければ完了です!

もしエラーが出たときの対処、以下のコマンドを実行してヒントを得る

ターミナル
% heroku logs --tail --app <<アプリケーション名>>

最後まで見ていただいてありがとうございます!誰かの参考になれば幸いです

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

デプロイする方法

デプロイの方法を自分の備忘録として残しておきます。

GitHubにご自身のアプリがmasterにマージされた状態と言う前提条件で進めます。

まずHerokuと言うサービスを使います
Herokuの新規登録ページ
https://signup.heroku.com/login

ここで必要な項目を入力したらメールが届くのでそこに入って以下の入力をしましょう!
※パスワードは英数・数字・記号の3つを含み8文字以上を入力しましょう。

スクリーンショット 2021-01-16 18.57.07.png

なんかこんなやつがでてきたら登録完了⬇︎

スクリーンショット 2021-01-16 18.59.44.png

下のような画面が出てきたら画面下の「Accept」をクリックしてください⬇︎

スクリーンショット 2021-01-16 19.00.47.png

Herokuのトップ画面に行けたらおk⬇︎

スクリーンショット 2021-01-16 19.01.59.png

Herokuの注意点

Herokuは基本的に無料で利用が可能ですが、使用するデータベースの設定がデフォルトでPostgreSQLというRDBMSになっています。

HerokuでMySQLを使用する為にはクレジットカードの登録が必須となっているので、アカウント管理ページのBillingからカード情報を登録しましょう。

クレカの登録

私はMySQLを使いたのでクレカを登録します(別にしない人は飛ばしてください)

以下のスクショの手順で進めましょう

スクリーンショット 2021-01-16 19.05.57.png

スクリーンショット 2021-01-16 19.06.09.png

スクリーンショット 2021-01-16 19.06.17.png

クレジットカードの情報を入力

スクリーンショット 2021-01-16 19.06.23.png

以下のような画面になれば登録完了!

スクリーンショット 2021-01-16 19.06.31.png

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 heroku

fatal: 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を閉じる

スクリーンショット 2021-01-17 2.16.27.png

環境変数の設定

heroku configコマンド

Heroku上で環境変数の参照・追加・削除等をする場合に用います。環境変数の追加であればheroku config:set 環境変数名="値"と実行します。そうすることによって、Heroku上で環境変数を追加できます。

以下のコマンドをターミナルで実行

ターミナル
% heroku config:set RAILS_MASTER_KEY=`cat config/master.key`

% heroku config

以下のような感じになっていたらおk

スクリーンショット 2021-01-17 2.49.07.png

アプリケーションをプッシュ

以下のコマンド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

最後まで見ていただいてありがとうございます!
誰かのお役に立てれば幸いです!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails + Webpacker】assetsの画像を使いたい! Vue.jsで画像を表示できるまで

RailsとWebpackerで開発している時に、画像どうやって読み込むのかなと思って調べてみた記録です。

WebpackerのREADMEをのぞいてみる

WebpackerのREADMEの Paths > resolved を参照してみると、assetsをもつアプリとimagesを共有したいときは、webpacker.ymlresolved_pathsと書いて読み込める、とあります。今回はこれに習って実装しています。

config/webpacker.yml
resolved_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.yml
  resolved_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>

こうやって書いてみるととってもシンプルですね。

以上、少しでも参考になれば嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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へ変えてみました。

変え方については検索すればいくらでもヒットするのでそちらを。
ちなみにクライアントからアクセスして使ってみた感じだと速度が遅めです。まぁ無料なのでそこは仕方ないですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

開発環境にRailsをインストール・新規アプリ作成

引用先
Railsチュートリアル

Railsをインストール

Rubyドキュメントをインストールしないよう.gemrcファイルを設定

$ echo "gem: --no-document" >> ~/.gemrc

Railsをインストールするには、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 <アプリ名>

各フォルダの役割

引用先
Railsチュートリアル 表 1.2: デフォルトのRailsディレクトリ構成の概要

ディレクトリ 用途
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を先に実行


ここまでが環境構築となります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby on Rails】EC2でwheneverを使ってcrontabを設定する時のハマったことの解決

wheneverというのはRuby on Railsのgemであり、crontabを設定する時によく使われています。

使い方

使い方はGithubホームページに詳しく記載されていますが、主に使うのは下記になります。

Gemfileに追加

Gemfile
gem 'whenever', require: false

インストール

bundle exec wheneverize .

schedule.rbファイルの内容を確認する

whenever

開発環境でcrontabを更新する

whenever --update-crontab --set environment='development'

Capistranoに入れる

config/deploy.rb
set :whenever_roles, -> { :app }
Capfile
require 'whenever/capistrano'

ハマったことなどの解決

EC2では動かない

EC2にデプロイの後、crontabが動かず、ログ確認したらBundleバージョンが間違いなどの問題

job_typeを以下に設定すれば良い

config/schedule.rb
set :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.rb
require '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>'
end

crontabのログに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を使います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ActiveHashの導入目的とアプリへの実装までの簡単な流れ

ActiveHashとは

都道府県名などの変更されないデータをモデルファイル内に直接記述することで、データベースへ保存せずにデータを取り扱うことができるgemです。

ActiveHashを導入する目的

ユーザー情報のような編集されることがあるデータと違って、都道府県名などは変更されないデータなので、データベースにわざわざ保存する必要がありません。

かといってビューに直接都道府県名のプルダウンメニューを作ってしまうと可読性が下がってしまいます。

そこでActiveHashを使ってモデルからデータを呼び出すという方法を採ることでコードの管理がしやすくなります。

また、ActiveHashを導入することで以下のようなプルダウンメニューを作成するときに大いに役立ちます。
スクリーンショット 2021-01-16 23.55.35.png

プルダウンメニューの実装

住んでいる都道府県を投稿するアプリを使って説明します。

ターミナル
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.rb
class 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

コントローラーとビュー(indexnew)を以下のように記述します。

app/controllers/addresses_controller.rb
class 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
end
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 %>
      </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します。

Gemfile
gem 'active_hash'
ターミナル
bundle install

都道府県のリストを用意するため、prefectureモデルを作成します。
ここで、いつものrails g model :モデル名コマンドに--skip-migrationというオプションを付けます。
--skip-migrationはマイグレーションファイルの作成をスキップしてくれるオプションです。都道府県に関する情報はデータベースに保存しないためです。

ターミナル
rails g model prefecture --skip-migration

作成したprefecture.rbに、以下のように記述します。

app/models/prefecture.rb
class 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.rb
class 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>

参考資料

ActiveHashの公式GitHub

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む