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

Ruby/Ruby on Rails 6 環境構築 *Mac OS 編*

はじめに 今回、progate にてRuby on Rails の学習を一周し終えたので環境構築にチャレンジしてみました。 が、スムーズに行かずつまずいた為その概要を書いていきたいと思います。 同じ駆け出しエンジニアの方の力に少しでもなれれば幸いです。 *Mac OSでのRails6環境構築の記事となります* ターミナルでコマンドを実行 Mac os には標準でターミナル.appが搭載されいるのでそれを使いました。 (アプリケーション/ユーティリティ/ターミナル.app にあります) Homebrewのインストール Mac os専用のパッケージ管理システムです。 Homebrew インストールできたらターミナルにて下記コマンドを入力します。 brew -v インストールできていると、この様にバージョンが表示されます。 *バージョン名は各自異なります。 Homebrew 3.1.2 Homebrew/homebrew-core (git revision e985cb6ba7; last commit 2021-04-16) rbenvのインストール ターミナルに下記コマンドを入力します。 brew install rbenv インストールができているか確認します。 rbenv --version インストールができていれば、この様にバージョンが表示されます。 *バージョン名は各自異なります。 rbenv 1.1.2 rbenvを使用できるようにPATHを通す ターミナル起動時にrbenvを自動的に起動するようにする為にパスを通します。 下記コマンドを一行ごとに入力します。 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 正直ここはよく分からなかったため別記事を参考に進めました。 readlineのインストール ターミナルのirbで日本語入力ができる様になります。 下記コマンドを入力します。 brew install readline 日本語入力できる様にパスを通します。 brew link readline --force Rubyのインストール Rubyのバージョンを確認する為、下記コマンドを入力します。 rbenv install -l コマンドを実行すると、バージョン一覧が表示されます。 *バージョンは各自異なります。 2.5.9 2.6.7 2.7.3 3.0.1 jruby-9.2.17.0 mruby-2.1.2 rbx-5.0 truffleruby-21.0.0 truffleruby+graalvm-21.0.0 Only latest stable releases for each Ruby implementation are shown. Use 'rbenv install --list-all / -L' to show all local versions. インストールするバージョンを指定してコマンドを入力します。 *バージョンは各自異なります。 rbenv install 3.0.1 インストール出来ているか確認します。 ruby -v インストールができていればこの様にバージョンが表示されます。 *バージョン名は各自異なります。 ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-darwin20] Bundlerのインストール gemに必要な正確なバージョンを追跡してインストールしてくれます。 下記コマンドを入力します。 gem install bundler インストール出来ているか確認します。 bundler -v インストールができていればこの様にバージョンが表示されます。 *バージョン名は各自異なります。 Bundler version 2.1.4 yarnのインストール Rails6ではyarnのインストールも必要になりましたので、下記コマンドを入力してインストールします。 brew install yarn インストール出来ているか確認します。 yarn -v インストールができていればこの様にバージョンが表示されます。 *バージョン名は各自異なります。 1.22.10 私はここでつまづきました...。 Rails6ではWebpackerが標準になったことにより、yarnが必要になったそうです。 いくらRailsをコマンドを実行してもインストールできず、ググっても出来ず...。 結果調べて試していたのは、Rails5のインストール手順でyarnのインストールをしていなかったから出来なかっただけでした。 常に最新情報に耳を傾け、調べる力も付けていく必要があること改めて実感しました...。 Railsのインストール インストールするバージョンを指定してコマンドを入力します。 今回は-v 6.0.3.4を指定します。 gem install rails -v 6.0.3.4 インストール出来ているか確認します。 rails -v インストールができていればこの様にバージョンが表示されます。 バージョン名は各自違います。 Rails 6.0.3.4 以上 Ruby / Rails の環境構築となります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

requireの使い方

requireメソッド 送信されたパラメーターの情報を持つparamsが、使用できるメソッド。 requireメソッドは、パラメーターからどの情報を取得するか、選択する。 params.require(:モデル名) requireを使うのはパラメーターが二重ハッシュの時のみ。 [1] pry(#<OrdersController>)> params => <ActionController::Parameters {"authenticity_token"=>"dIFiIxMsjPdq0lATAzwoZgYl/LKtBrD1Zsoo gqyCDoVhXGqCAQHoVSWIkvkMhuXn+ooywt50eQJiCfcCniJamQ==", "hoge"=>"", "post_code"=>"111-1111", "shipping_area_id"=>"3", "municipality"=>"aa", "address"=>"aa", "building_name"=>"", "phone_number"=>"00000000000", "commit"=>"購入", "controller"=>"orders", "action"=>"create", "item_id"=>"2"} permitted: false> この場合だとハッシュは一つなのでrequireは使えない。 [1] pry(#<OrdersController>)> params => <ActionController::Parameters {"authenticity_token"=>"dIFiIxMsjPdq0lATAzwoZgYl/LKtBrD1Zso ogqyCDoVhXGqCAQHoVSWIkvkMhuXn+ooywt50e QJiCfcCniJamQ==","user_purchases"=>{ "hoge"=>"", "post_code"=>"111-1111", "shipping_area_id"=>"3", "municipality"=>"aa", "address"=>"aa", "building_name"=>"", "phone_number"=>"00000000000"}, "commit"=>"購入", "controller"=>"orders", "action"=>"create", "item_id"=>"2"} permitted: false> このような場合だと二重ハッシュなのでrequireを使うことになる。 二重ハッシュになる場合はモデルを指定した時に生成される。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【MAC】環境変数について調べてみた

背景 プログラミング言語を学ぶときによく見かける環境変数。分かりそうで実は分からないところが多かったので、気になったところを調べてみました。linuxコマンド、シェルスクリプトなど関連知識もまとめてみました。MACユーザーであるため、Windowsの環境変数については割愛します。 環境変数とは MacやWindos、DosなどのOS上で設定値やデータを永続的に記憶しておき、どこからでも参照&利用できるようにするための箱(変数)のようなものです。英語だと「Environment variables」になります。 MacのShell Macには「bash」と「zsh」という2種類のシェル(shell)があり、このシェルを通じてカーネルというOSの中核となる部分にターミナルからのコマンドを解釈して伝える役割をしています。現在のMacのシェルは「zsh」であり、 Catalina以前のバージョンでは「bash」でした。環境変数の保存先にはこのshell名が入っています。 主な環境変数について 主な環境変数は以下のようになります。echoコマンドを使って確認出来ます。ユーザー名は「hoge」とします。 $PATH:実行可能なファイルのパス(ディレクトリー)が保存されています。複数の場合(:)で区切って表示されます。 ❯ echo $PATH /usr/local/opt/node@14/bin:/usr/local/opt/mysql@5.6/bin:/Users/hoge/.rbenv/shims:/Library/Frameworks/Python.framework/Versions/3.9/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands $USER:ユーザーネームを表します。 ❯ echo $USER hoge $HOME:デフォルトのユーザーのフォームディレクトリーのパスを表します。 ❯ echo $HOME /Users/hoge $UID:ユーザーのユニックなIDを表します。 ❯ echo $UID 501 $TERM:デフォルトの端末エミュレーター(terminal emulator)を表示してくれます。 ❯ echo $TERM xterm-256color $SHELL:ユーザーが使用しているシェルのパスを表します。 ❯ echo $SHELL /bin/zsh その他に指定されている全ての環境変数を表示するには「env」コマンドを使います。 ❯ env TERM_SESSION_ID=xxxxxxxxxxxxxxxxxxxxxx SSH_AUTH_SOCK=xxxxxxxxxxxxxxxxxx COLORFGBG=xxxxxxxxxxx ITERM_PROFILE=xxxxxxxxxx XPC_FLAGS=xxxxxxxxxx LANG=ja_JP.UTF-8 PWD=/Users/hoge SHELL=xxxxxxxxxxxxxxxx TERM_PROGRAM_VERSION=xxxxxx     (中略) MacOS上の環境変数を操作できるファイル(ログインシェル)はどこにある? 結論から言うとホームディレクトリーにあります。ホームディレクトリーとは「/Users/ユーザ名」となっているところであり、コマンドラインでは「〜」と表示されます。ファイル名は「bash」ジェルの場合は「.bash_profile」、「zsh」シェルでは「.zshrc」です。「.」は隠しファイルを意味します。ホームディレクトリーに移動しコマンドラインで「ls -a」を打つと見れます。Finderで確認するには「shift + command + .」キーを同時に押すと隠しファイルを表示してくれます。 ❯ ls -a . .zsh .. .zsh_history .CFUserTextEncoding .zsh_sessions .DS_Store .zshrc .Trash .zshrc.pre-oh-my-zsh .atom .zshrc_history (中略) 環境変数ファイルログインシェルを編集するには テキストエディターを使います。vscode、atom、sublime textなどのエディターでも構いませんが、通常vimテキストエディターを利用します。vimエディターを使う理由はいろいろあると思いますが、私が思うにはCUI上で起動するのでAMAZONのEC2仮想サーバーにsshキーで接続した場合など、GUIのエディターを利用出来ない環境であったりした場合に活躍するので、vimエディターを利用するのではないかと思います。(また、起動するのに時間が掛からなかったり、とてもシンプルで使いやすいのでよく使われているのだとか) #bashシェルの場合 vim ~/.bash_profile #zshシェルの場合 vim ~/.zshrc 「~/」は「~」でホームディレクトリー(/Users/ユーザ名)に「/」を付けただけで、/Users/ユーザ名/を意味します。 独自の環境変数を設定する方法 vimで開いた「.zshrc」ファイルで「export」コマンドで設定出来ます。正確には設定ではなく、保存した環境変数をOS上で利用できるように輸出(export)・共有します。書き方としては「export 変数名=値」。 export AUTH_USER='hoge' export AMAZON_PASS_WORD='XXXX' 変数名は何でもありですが、覚えやすい変数名にした方がいいと思います。また、既存の環境変数$PATHに独自の実行ファイルのパス(ディレクトリー)を指定することも可能です。指定方法は「export PATH="新たに指定したい実行ファイルのパス:$PATH"」で、PATHと言う環境変数名に"新たに指定したい実行ファイルのパス"を書き、":$PATH"と繋げます。こうすることで最初から定義されていたPATHの値に新たに追加することが出来ます。 #mysqlのパスを指定した例 export PATH="/usr/local/opt/mysql@5.6/bin:$PATH" その他 evalコマンドを「.zshrc」や「.bash_profile」ファイルに記述することで、ターミナルを起動するたびに特定のコマンドを実行するようにすることが可能になります。「eval」コマンドは、指定した文字列を解釈し連結した後にシェル上で実行されます。複数のコマンドを実行するにはコマンドの間に「;」を入れます。試しに「.zshrc」ファイルをvimエディターで開いて次のように記述します。 eval echo $PATH;echo $USER export BASIC_AUTH_USER="xxxxxxxxxxx" export BASIC_AUTH_PASSWORD="xxxxxxxxxx" export AWS_ACCESS_KEY_ID="xxxxxxxxxxxxxx" export AWS_SECRET_ACCESS_KEY="xxxxxx" (中略) ターミナルを閉じて、再起動すると、 Last login: Fri Apr 16 21:29:48 on ttys008 /Library/Frameworks/Python.framework/Versions/3.9/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands hoge ~ ❯ 環境変数$PATHと$USERの値がechoコマンドによって実行され表示されます。 Railsでは「rbenv init」コマンドで毎回初期化する必要がありますが、これを環境変数を管理する「.zshrc」ファイルに書いておくことによって手で打つ手間が省けます。 eval "$(rbenv init -)" 参考サイト&記事 https://wa3.i-3-i.info/word11027.html https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html https://en.wikipedia.org/wiki/Environment_variable https://yuu.1000quu.com/understanding_the_env https://www.guru99.com/linux-environment-variables.html https://www.atmarkit.co.jp/ait/articles/1712/22/news019.html https://eng-entrance.com/unix_linux https://eng-entrance.com/linux-shellscript-what https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1420093584 https://www.webzoit.net/hp/it/internet/homepage/env/cs/server/os/type/unix/linux/shell/kind/ https://gabekore.org/mac-ruby-rails-rbenv
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React + RailsのSPAでdestroyアクションを実装する

これは何? React+Railsで簡単なタスク管理アプリを作っています。 ラベルの隣にある「削除」ボタンを押すと、確認メッセージののち、ラベルが削除されます。 実行環境は以下の通りです。 Rails 6.0.3 React 17.0.2 また、今回のディレクトリ構成は以下の通りです。(関係のある箇所だけ表示) . ├── controllers │   └── api │      └── labels_controller.rb └── javascript    └── pages    └── Labels.jsx Rails側 ある意味衝撃でした。詳細確認中ですが、controllerにもroutesにもdestroy関連アクションを何も記載しなくても動作しました。(axiosのためかしら。。。。) SPA側 削除メソッド自体はとてもシンプルで、axios.delete(URL[, オプション])で渡せばOKでした。その他、実装においてスラスラといかなかったところは解説します。 import React, { useState } from 'react' import axios from 'axios' export const Labels = (props) => { const [labels, setLabels] = useState([]) React.useEffect(async () => { const response = await axios.get('/api/labels'); setLabels(response.data) }, []) const removeLabel = (labelId, e) => { e.preventDefault(); if (window.confirm("ラベルを削除します。よろしいですか?")) { axios.delete("/labels/" + labelId, { headers: { // ★1解説します 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content') } }) .then( res => { // ★3解説します const targetIndex = labels.findIndex( label => { return label.id === res.data.id }) const newLabels = labels.slice(); newLabels.splice(targetIndex, 1); setLabels(newLabels) }) .catch(data => { console.log(data); }) } } return ( <div> <h1>ラベル一覧</h1> // 略 <h3>ラベル</h3> <ul> {labels.map(label => ( <li key={label.id}> {label.name} <a href="" onClick={(e) => removeLabel(label.id, e)}>削除</a> // ★2解説します </li> ))} </ul> </div> ) } CSRFトークン ★1の部分です。RailsではGET以外のajaxリクエストにデフォルトで、ヘッダーにセキュリティトークンを付与します(詳細はRailsセキュリティガイドを参照)。 axios.delete("/labels/" + labelId, { headers: { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content') } }) AjaxでGET以外のリクエストを実施するときには、リクエストヘッダーのX-CSRF-Tokenの項に、トークンを付与する必要があります。 トークンは、<head>タグ内、<meta name="csrf-token" ...>のcontentに記載されています。これは別のRailsアプリの画像ですが、該当箇所にトークンがありますね。 トークンの上の行にある、こちらの記載は詳しく調べきれていないのですが、 'X-Requested-With': 'XMLHttpRequest', こちらの記事によると、 また、クロスドメインの場合、headerに'X-Requested-With' : 'XMLHttpRequest'を入れて送信しなければ、api側でAjaxであることが伝わらない... 引用:クロスドメインで'X-Requested-With'の設定 とのことだったので、RailsにAjaxのリクエストであることを伝えるコードなのだと今は理解しておきます。 onClickイベントの渡し方 ★2の部分です。「削除」のリンクがある箇所です。 <a href="" onClick={(e) => removeLabel(label.id, e)}>削除</a> 大したことではないのですが、Reactチュートリアルにこのような記載もあるくらい、間違えやすい箇所でしたので、備忘も兼ね記載しておきます。 onClick={() => alert('click')} と記載したときに onClick プロパティに渡しているのは関数であることに注意してください。React はクリックされるまでこの関数を実行しません。() => を書くのを忘れて onClick={alert('click')} と書くのはよくある間違いであり、こうするとコンポーネントが再レンダーされるたびにアラートが表示されてしまいます。 JSの式を渡さずに、関数を渡すように心がけます。 findIndex とか splice とか ★3の部分です。ここも難しいことはしていないのですが、私がJSに詳しくないので、勉強も兼ねての記載です。 なお、ロジックそのものはこちらの記事のものを利用させていただきました。 React + Rails API モードで基本的な CRUD アプリを作ってみた (フロントエンド編 その2) .then( res => { const targetIndex = labels.findIndex( label => { return label.id === res.data.id }) const newLabels = labels.slice(); newLabels.splice(targetIndex, 1); setLabels(newLabels) }) findIndex ... 配列.findIndex(条件)の形で、条件を満たす最初の要素のインデックス番号を返します。条件を満たすものがない場合は-1を返します。 splice ... 配列.splice(スタート位置[, 削除する数])の形で、スタート位置(インデックス番号)から指定の数の要素を取り除きます。 完成! 以上で、削除機能の実装は完了です。次回は、「1回1回フォームにリクエストを書くのは面倒なので、まとめて一括で設定する」に取り組んでみたいです。 色々やったけどうまくいかなかった。。。。 また、アップデートアクションを作ったら続きを記載します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Herokuでデプロイする手順

手順 Heroku CLIをインストール brew tap heroku/brew && brew install heroku その後、完了を確認するため heroku --version heroku/7.40.0 darwin-x64 node-v12.16.2 #このようにバージョンが表示されていると良い Herokuにログイン heroku login --interactive Heroku上にアプリ作成 heroku create アプリ名 その後、確認のため git config --list | grep heroku Heroku上でMySQLを使えるようにする heroku addons:add cleardb #ClearDBアドオンを追加 その後、ClearDBデータベースのURLを変数heroku_cleardbに格納する heroku_cleardb=`heroku config:get CLEARDB_DATABASE_URL` Heroku上で環境変数を設定する heroku config:set RAILS_MASTER_KEY=`cat config/master.key` 環境変数一覧を表示する heroku config #RAILS_MASTER_KEYが設定されていれば良い 動作環境を変更する heroku stack:set heroku-18 -a #Herokuで利用するStackを指定 Herokuへアプリを追加 git push heroku master その後、Heroku上でマイグレーションファイルを実行 heroku run rails db:migrate  コマンド一覧 heroku apps:info → 公開されたアプリの詳細をみる heroku logs --tail --app アプリ名 → ログを表示する  補足情報 Herokuでは、定期的に画像のデータなどがリセットされるため、出品から一定時間経過した商品画像は適切に表示されなくなる。適切に表示されなくなった画像のデータを消すためには、下記コマンドを用いてデータベースをリセットすることが必要(最後にS3を導入することで、商品画像が適切に表示されなくなる問題は解消される)。 % heroku run DISABLE_DATABASE_ENVIRONMENT_CHECK=1 rails db:drop db:create db:migrate
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Heroku】git push heroku masterしたとき、error: failed to push some refs to 'https://git.heroku.com/herokuname-12345.git'と怒られた時の対処法

症状 git push heroku masterをしたところ、下記エラーメッセージが表示されてしまい、herokuにpushできませんでした。 gitpushherokumaster git push heroku master Counting objects: 219, done. Compressing objects: 100% (193/193), done. Writing objects: 100% (219/219), 3.96 MiB | 2.48 MiB/s, done. Total 219 (delta 70), reused 0 (delta 0) remote: Compressing source files... done. remote: Building source: remote: remote: -----> Building on the Heroku-20 stack remote: -----> Determining which buildpack to use for this app remote: -----> Ruby app detected remote: -----> Installing bundler 2.2.15 remote: -----> Removing BUNDLED WITH version in the Gemfile.lock remote: -----> Compiling Ruby/Rails remote: Command: 'set -o pipefail; curl -L --fail --retry 5 --retry-delay 1 --connect-timeout 3 --max-time 30 https://s3-external-1.amazonaws.com/heroku-buildpack-ruby/heroku-20/ruby-2.6.3.tgz -s -o - | tar zxf - ' failed on attempt 1 of 3. remote: Command: 'set -o pipefail; curl -L --fail --retry 5 --retry-delay 1 --connect-timeout 3 --max-time 30 https://s3-external-1.amazonaws.com/heroku-buildpack-ruby/heroku-20/ruby-2.6.3.tgz -s -o - | tar zxf - ' failed on attempt 2 of 3. remote: remote: ! remote: ! The Ruby version you are trying to install does not exist on this stack. remote: ! remote: ! You are trying to install ruby-2.6.3 on heroku-20. remote: ! remote: ! Ruby ruby-2.6.3 is present on the following stacks: remote: ! remote: ! - cedar-14 remote: ! - heroku-16 remote: ! - heroku-18 remote: ! remote: ! Heroku recommends you use the latest supported Ruby version listed here: remote: ! https://devcenter.heroku.com/articles/ruby-support#supported-runtimes remote: ! remote: ! For more information on syntax for declaring a Ruby version see: remote: ! https://devcenter.heroku.com/articles/ruby-versions remote: ! remote: ! Push rejected, failed to compile Ruby app. remote: remote: ! Push failed remote: ! remote: ! ## Warning - The same version of this code has already been built: e4e8b0a69aeb09b76275b11e90d4096eb832212c remote: ! remote: ! We have detected that you have triggered a build from source code with version e4e8b0a69aeb09b76275b11e90d4096eb832212c remote: ! at least twice. One common cause of this behavior is attempting to deploy code from a different branch. remote: ! remote: ! If you are developing on a branch and deploying via git you must run: remote: ! remote: ! git push heroku <branchname>:main remote: ! remote: ! This article goes into details on the behavior: remote: ! https://devcenter.heroku.com/articles/duplicate-build-version remote: remote: Verifying deploy... remote: remote: ! Push rejected to murmuring-headland-65418. remote: To https://git.heroku.com/murmuring-headland-65418.git ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'https://git.heroku.com/murmuring-headland-65418.git' 翻訳すると、「インストールしようとしているRubyバージョンはこのスタックに存在しません。」 「エラー:一部の参照を「https://git.heroku.com/herokuname-12345.git」にプッシュできませんでした」 解決方法 Gemfileのrubyをしている箇所をコメントアウトすることで、上記エラーが表示されなくなりました。 herokuがruby2.6.3をサポートしていなかったようです。 Gemfile # ruby '2.6.3' ターミナル #bundleinstallしておく bundle install #gitにpushしておく git add -A git commit -m "changeGemfile" git push heroku master 参考 【初心者向け】RailsチュートリアルでHerokuデプロイ時に「Ruby 2.6.3はインストールできない」と言われたときの適切な対処方法 https://qiita.com/jnchito/items/c3035cc49a9cef053549
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Spotify APIを用いて音楽再生機能の実装

概要 Railsアプリケーションにて、SpotifyのAPIを用いて、楽曲の再生機能を実装します。 私の初めてのPFに実装してあります。 musicrows 音楽のプレイリストの共有サービス https://musicrows.com/ 「たまたま聞いた曲を好きになる」、コロナの外出自粛で音楽との出会いにもそんな偶発性がなくなってきてるなと感じます。だからこそspotifyやapplemusicなどのサブスクのおすすめばかり聴くのではなく、自分から好きな音楽を見つけよう!そんな気持ちで作ったサービスです。 よかったら登録後、自作のプレイリストを投稿してみてください! Spotifyアプリへの登録 こちらを参考にしました、@kents1002さん素晴らしい記事ありがとうございます。 https://qiita.com/kents1002/items/362552906b6438909a7b "CLIENT ID"と"CLIENT SECRET ID"を忘れずにメモしておいてください。 RSpotify(gem)の導入 Rspotifyのgithub https://github.com/guilhermesad/rspotify gem 'rspotify' gem 'dotenv-rails' dotenv-railsのgemは"CLIENT ID"と"CLIENT SECRET ID"などを環境変数で保管するためのgemです。 $ bundle install RSpotifyのgithubのREADMEには下記のようにまとめられており、音楽再生に用いるのは下のほうにある「do_i_wanna_know.preview_url #=> "https://p.scdn.co/mp3-preview/"」のところです。軽くチェックしていてください。 require 'rspotify' artists = RSpotify::Artist.search('Arctic Monkeys') arctic_monkeys = artists.first arctic_monkeys.popularity #=> 74 arctic_monkeys.genres #=> ["Alternative Pop/Rock", "Indie", ...] arctic_monkeys.top_tracks(:US) #=> (Track array) albums = arctic_monkeys.albums albums.first.name #=> "AM" am = albums.first am.release_date #=> "2013-09-10" am.images #=> (Image array) am.available_markets #=> ["AR", "BO", "BR", ...] tracks = am.tracks tracks.first.name #=> "Do I Wanna Know?" do_i_wanna_know = tracks.first do_i_wanna_know.duration_ms #=> 272386 do_i_wanna_know.track_number #=> 1 do_i_wanna_know.preview_url #=> "https://p.scdn.co/mp3-preview/<id>" playlists = RSpotify::Playlist.search('Indie') playlists.first.name #=> "The Indie Mix" # You can search within other types too albums = RSpotify::Album.search('The Wall') tracks = RSpotify::Track.search('Thriller') 音楽再生の機能を実装する コントトーラで取得 私は楽曲のモデルとしてSongモデルを使っていたので、Songのshowのビューに音楽再生の機能を実装してます。 ⚠まれに自分が意図したデータを持ってこれない可能性もあります。その場合はここで取得するデータをいじってみてください。 class SongsController < ApplicationController require 'rspotify' require 'open-uri' RSpotify.authenticate(ENV['SPOTIFY_CLIENT_ID'], ENV['SPOTIFY_SECRET_ID']) def show @song = Song.find(params[:id]) tracks = RSpotify::Track.search(@song.name).first(5) @track = tracks.find { |track| track.artists[0].name == @song.artist_name } end showアクションの中身を一つずつ説明します。  @song = Song.find(params[:id]) でidに紐づくSongの情報を持ってきて  tracks = RSpotify::Track.search(@song.name).first(5) でSongの名前が含まれる楽曲を先頭から5曲持ってきてを@tracksにいれる  @track = tracks.find { |track| track.artists[0].name == @song.artist_name } @tracksの5つのデータの中から@songのアーティスト名と同じ楽曲を@trackにいれる これで@trackにすべての情報が入っている状態です。 あとはviewで表示させましょう! 例) YOASOBIの「夜に駆ける」のデータを持ってきた場合 def show @song = Song.find(params[:id]) tracks = RSpotify::Track.search("夜に駆ける").first(5) @track = tracks.find { |track| track.artists[0].name == "YOASOBI" } @track = tracks.first if @track.nil? end @trackをrails consoleで表示するとこのようになります。 そして、下画像の赤線の@preview_urが音楽再生のurlです。データの構造をイメージしていてください。 viewで表示 <img src="<%= @track.album.images.first["url"] %>" width="300" height="300" class="block"> <h3 class="text-light"><%= @track.artists[0].name %></h3> <iframe class="iframe-song" src="<%= @track.preview_url %>"> 上から順には ・楽曲のアルバムイメージ ・アーティスト名 ・音楽再生 です。 ここではiframe埋め込みを使ってurl先のコンテンツを表示させています。 (iframeに関してはyoutubeの動画等を表示できるそうなのですが、如何せん記事が少なかったので詳細はご自身でお調べください) これで表示は完成です。 何かミス等あれば教えていただきたいです。 初めての投稿になりますが、今後も色々アウトプットしていきたいと思います!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FontawesomeのRails6への導入

はじめに この記事ではyarnへのインストールをする方法で話を進めていきます。 導入環境 Mac Catalina ver10.15.7 Ruby 2.6.5 Rails 6.0.3.5 導入方法 まずは導入したいアプリのディレクトリでyarnにfontawesomeを取り込むコマンドを打ち込みます。 %yarn add @fortawesome/fontawesome-free そうすると処理の後、Done!と出るのでyarn.lockとpakage.jsonファイルを確認してみましょう yarn.lock "@fortawesome/fontawesome-free@^5.15.3": version "5.15.3" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.3.tgz#c36ffa64a2a239bf948541a97b6ae8d729e09a9a" integrity sha512-rFnSUN/QOtnOAgqFRooTA3H57JLDm0QEG/jPdk+tLQNL/eWd+Aok8g3qCI+Q1xuDPWpGW/i9JySpJVsq8Q0s9w== pakage.json "@fortawesome/fontawesome-free": "^5.15.3" 各ファイルに上記の記述があればひとまずOKです。 そして今度はjavascriptとstylesheetsへの導入を行います。 javascript/packs/application.js import '@fortawesome/fontawesome-free/js/all'; javascriptファイルへはそのまま上記の記述をするだけで良いですが stylesheetsへの導入の際、元々あるapplication.cssをapplication.scssに変更する必要があるので注意してください。 application.scss $fa-font-path: '@fortawesome/fontawesome-free/webfonts'; @import '@fortawesome/fontawesome-free/scss/fontawesome'; @import '@fortawesome/fontawesome-free/scss/solid'; @import '@fortawesome/fontawesome-free/scss/regular'; @import '@fortawesome/fontawesome-free/scss/brands'; @import '@fortawesome/fontawesome-free/scss/v4-shims'; これらの記述が完了したら実際にviewにfontawesomeで提供されているタグをコピペしたり、 記述する事で見た目に反映されます。 余談ではありますが上記の記述の内regular以下はfontawesomeにPro登録をする事で使用可能になるもののため記述の必要は無さそうではあります。 最後に これで様々なアイコンが使用可能になるため、ユーザーへのUIデザインの配慮がしやすくなります。 今回はあくまでHowの部分なため各ファイルの相互関係による動作の部分であるWhyも今後学習を進めていきたいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

カラム名間違いでmigrationファイル差し戻し(最新のテーブルしかロールバックできない)

あまりやらないので気をつけないといけないことがあります。 マイグレーションファイルはrials db:migrate:statusしても terminal database: furima_32844_development Status Migration ID Migration Name -------------------------------------------------- up 20210409081355 Devise create users up 20210414110750 Create items down 20210415131442 Create active storage tablesactive storage 3テーブルあったら最新で作った1テーブル分のファイルしかロールバックできない。 解決方法 STEP=nを付け加えればいいだけです。 rails db:rollback STEP=1 terminal Status Migration ID Migration Name -------------------------------------------------- up 20210409081355 Devise create users down 20210414110750 Create items down 20210415131442 Create active storage tablesactive storage
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】Docker上のアプリケーションでDevise(認証機能)を使う方法

Docker上のRailsアプリケーションでDevise(認証機能)を使う方法のまとめ。 参考リンク https://github.com/heartcombo/devise https://github.com/heartcombo/devise/wiki/How-Tos https://github.com/heartcombo/devise/wiki/How-To:-Add-:confirmable-to-Users (はじめに)dockerコンテナ内でコマンドを実行する方法 Dockerコンテナの中のアプリケーションでコマンドを実行する場合はまずコンテナに入る。 コンテナの中に入るにはdockerコマンドとdocker-compose使う方法がある。 どちらの場合もコンテナは起動している必要がある。 docker exec -it サービス名 シェル docker-compose exec サービス名 シェル シェルは基本的にbashかsh。アプリケーション毎に異なる。 ▼実例 例えば、alpine(Linuxディストリビューションの一つ)のrubyを使って作成したdocker上のrailsアプリケーションに入る場合は以下となる。 $ docker exec -it サービス名 sh /app # または $ docker-compose exec サービス名 sh /app # /app #が表示されればコンテナ内に入れている。コンテナから出る時はexitを入力しEnter。 ログイン機能の作成方法 ここから本題。railsのdeviseというgemを使ってログイン認証機能を簡単に実装する手順。 1. deviseのインストール Gemfileにdeviseを追記し、bundle installを実行する。 Gemfile gem 'devise' railsはdockerの中で起動しているので、docker内のコンテナに入ってからbundle installを実行する。 $ docker exec -it サービス名 sh /app # bundle install 以下のように表示されればdeviseパッケージのインストールが完了。 2. deviseをアプリケーションに導入する deviseのパッケージインストールが終わったので、次にアプリケーションにdevise機能を実装する。Dockerコンテナに入ったままrails g devise:installを実行。 /app # rails g devise:install Running via Spring preloader in process 534 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 * =============================================================================== これでdeviseが使えるようになった。 3. 認証機能が使えるモデルの作成 認証機能が使えるモデルを作成するには、通常のrails g model モデル名ではなくdeviseを使う。 ・rails g devise モデル名 /app # rails g devise user Running via Spring preloader in process 572 invoke active_record create db/migrate/20210414012052_devise_create_users.rb create app/models/user.rb invoke test_unit create test/models/user_test.rb create test/fixtures/users.yml insert app/models/user.rb route devise_for :users 3-1. migrationファイルの中身 db/migrate/20210414012052_devise_create_users.rb devise_create_テーブル名 のクラスが生成され、関数の中には各モジュール毎の設定が記述されている。 # frozen_string_literal: true class DeviseCreateUsers < ActiveRecord::Migration[6.1] 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.string :current_sign_in_ip # t.string :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 カラムの型の記述ルールは以下のようになっている。 t.カラムの型 :カラム名 条件1: 値1, 条件2: 値2,,, 3-1-1. Database authenticatable t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: "" emailと暗号化したパスワードのカラムを作成している。 null: false 何かしら値がない場合はエラーとなる。 default: "" 初期値は何も指定されていない。 3-1-2. Recoverable t.string :reset_password_token t.datetime :reset_password_sent_at パスワードリセット用のトークンを保存するカラムと、送信日時を保存するカラム。 3-1-3. Rememberable t.datetime :remember_created_at ログイン状態を維持しておく期間。 3-1-4. Trackable t.integer :sign_in_count, default: 0, null: false t.datetime :current_sign_in_at t.datetime :last_sign_in_at t.string :current_sign_in_ip t.string :last_sign_in_ip ログインした回数、最新のログイン日時、前回のログイン日時、最新のログインIP、最終のログインIPを保存。 デフォルトはコメントアウト。 3-1-5. Confirmable t.string :confirmation_token t.datetime :confirmed_at t.datetime :confirmation_sent_at t.string :unconfirmed_email # Only if using reconfirmable メールに記載されているURLをクリックして登録完了する時に使うカラム。 確認用の番号(トークン)、登録申請された時間、本登録用のメールを送信した時間、e-mailアドレスを保存する。 デフォルトはコメントアウト。 3-1-6. 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 一定回数ログインに失敗した時にロックアウトする用のカラム。 ログインの入力可能回数、ロックアウトしたトークン、ロックアウトした時間を保存。 デフォルトはコメントアウト。 3-1-7. 重複防止のバリデーション(ユニーク設定) emailやトークンなど重複してはいけないカラムを指定する。 ・add_index :テーブル名, :カラム名, unique: true 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 (補足)追加モジュール デフォルトでは記述がないが、以下のようなモジュールも用意されている。使う場合は追加でカラムの設定が必要。 ・timeoutable 一定時間活動していないアカウントのセッションを破棄する。デフォルトは30分が設定されている。 変更したい場合はconfig/initializers/devise.rbに追記する。 ・omniauthable SNS認証機能(twitterやfacebookなど)の追加。intridea/omniauthを使えるようにする。 3-2. コントローラの中身 コントローラの中で使いたいモジュールを:モジュール名で指定する。 app/models/user.rb user.rb class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable end モジュールは複数指定可能。 3-3. ルーティングの確認 config/routes.rb を確認するとdevise_for: usersが追加されている。 ・devise_for: モデル名 指定したモデル名を使ったルーティングを自動設定してくれる。 /users/sign_inや/users/password/newといったルートが作成されている。 追加されたルーティング一覧 /app # rails routes Prefix Verb URI Pattern Controller#Action new_user_session GET /users/sign_in(.:format) devise/sessions#new user_session POST /users/sign_in(.:format) devise/sessions#create destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy new_user_password GET /users/password/new(.:format) devise/passwords#new edit_user_password GET /users/password/edit(.:format) devise/passwords#edit user_password PATCH /users/password(.:format) devise/passwords#update PUT /users/password(.:format) devise/passwords#update POST /users/password(.:format) devise/passwords#create cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel new_user_registration GET /users/sign_up(.:format) devise/registrations#new edit_user_registration GET /users/edit(.:format) devise/registrations#edit user_registration PATCH /users(.:format) devise/registrations#update PUT /users(.:format) devise/registrations#update DELETE /users(.:format) devise/registrations#destroy POST /users(.:format) devise/registrations#create 4. development.rbの設定 config/environments/development.rb に、デフォルトのURLを設定する。 development.rb #devise setting config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } 5. デフォルトの認証ページ画面を表示する マイグレーションをしてから、認証ページにアクセスする。 Dockerコンテナ内でrails db:migrateを実行。 /app # rails db:migrate == 20210414012052 DeviseCreateUsers: migrating ================================ -- create_table(:users) -> 0.0302s -- add_index(:users, :email, {:unique=>true}) -> 0.0041s -- add_index(:users, :reset_password_token, {:unique=>true}) -> 0.0036s == 20210414012052 DeviseCreateUsers: migrated (0.0382s) ======================= ブラウザで追加されたルートにアクセスする。 http://localhost:3000/users/sign_in http://localhost:3000/users/password/new 6. 日本語に変更(localeの日本語化) デフォルトの言語は英語なので日本語に変更する。(deviseではなくrailsアプリケーションの言語設定を変える) 6-1. configファイルの変更 config/application.rb に以下を追記。 application.rb config.i18n.default_locale = :ja 6-2. localesディレクトリに言語ファイルを追加 config/locales配下に以下2つのファイルを追加する。 ・ja.yml ・devise.ja.yml (参考)i18nとは?使い方まとめ。ビュー(View),コントローラー(Controller), コンソールでの呼び出し方とlocaleの使い方 devise.ja.yml ja: errors: messages: not_found: "は見つかりませんでした" # not_found: "not found" already_confirmed: "は既に登録済みです" # already_confirmed: "was already confirmed" not_locked: "は凍結されていません" # not_locked: "was not locked" devise: failure: unauthenticated: 'ログインしてください。' # unauthenticated: 'You need to sign in or sign up before continuing.' unconfirmed: '本登録を行ってください。' # unconfirmed: 'You have to confirm your account before continuing.' locked: 'あなたのアカウントは凍結されています。' # locked: 'Your account is locked.' invalid: 'メールアドレスかパスワードが違います。' # invalid: 'Invalid email or password.' invalid_token: '認証キーが不正です。' # invalid_token: 'Invalid authentication token.' timeout: 'セッションがタイムアウトしました。もう一度ログインしてください。' # timeout: 'Your session expired, please sign in again to continue.' inactive: 'アカウントがアクティベートされていません。' # inactive: 'Your account was not activated yet.' sessions: signed_in: 'ログインしました。' # signed_in: 'Signed in successfully.' signed_out: 'ログアウトしました。' # signed_out: 'Signed out successfully.' passwords: send_instructions: 'パスワードのリセット方法を数分以内にメールでご連絡します。' # send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.' updated: 'パスワードを変更しました。' # updated: 'Your password was changed successfully. You are now signed in.' confirmations: send_instructions: '登録方法を数分以内にメールでご連絡します。' # send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.' confirmed: 'アカウントを登録しました。' # confirmed: 'Your account was successfully confirmed. You are now signed in.' registrations: signed_up: 'アカウント登録を受け付けました。確認のメールをお送りします。' # signed_up: 'You have signed up successfully. If enabled, a confirmation was sent to your e-mail.' updated: 'アカウントを更新しました。' # updated: 'You updated your account successfully.' destroyed: 'アカウントを削除しました。またのご利用をお待ちしております。' # destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.' unlocks: send_instructions: 'アカウントの凍結解除方法を数分以内にメールでご連絡します。' # send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.' unlocked: 'アカウントを凍結解除しました。' # unlocked: 'Your account was successfully unlocked. You are now signed in.' mailer: confirmation_instructions: subject: 'アカウントの登録方法' # subject: 'Confirmation instructions' reset_password_instructions: subject: 'パスワードの再設定' # subject: 'Reset password instructions' unlock_instructions: subject: 'アカウントの凍結解除' # subject: 'Unlock Instructions' ja.yml ja: activerecord: attributes: user: confirmation_sent_at: パスワード確認送信時刻 confirmation_token: パスワード確認用トークン confirmed_at: パスワード確認時刻 created_at: 作成日 current_password: 現在のパスワード current_sign_in_at: 現在のログイン時刻 current_sign_in_ip: 現在のログインIPアドレス email: Eメール encrypted_password: 暗号化パスワード failed_attempts: 失敗したログイン試行回数 last_sign_in_at: 最終ログイン時刻 last_sign_in_ip: 最終ログインIPアドレス locked_at: ロック時刻 password: パスワード password_confirmation: パスワード(確認用) remember_created_at: ログイン記憶時刻 remember_me: ログインを記憶する reset_password_sent_at: パスワードリセット送信時刻 reset_password_token: パスワードリセット用トークン sign_in_count: ログイン回数 unconfirmed_email: 未確認Eメール unlock_token: ロック解除用トークン updated_at: 更新日 models: user: ユーザー devise: confirmations: confirmed: メールアドレスが確認できました。 new: resend_confirmation_instructions: アカウント確認メール再送 send_instructions: アカウントの有効化について数分以内にメールでご連絡します。 send_paranoid_instructions: メールアドレスが登録済みの場合、本人確認用のメールが数分以内に送信されます。 failure: already_authenticated: すでにログインしています。 inactive: アカウントが有効化されていません。メールに記載された手順にしたがって、アカウントを有効化してください。 invalid: "%{authentication_keys}またはパスワードが違います。" last_attempt: もう一回誤るとアカウントがロックされます。 locked: アカウントはロックされています。 not_found_in_database: "%{authentication_keys}またはパスワードが違います。" timeout: セッションがタイムアウトしました。もう一度ログインしてください。 unauthenticated: ログインもしくはアカウント登録してください。 unconfirmed: メールアドレスの本人確認が必要です。 mailer: confirmation_instructions: action: メールアドレスの確認 greeting: "%{recipient}様" instruction: 以下のリンクをクリックし、メールアドレスの確認手続を完了させてください。 subject: メールアドレス確認メール email_changed: greeting: こんにちは、%{recipient}様。 message: メールアドレスの(%{email})変更が完了したため、メールを送信しています。 message_unconfirmed: メールアドレスが(%{email})変更されたため、メールを送信しています。 subject: メール変更完了 password_change: greeting: "%{recipient}様" message: パスワードが再設定されました。 subject: パスワードの変更について reset_password_instructions: action: パスワード変更 greeting: "%{recipient}様" instruction: パスワード再設定の依頼を受けたため、メールを送信しています。下のリンクからパスワードの再設定ができます。 instruction_2: パスワード再設定の依頼をしていない場合、このメールを無視してください。 instruction_3: パスワードの再設定は、上のリンクから新しいパスワードを登録するまで完了しません。 subject: パスワードの再設定について unlock_instructions: action: アカウントのロック解除 greeting: "%{recipient}様" instruction: アカウントのロックを解除するには下のリンクをクリックしてください。 message: ログイン失敗が繰り返されたため、アカウントはロックされています。 subject: アカウントのロック解除について omniauth_callbacks: failure: "%{kind} アカウントによる認証に失敗しました。理由:(%{reason})" success: "%{kind} アカウントによる認証に成功しました。" passwords: edit: change_my_password: パスワードを変更する change_your_password: パスワードを変更 confirm_new_password: 確認用新しいパスワード new_password: 新しいパスワード new: forgot_your_password: パスワードを忘れましたか? send_me_reset_password_instructions: パスワードの再設定方法を送信する no_token: このページにはアクセスできません。パスワード再設定メールのリンクからアクセスされた場合には、URL をご確認ください。 send_instructions: パスワードの再設定について数分以内にメールでご連絡いたします。 send_paranoid_instructions: メールアドレスが登録済みの場合、パスワード再設定用のメールが数分以内に送信されます。 updated: パスワードが正しく変更されました。 updated_not_active: パスワードが正しく変更されました。 registrations: destroyed: アカウントを削除しました。またのご利用をお待ちしております。 edit: are_you_sure: 本当によろしいですか? cancel_my_account: アカウント削除 currently_waiting_confirmation_for_email: "%{email} の確認待ち" leave_blank_if_you_don_t_want_to_change_it: 空欄のままなら変更しません title: "%{resource}編集" unhappy: 気に入りません update: 更新 we_need_your_current_password_to_confirm_your_changes: 変更を反映するには現在のパスワードを入力してください new: sign_up: アカウント登録 signed_up: アカウント登録が完了しました。 signed_up_but_inactive: ログインするためには、アカウントを有効化してください。 signed_up_but_locked: アカウントがロックされているためログインできません。 signed_up_but_unconfirmed: 本人確認用のメールを送信しました。メール内のリンクからアカウントを有効化させてください。 update_needs_confirmation: アカウント情報を変更しました。変更されたメールアドレスの本人確認のため、本人確認用メールより確認処理をおこなってください。 updated: アカウント情報を変更しました。 updated_but_not_signed_in: あなたのアカウントは正常に更新されましたが、パスワードが変更されたため、再度ログインしてください。 sessions: already_signed_out: 既にログアウト済みです。 new: sign_in: ログイン signed_in: ログインしました。 signed_out: ログアウトしました。 shared: links: back: 戻る didn_t_receive_confirmation_instructions: アカウント確認のメールを受け取っていませんか? didn_t_receive_unlock_instructions: アカウントのロック解除方法のメールを受け取っていませんか? forgot_your_password: パスワードを忘れましたか? sign_in: ログイン sign_in_with_provider: "%{provider}でログイン" sign_up: アカウント登録 minimum_password_length: "(%{count}字以上)" unlocks: new: resend_unlock_instructions: アカウントのロック解除方法を再送する send_instructions: アカウントのロック解除方法を数分以内にメールでご連絡します。 send_paranoid_instructions: アカウントが見つかった場合、アカウントのロック解除方法を数分以内にメールでご連絡します。 unlocked: アカウントをロック解除しました。 errors: messages: already_confirmed: は既に登録済みです。ログインしてください。 confirmation_period_expired: の期限が切れました。%{period} までに確認する必要があります。 新しくリクエストしてください。 expired: の有効期限が切れました。新しくリクエストしてください。 not_found: は見つかりませんでした。 not_locked: はロックされていません。 not_saved: one: エラーが発生したため %{resource} は保存されませんでした。 other: "%{count} 件のエラーが発生したため %{resource} は保存されませんでした。" https://gist.github.com/yhara/606476 https://github.com/tigrish/devise-i18n/blob/master/rails/locales/ja.yml ページをリロード 一部の英語が日本語に変換された。残りはビューを変更する必要がある。 7. ビューの日本語化 dockerコンテナ内でrails g devise:viewsを実行する。 /app # rails g devise:views Running via Spring preloader in process 564 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 viewsディレクトリ配下にdeviseのディレクトリが追加された。 ディレクトリ 内容 ファイル confirmation パスワード再発行用のフォーム new.html.erb mailer 送信するメールの内容 (1)confirmation_instructions.html.erb, (2)email_changed.html.erb, (3)password_change.html.erb, (4)reset_password_instructions.html.erb, (5)unlock_instructions.html.erb passwords パスワードを忘れた時のフォーム (1)edit.html.erb, (2)new.html.erb registrations ユーザー情報の新規登録と編集フォーム sessions ログインフォーム new.html.erb shared 共通のエラーメッセージとリンク部分のテンプレート unlocks アカウントロック通知メールのフォーム new.html.erb http://localhost:3000/users/sign_in で表示されるビューを編集する。 app/views/devise/sessions/new.html.erb new.html.erb <h2>ログイン</h2> <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> <div class="field"> <%= f.label :email %><br /> <%= f.email_field :email, autofocus: true, autocomplete: "email" %> </div> <div class="field"> <%= f.label :password %><br /> <%= f.password_field :password, autocomplete: "current-password" %> </div> <% if devise_mapping.rememberable? %> <div class="field"> <%= f.check_box :remember_me %> <%= f.label :remember_me %> </div> <% end %> <div class="actions"> <%= f.submit "送信" %> </div> <% end %> <%= render "devise/shared/links" %> 下部の<%= render "devise/shared/links" %>は以下のファイルを呼び出しているため、該当部分を変更する。 app/views/devise/shared/_links.html.erb _links.html.erb <%- if devise_mapping.registerable? && controller_name != 'registrations' %> <%= link_to "新規登録", new_registration_path(resource_name) %><br /> <% end %> <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> <%= link_to "パスワードを忘れましたか?", new_password_path(resource_name) %><br /> <% end %> ▼ページをリロード これで日本語化が完了。 8. フラッシュメッセージの作成 deviseをインストールしたときの指示にしたがってapplication.html.erbにフラッシュメッセージを表示するタグを追加する。 deviseの説明 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> noticeはログインや投稿に成功した時に表示されるメッセージ。 alertはEメールやPWが正しくない場合に表示されるメッセージ。 app/views/layouts/application.html.erb のbodyタグにフラッシュメッセージを表示するタグを追加。 application.html.erb <body> <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> <%= yield %> </body> 画面上部にフラッシュメッセージが表示されるようになった。 ただし、この状態ではデフォルト状態で隙間が開いてしまうためフラッシュメッセージが存在する時のみタグを表示するように変更する。 application.html.erb <body> <% if notice %>    <p><%= notice %></p> <% end %> <% if alert %> <p><%= alert %></p> <% end %> <%= yield %> </body> 9. ログイン後に表示されるページを変更する ログインに成功するとデフォルトでroot_urlにリダイレクトされる。これを任意のページに変更する。 9-1. rails g controller コントローラ名 例として、pages > show.html.erbを表示する設定にする。 Dockerコンテナの中に入りコントローラーを作成する。 $ docker-compose exec サービス名 sh /app # rails g controller pages 9-2. ビューの作成 生成されたapp/views/pages配下に show.html.erb を作成する。 app/views/pages/show.html.erb <div>ログイン成功後に表示されるページ</div> <%= link_to 'ログアウト', destroy_user_session_path, method: :delete %> 9-3. ルーティングの設定 ルート名をpages_showとする。 routes.rb Rails.application.routes.draw do devise_for :users root to: 'top#index' #追記 get '/pages/show', to: 'pages#show', as: :pages_show end ・get 'URI', to: 'コントローラ名#アクション名, as: :ルート名' 9-4. コントローラの設定(application_controller.rb) ログインに成功した場合と失敗した場合に表示するビューへのリダイレクトを設定する。 使うルート名はpages_showとnew_user_session。詳細はrails routesで確認できる。 /app # rails routes Prefix Verb URI Pattern Controller#Action new_user_session GET /users/sign_in(.:format) devise/sessions#new pages_show GET /pages/show(.:format) pages#show new_user_sessionはログインページ。 app/controllers/application_controller.rbに以下のようにメソッドを記述する。 applcation_controller.rbのメソッドは他のコントローラにも読み込まれる(<で拡張しているため)。 application_controller.rb class ApplicationController < ActionController::Base def after_sign_in_path_for(resource) pages_show_path end private def sign_in_required redirect_to new_user_session_url unless user_signed_in? end end Deviseのログイン後にリンクするページ after_sign_in_path_forヘルパをで指定する。 ルートへのパス def after_sign_in_path_for(resource) パス end ルート名_pathは指定したルートのパス('/配下')を表示するヘルパ。 pages_showを指定した場合、対応するpagesコントローラのshowメソッドが実行される(pages#show) ログインに失敗した場合の処理 ログインに失敗した場合はnew_user_session private def sign_in_required redirect_to new_user_session_url unless user_signed_in? end このメソッド名はなんでもいい。pagesコントローラで使う時に合わせる。 privateを記述すると、同じクラス(拡張したクラスも含む)の中からしか読み込めないようにできる。 ・unless修飾子を使った条件分岐 trueで実行する処理 unless 条件 user_signed_inが存在すればnew_user_sessionのルートにリダイレクトする。 ・redirect_to URL 指定したURLにリダイレクトする ・ルート名_url 指定したルート名のurlを呼び出す。 ・unless 条件 ifの逆。条件がfalseだった時に指定した処理を実行する。if !条件と同じ。 ・user_signed_in? Deviseのヘルパ。ログインしている場合はtureになる。(便利!) 9-5. コントローラの設定(pages_controller.rb) ログインに成功した時に表示するapp/controllers/pages_controller.rbの設定をする。 before_actionを使って先ほど定義したis_signed_inメソッドを呼び出してから、showアクションを実行する。 pages_controller.rb class PagesController < ApplicationController before_action :is_signed_in, only: [:show] def show end end ・before_action :メソッド名 アクションを指定しない場合は、すべてのアクションの前に指定したメソッドが実行される。 ・before_action :メソッド名, only: [:アクション名, アクション名,,,] only: を使うと指定したアクションを実行する場合のみメソッドを実行する。 ・before_action :メソッド名, except: [:アクション名, アクション名,,,] exceptを使うと指定したアクション以外でメソッドを実行する。 onlyもexceptもアクションが一つの場合は[ ]がなくてもいい。 補足:別の記述方法 deviseのヘルパでauthenticate_user!を使うとより簡単に記述できる。これは、ログインしてない場合はログインページにリダイレクトするヘルパ。 class PagesController < ApplicationController before_action :authenticate_user!, only: [:show] def show end end ↓↑ 同じ class PagesController < ApplicationController before_action :is_signed_in, only: [:show] def show end end private def is_signed_in redirect_to new_user_session_url unless user_signed_in? end 9-6. ブラウザの表示 ログイン画面/users/sign_inから正しくログインできると指定したページに飛ぶことができる。 10. Deviseのヘルパ モデル名をuserとして生成した場合(rails g devise user)の例。 別のモデル名を使った場合は、userの部分を指定したモデル名に変更する。 10-1. before_action :authenticate_user! ログインしてない場合はログインページにリダイレクトするヘルパ。コントローラの上部で使う。 class PagesController < ApplicationController before_action :authenticate_user!, only: [:show] def show end end 10-2. user_signed_in? ユーザーがログインしている場合はtrueを返す。 デバッグ例 def show pp "user_signed_in?:#{user_signed_in?}" end 10-3. current_user 現在のセッションのユーザー情報を取得できる。保存してある情報は、4つ。(1)id, (2)email, (3)created_at, (4)updated_at。 irb(main):009:0> User.find[1] User Load (0.8ms) SELECT "users".* FROM "users" => #<User id: 2, email: "111@222", created_at: "2021-04-15 05:08:07.005182000 +0000", updated_at: "2021-04-15 05:08:07.005182000 +0000"> ユーザーのidを呼び出したい場合は、current_user.idとする。 デバッグ例 def show pp "current_user:#{current_user}" pp "current_user.id:#{current_user.id}" end 10-4. user_session ユーザーのセッション情報を格納しておく変数。デフォルトは空。 デバッグ例 def show pp "user_session:#{user_session}" user_session["point"] = 5432 user_session["os"] = ["apple", "windows"] pp "user_session:#{user_session}" end 一度ログアウトしてから、再度ログインすると空になる。 11. 新規登録時のメール承認機能の実装 confirmableモジュールを使うとユーザーの新規登録時にメール承認機能をつけることができる。 11-1. モデルにconfirmableを追加 app/models/user.rb user.rb class User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :confirmable end 11-2. メール送信用サーバーの設定 config/environments/development.rb に以下を追記。 development.rb Rails.application.configure do (省略) # mailer setting config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } config.action_mailer.raise_delivery_errors = true config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { :address => 'smtp.gmail.com', :port => 587, :user_name => 'gmailのアドレス', :password => 'gmailのアプリパスワード', :authentication => :plain, :enable_starttls_auto => true } (省略) end 11-3. Deviseのメーラー設定 次に、Deviseのconfigファイルでメーラーを指定する。 config/initializers/devise.rb devise.rb config.mailer_sender = 'gmailのアドレス' 11-4. reconfirmableをfalseにする メールアドレス更新時にメール確認を必須にするreconfirmableをfalseにする。(デフォルトはtrue) config/initializers/devise.rb devise.rb # If true, requires any email changes to be confirmed (exactly the same way as # initial account confirmation) to be applied. Requires additional unconfirmed_email # db field (see migrations). Until confirmed, new email is stored in # unconfirmed_email column, and copied to email column on successful confirmation. config.reconfirmable = false 11-5. アプリパスワードの発行 gmailで自動のアプリケーションを使ってメール送信する場合、PWにはアプリパスワードを指定する必要がある。 ログインしてセキュリティを開く。 ↓ ↓ 「その他」を選択し、名前を適当に入力。 表示されたパスワードをコピーして、:password => 'gmailのアプリパスワード',にペーストする。 これで、現在のrailsアプリケーションで指定したメールサーバーが使えるようになった。 11-6. マイグレーションファイルのconfirmableに必要なカラムを有効化する db/migrate/yyyymmdd_devise_create_users.rb confirmableのコメントアウトを外す。 yyyymmdd_devise_create_users.rb ## Confirmable t.string :confirmation_token t.datetime :confirmed_at t.datetime :confirmation_sent_at t.string :unconfirmed_email # Only if using reconfirmable アプリケーションをctrl + cで終了してから再起動し、rails db:migrateを実行する。 #アプリケーションの起動(プロジェクトのルートディレクトリで) $ docker-compsoe up #コンテナ内に入る $ docker exec -it コンテナ名 sh #マイグレーション $ rails db:migrate 11-7. ブラウザで検証 新規登録時のメール確認なので、/users/sign_upにアクセスする。 「Sign up」をクリックするとTOPページにリダイレクトし、上部に「 本人確認用のメールを送信しました。メール内のリンクからアカウントを有効化させてください。」が表示される。 メール本文 Welcome example@com! You can confirm your account email through the link below: Confirm my account ログイン画面に飛び、「リンクをクリックするとメールアドレスが確認できました」が表示される。 登録したEメールとパスワードを入力すればログインが完了する。 localhostのポート番号が異なる場合はconfig/environments/development.rbで設定。 link_toで生成されるリンク <%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %> confirmation_urlヘルパに@resourceと@tokenの2つの変数を渡している。 11-8. confirmableの送信メールの内容を変更する 初回登録時に送信されるメール内容は以下ファイルに記述されている。 app/views/devise/mailer/confirmation_instructions.html.erb confirmation_instructions.html.erb <p>Welcome <%= @email %>!</p> <p>You can confirm your account email through the link below:</p> <p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p> ↓ confirmation_instructions.html.erb <p>ご登録ありがとうございます。</p> <p>登録されたメールアドレスは<%= @email %>です。</p> <p>下記リンクをクリックして最終承認を完了させてください。</p> <p><%= link_to '「ご登録の承認」', confirmation_url(@resource, confirmation_token: @token) %></p>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

手数料計算のためのjavascript実装手順

furimaアプリの実装中です。 Javascriptの手数料計算自動化の実装中です。 Javascriptファイルを作る ①-1:furimaApp/app/javascript/packs内にファイルを置きます。 ①-2:application.jsファイル内に記述呼び出しの記述をします 書き方 const 変数 = require( モジュール名 ); ①−3ブラウザ上いったんファイル呼び出し確認を行います (注意)railsファイルがきちんとかけていて呼び出せる(綺麗に表示できていること)が前提です。 fee_calculation.js window.addEventListener('load', () => { console.log("OK"); }); **①−4ブラウザを開いたら「command+option+j」 consoleタブでOKとファイル名があれば表示確認OKです。 ①販売価格を Viewファイルから取得する @amamamaouさんありがとうございます。参考になります。 https://qiita.com/amamamaou/items/25e8b4e1b41c8d3211f4 目的 メソッド 返り値 要素が取得 document .getElementById( ” id 名 ” ); HTMLElement / null 参照:UX MILKさん 「JavaScriptでidから要素を取得する方法:getElementById()」 https://uxmilk.jp/11593 HTML 体重を入力して下さい:<input type="text" id="id01"><br/> 身長をメートルで入力して下さい:<input type="text" id="id02"><br/> <input type="button" value="計算" onclick="calcBmi();"> javascript //入力された体重と身長からBMI値を計算するプログラム function calcBmi(){ // idが「id01」のテキストボックスに入力された値を取得して変数weightに代入 var weight = document.getElementById('id01').value; var height = document.getElementById('id02').value; weight = Number(weight); // 入力された文字列を数値に変換する height = Number(height); // 入力された文字列を数値に変換する var bmi = height / (weight * weight); // BMIを計算 alert("あなたのBMI値は" + bmi + "です。"); // 結果を表示 } ②どの時点で取得(発火)するのか決める:イベントハンラー @_ayk_studyさん参考にさせていただきました。 https://qiita.com/_ayk_study/items/519bb661a746f96727ce addEventListenerの書き方 javascript オブジェクト(対象の要素).addEventListener('イベント名',function(){処理内容},false) イベントとはトリガー(拳銃の引き金)のことでいつ発生させるのかのきっかけ【タイミング】のことです。 参考 イベント種類 内容 load Webページの読み込みが完了した時に発動(画像などのリソースすべて含む) click マウスボタンをクリックした時に発動 mousedown マウスボタンを押している時に発動 mouseup マウスボタンを離したときに発動 mousemove マウスカーソルが移動した時に発動 keydown キーボードのキーを押したときに発動 keyup キーボードのキーを離したときに発動 keypress キーボードのキーを押している時に発動 submmit フォームのsubmitボタンを押したときに発動 scroll 画面 ①+②(これはエラーになります) fee_calculation.js const priceInput = document.getElementById("金額を入力する場所のid"); priceInput.addEventListener("input", () => { console.log("イベント発火"); }) これでサーバーを立ち上げると 問題点1document.getElementByIdはHTMLを一度読み込んでからid取得させるが正解でした fee_calculation.js window.addEventListener('load', () => { const priceInput = document.getElementById("item-price"); priceInput.addEventListener("input", () => { console.log("イベント発火"); }) }); ちゃんとイベント発火しました。 4.さらに消費税自動入力にけて行きます fee_calculation.js window.addEventListener('load', () => { const priceInput = document.getElementById("item-price"); priceInput.addEventListener("input", () => { const inputValue = priceInput.value; console.log(inputValue); }) }); constはconstを先頭につけて変数を宣言します。 使い方 const 変数名 = 変数に入れる値; *constとは値書き換えを禁止した変数を宣言する方法。 変数・関数共に基本キャメルケース(camelCase)を用いる。ここではinputValue/priceInputがそれ。 5.いい感じに仕上がってます 価格に入力すると発火します 6.JavaScriptでページ内の特定の位置に文字を出力する iPentec.com さまありがとうございます。 https://www.ipentec.com/document/javascript-get-tag-element-and-access-element コード例 html <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <script type="text/javascript"> window.onload = function onLoad() { target = document.getElementById("output"); target.innerHTML = "Penguin"; } </script> <style> <中略> </style> </head> <body> <div class="header-footer">ヘッダです</div> <div class="contents" id="output"></div> <div class="header-footer">フッタです</div> </body> </html> 7.結果 javascript target = document.getElementById("output"); で html <div class="contents" id="output"></div> の位置を取得します。 次に javascript target.innerHTML = "Penguin"; で先ほどのdivの位置に”Penguin”という文字列を挿入します。 (1)ここから表示場所を特定して表示させます。 const addTaxDom = document.getElementById("販売手数料を表示する場所のid"); addTaxDom.innerHTML = "入力した金額をもとに販売手数料を計算する処理" (2)計算方法 Math.round(priceInput * 0.1 ) 8.でもエラー @haspyokoさんに感謝。全く同じエラーでした。 まずはコンソールでpriceInputの中身から確認 javascript console.log(priceInput) 変数priceInputの中身は <input class="price-input" id="item-price" placeholder="例)300" type="text" name="item[price]"> という文字列でした。 これは掛け算を行っても数値は出ません。 ちなみに JavascriptでNaNは非数「Not-A-Number」を表す値です。 9.完成 あとは変数priceInputの中身を取り出すだけなので 「.value」を後ろにつけるだけ javascript window.addEventListener('load', () => { const priceInput = document.getElementById("item-price"); // console.log(priceInput) priceInput.addEventListener("input", () => { const addTaxDom = document.getElementById("add-tax-price"); // console.log(priceInput.innerHTML); addTaxDom.innerHTML = Math.round(priceInput.value * 0.1 ); const addPofitDom = document.getElementById("profit"); // console.log(priceInput.innerHTML); addPofitDom.innerHTML = Math.round(priceInput.value - Math.round(priceInput.value * 0.1 )) }) }); 完成です 長い間お付き合いいただきありがとうございます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RSpecエラー Failure/Error: expect(show_link[:href]).to eq book_path(book) expected: "/books/1" got: "/books/6"

RSpecでエラー出た 以下Error発生 terminal Failures: 1) 投稿のテスト 一覧画面のテスト 一覧の表示とリンクの確認 bookのタイトルと感想を表示し、詳細・編集・削除のリンクが表示されているか Failure/Error: expect(show_link[:href]).to eq book_path(book) expected: "/books/1" got: "/books/6" (compared using ==) # ./spec/system/books_spec.rb:40:in `block (5 levels) in <main>' # ./spec/system/books_spec.rb:33:in `each_with_index' # ./spec/system/books_spec.rb:33:in `block (4 levels) in <main>' Finished in 1.78 seconds (files took 1.5 seconds to load) 28 examples, 1 failure Failed examples: rspec ./spec/system/books_spec.rb:28 # 投稿のテスト 一覧画面のテスト 一覧の表示とリンクの確認 bookのタイトルと感想を表示し、詳細・編集・削除のリンクが表示されているか 何度調べても、出てこなかったので備忘録として。 このエラー解決した時には、「なんやねん」って感じの単純なミスでした。 index.html.erb index.html.erb ----------省略------------ <tbody> <% @books.each do |b| %> <tr> <td><%= b.title %></td> <td><%= b.body %></td> <td><%= link_to 'Show', book_path(b), class:'jump' %></td> <td><%= link_to 'Edit', edit_book_path(b), class:'jump' %></td> <td><%= link_to 'Destroy', book_path(b), method: :delete, data: { confirm: 'Are you sure?' }, class:'jump' %></td> </tr> <% end %> </tbody> ----------省略------------ 見た感じ、リンクの書き方は合ってる。 terminalでrails routesでpathを確認してください。 私は、routes.rbで以下記述です routes.rb Rails.application.routes.draw do root to: 'home#top' resources :books end 解決法 books_controller.rb class BooksController < ApplicationController def index @books = Book.all.order(created_at: 'desc') < 削除 > @books = Book.all < 追記 > @book = Book.new end < 省略 > end 以上のように、@books = Book.all.order(created_at: 'desc')としていると、降順になるのでidの順番が逆になる。 学んだこと expected: "/books/1" got: "/books/6" のように、params[:id]の数字の部分がexpectedとgotで「違うで」とError表示されたら、コントローラーを確認する 間違っていたら、教えてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

deviseに追加したカラムを保存する方法

概要 deviseはデフォルトでemailやpasswordのカラムは入っている。しかし、nameやnicknameなど新しくカラムを追加した際、以下の手順で保存を行えるようにする app/controllers/application_controller.rb class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? private def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :nickname]) end end end 上記のkeysの中に追加したカラム名を入れることによって保存が行えるようになる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsでEnum宣言を使ってモデルを作成する

enumとは? 日本語訳は、「列挙型」 列挙:一つ一つ数え立てて挙げること。並べ立てること。 カラムに対して、数値ごとに対応する任意の名前をつけることができる。 enum宣言を採用するメリット □ dbの可読性向上、管理しやすい □ 日本語化にも応用が効く 追加したいDB 項目名 フィールド名 型 null 備考 メッセージID id string false 送信元ユーザーID send_by string false 送信先ユーザー send_to string false メッセージ本文 discription text false 作成日時 create_date datetime false APIに送信できたかの確認 api_status string false enum宣言で拡張性を持たせる docker上でレターモデルを追加 作るときは普通にstringで作る..??であってるのかな % docker-compose run --rm web rails g model Letter id:string send_by:string send_to:string discription:text create_date:datetime api_status:string --no-fixture 以下の様なDBファイルができる。 db/migrate/yyyyMMddhhmmss_create_letters.rb class CreateRatings < ActiveRecord::Migration[5.2] def change create_table :letters do |t| t.string :id, null: false t.string :send_by, null: false #...略 t.string :api_status, defalut: 0 #=>ここ。 #...略 end end ここから対象モデルにenum宣言を書き込んでいくだけ。でできるらしい。 app/models/letter.rb class letter < ApplicationRecord  enum api_status: {   sending: 0,   success: 1,   failure: 2}  } end 参照させていただいたサイト様たち ・Qiita. 【Rails】Enumってどんな子?使えるの? ・Qiita. Rails - enumの使い方 ・Qiita. 【enum】 rails enumを利用してデータの可読性をあげよう
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[カラム重複によるerror]Mysql2::Error: Duplicate column name ''カラム名"

概要 ターミナルで「rails db:migrate」を入力した際に起きたerror。インターネットで調べてみるとカラムが重複していることが原因だった。 原因 db/migrateを調べるとemailカラムが重複していた qiita.rb t.string :email, null: false, default: "" t.string :email, null: false, default: "" 改善方法 rails db:rollbackでマイグレーションファイルをdownさせる →重複している内容を削除し、データを1つにする →rails db:migrateする。以上のことでerrorが改善された。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】マイグレーションファイルを変更した後にrails db:migrateをしても変更が反映されない時の対処法

Railsでマイグレーションファイルでカラムを変更した後にrails db:migrateをしても変更が反映されない。 マイグレーションファイルを直接変更した場合、マイグレーションの現在のバージョンとファイルが一致しているため再実行されない。 マイグレーションのバージョンを戻せば再度実行できる。使うのはrails db:rollback。 公式 Railsガイド いったんマイグレーションを実行してしまった後では、既存のマイグレーションを単に編集してもう一度マイグレーションをやり直しても意味がありません。Railsはマイグレーションが既に実行済みであると認識しているので、rails db:migrateを実行しても何も変更されません。 1. db:rollback rails db:rollbackを使って、マイグレーションファイルの内容を一つ前に戻す。 $rails db:rollback $rails db:migrate $rails db:rollback STEP=数値にすると指定した数値分前の状態に戻る。 2. db:migrate:redo Railsにはロールバックとマイグレーションを同時に実行できるrails db:migrate:redoコマンドがある。 $rails db:migrate:redo ↓↑ 同じ $rails db:rollback $rails db:migrate マイグレーションの役割 マイグレーションはDBを直接操作せずにDBの構造(スキーマ)を変更する仕組み。バージョン(履歴)管理ができるため、過去の状態に戻すこともできる。 最初スキーマは空の状態。 マイグレーションを実行するとDBにスキーマが生成される。 マイグレーションを実行する毎にバージョンが更新される。 3. db:reset dbを完全にリセットする。データがなくなるので非推奨。 $rails db:reset $rails db:migrate db:resetコマンドは、db:dropでDBを削除して、db:setupで再設定しているのと同じ。 4. 新しいマイグレーションファイルを作成する 新しいマイグレーションファイルを作成すれば、現在のマイグレーションのバージョンとズレるため、rails db:migrateが実行できるようになる。 4-1. マイグレーションファイルの新規作成 $ rails g migration マイグレーションクラス名 次で、元ファイルをコピペするのでカラムや型は特に指定する必要はない。 もし、指定する場合は以下。 カラムと型を指定する場合 $ rails g migration マイグレーションクラス名 カラム名:型,,, 4-2. マイグレーションファイルの編集 生成したマイグレーションファイルに以前のスキーマをコピペして編集する。 4-3. マイグレーションの実行 マイグレーションファイルの内容をDBに反映させる。 $ rails db:migrate 以上で変更内容の反映が完了。 5. バージョンや履歴の確認方法 履歴の確認 rake db:migrate:statusを実行するとマイグレーションの履歴を確認することができる。(下の方が新しい) # rake db:migrate:status database: rails_screamer_development Status Migration ID Migration Name -------------------------------------------------- up 20110521181506 Create pages up 20110521182915 Create categories up 20110703120321 Add position to pages up 20110716180121 Add position to categories down 20110724110158 Add english name to categorydevise upはDBに適用済み。downは未適用。 $rails db:rollbackを実行するとdownになる。 バージョンの確認 # rails db:version Current version: 20110716180121
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

エラーに遭遇(warning: parser/current is loading parser/ruby27, which recognizes warning: 2.7.3-compliant syntax, but you are running 2.7.2. warning: please see https://github.com/whitequark/parser#compatibility-with-ruby-mri.)

Rails+Docker+VSCodeという環境でVSCodeから表示された警告がみたことがなかったのでメモ。 TL;DR Rubyのバージョンアップは大事(特にパッチレベル) Rubyのバージョンのパッチバージョンが上がったらバージョンアップするべし Dockerの場合は端末側のRubyのバージョン指定も変更するべし 動作環境 21/04時点での動作環境です。 MacOS Catalina(10.15.7) VSCode 1.55.0 Ruby 2.7.3 Rails 6.0.3.6 内容 VSCodeに突然下記のような警告が表示されるようになりました。 warning: parser/current is loading parser/ruby27, which recognizes warning: 2.7.3-compliant syntax, but you are running 2.7.2. warning: please see https://github.com/whitequark/parser#compatibility-with-ruby-mri. cannot load such file -- rubocop-rspec 特にRailsやDockerの設定を変えた覚えはなかったのでとても焦りました。 原因 parserというgemが原因でした。 上記のコメントの中にgithubへのリンクがあったのでその内容をgoogle先生で直訳すると パーサーはセマンティックバージョニングを使用しません。パーサーのバージョンは次のように構成されますx.y.z.t。ここで、x.y.zはサポートされている最新のRubyリリースを示し(時系列的に早いすべてのRubyリリースのサポートを意味します)、t単調に増加する数です。 という内容が書かれていました。 「じゃあいいじゃん、問題ないじゃん」 という話になるのですが、その下に Unfortunately, Ruby MRI often changes syntax in patchlevel versions. This has happened, at least, for every release since 1. と書かれています。 直訳すると、 残念ながら、RubyMRIはパッチレベルバージョンで構文を変更することがよくあります。これは、少なくとも1.9以降のすべてのリリースで発生しています。 どうやらRubyMRIでパッチレベルバージョンでの構文の変更が今回の警告に影響したようです。 Backwards compatibility whitequark/parser: A Ruby parser. 解決法 Rubyのバージョンを上げて、それに伴う変更を行いましょう。 それで解決する(はず)です。 今回の内容はDocker環境・非Docker環境でも流れは一緒(のはず)です。 例えば今回の内容であれば(2.7.2から2.7.3へバージョンアップ)、 使用しているプロジェクトのルートディレクトリで.ruby-versionの数値を変更する(2.7.2->2.7.3) ローカルでrbenvを使用しているなら ruby-buildのアップグレード(brewのアップデートも必要) rbenvで新しいバージョンのrubyをインストール 使用しているプロジェクトに新しいバージョンを適用する といった感じです。 これを手順化すると下記になります(rubyのバージョンはご自身の状況に合わせてください)。 手順1と手順4はそれなりに時間がかかります。 1.terminalで下記を実行してruby-buildのアップグレード、Rubyをインストール terminal brew update && brew upgrade ruby-build && rbenv install 2.7.3 && rbenv local 2.7.3 && rbenv rehash 2..ruby-versionの数値を変更 .ruby-version + 2.7.3 - 2.7.2 3.Gemfileにrubyのバージョンを明記していれば数値を変更 Gemfile + ruby '2.7.3' - ruby '2.7.2' 4.Dockerfileを修正後docker-compose build --no-cacheでコンテナを再構築(Docker環境のみ対象) Dockerfile + FROM ruby:2.7.3 - FROM ruby:2.7.2 上記を実行して特にエラーが発生していなければVSCodeで適当なrubyファイルを開いて保存してみてください。 上記の警告は表示されなくなっていると思います。 以上です。 ありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails ActionCable チャット機能 処理の流れ

はじめに ポートフォリオ作成中の初学者です。 ポートフォリオにActionCableを使った「チャット機能」を導入しました。 ネット上に素晴らしい記事がたくさんあり、実装することはできましたが、 なぜ、そのような書き方なのか、どのような処理の順番なのかなど 理解不十分な部分が多々あった為、今回は処理の流れをメインに備忘録としてここに残します。 ポートフォリオ作成完了後に時間があれば、まとめなおそうと思っています。 ※他の勉強もしたいですが、アウトプットも大事。 知識が乏しく、間違った解釈をしている箇所がありましたら、コメントいただけると幸いです。 開発環境 ・ruby: 2.6.3 ・rails: 5.2.4.5 ・OS: macOS Catalina ver10.15.7 ・Cloud9 ※最近ではRails6でのActionCable実装記事もあります。 前提条件 ・devise導入 ・チャットルームとメッセージの名前はこちら ※テーブル名やカラム名は他記事と異なるかもしれません。 schema.rb create_table "direct_messages", force: :cascade do |t| t.integer "user_id", null: false t.integer "room_id", null: false t.string "message", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "rooms", force: :cascade do |t| t.string "name", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end 他には room.rb rooms_controller.rb direct_message.rb direct_messages.rb room.coffee room_channel.rb direct_message_broadcast_job など 処理の流れ 1: WebSocketによる通信を行う前に一度HTTP通信を行う (サーバーを立ち上げた瞬間) ハンドシェイクという処理 ブラウザ上から「upgrade」というリクエストを行う ↓ サーバー側から「101 Switching Protocols」というレスポンスがくる ↓ これが終わるとそれ以降のデータのやり取りはWebSocketプロトコル上で行われる 2: WebSocketコネクションを確立させるか判断する (connection.rb内でユーザーidを元に、確立させていいか判断している) 3: 指定したchannelをsubscribeする (room_channel内でsubscribedメソッドを実行) subscribedメソッドでは、 サーバー側で受け取った内容をどこに配信(ブロードキャスト)するかを定義している 4: 入力フォームにテキストを入力し、エンターキーを押すとイベントが発火する (room.coffee内) 5: room.coffee内のspeakアクションが呼び出される speakアクションでサーバー側(room_channel.rb)のspeakアクションを呼び出す ※紛らわしいので注意 クライアントサイドのspeakメソッドで、サーバーサイドのspeakメソッドを呼び出している 6: speakアクションでdirect_messageをcreateする (room_channel.rb内) 7: after_create_commitメソッドにより、direct_message_broadcast_job.rbのpeformアクションを呼び出す (direct_message.rb内) 8: subscribedメソッドで決めた場所にデータを配信(ブロードキャスト)する (direct_message_broadcast_job.rb) 9: ブロードキャストを介して、room.coffeeのrecievedメソッドにデータが渡される 10: 受け取ったdirect_message(入力されたメッセージ)を(idがdirect_messageの箇所)にappendする(HTML要素を追加する) (room.coffee内) 専門用語 cousumer(コンシューマ):ユーザーが開くブラウザ1つ1つのこと connection(コネクション):consumerとサーバーのつながり subscribe(サブスクライブ):consumerがchannelと繋がること subscriber(サブスクライバー):channelとつながったconsumerをさす brodecast(ブロードキャスト):サーバーがsubscriberにデータを送ること channel(チャネル):コントローラ的役割(機能毎に分ける) publisher(パブリッシャ):実際に通信を発信するところ(Rails内) broadcast(ブロードキャスト):パブリッシャが出す通信(ストリームに対して) stream(ストリーム):ブロードキャストをサブスクライバーに転送すること コード一覧 connection.rb module ApplicationCable class Connection < ActionCable::Connection::Base # 処理① # ハンドシェイク後、WebSocket通信を確立させるか判断する identified_by :current_user def connect self.current_user = find_verified_user end protected def find_verified_user #ユーザーidで認証する verified_user = User.find_by(id: env['warden'].user.id) # 認証したユーザー(verified_user)出ない限りはreturn return reject_unauthorized_connection unless verified_user verified_user end end end room_channel.rb class RoomChannel < ApplicationCable::Channel # 処理② # サーバー側で受け取った内容をどこに配信するかを定義している # room_channel_1,room_channel_2...とparams['room']にはroomのidが入る # つまり、部屋毎にその部屋にアクセスした人クライアントに配信している def subscribed # stream_from "some_channel" stream_from "room_channel_#{params['room']}" end def unsubscribed # Any cleanup needed when channel is unsubscribed end # 処理⑤ def speak(data) direct_message = DirectMessage.create! message: data['direct_message'], user_id: current_user.id, room_id: params['room'] end end room.coffee document.addEventListener 'turbolinks:load', -> if App.room App.cable.subscriptions.remove App.room # サーバー側のチャネルをcreate # 引数のRoomChannel = app/channels/room_channel.rbで指定されるサーバー側のチャネルにクライアント側から接続する App.room = App.cable.subscriptions.create { channel: "RoomChannel", room: $('#direct_messages').data('room_id') }, connected: -> disconnected: -> # 処理⑧ # サーバー側から送られてきたデータを引数dataで受け取る # 受け取ったdirect_message(入力されたメッセージ)を(idがdirect_messageの箇所)にappendする(HTML要素を追加する) received: (data) -> $('#direct_messages').append data['direct_message'] # 処理④ # room_channel.rbのspeakメソッドを呼び出している speak: (direct_message) -> @perform 'speak', direct_message: direct_message # 処理③ # data-behavior属性がroom_speakerである入力フォームでのキーボード入力イベントで発火 $(document).on 'keypress', '[data-behavior~=room_speaker]', (event) -> if event.keyCode is 13 # 入力されたメッセージを送信する処理をサーバー側に求める App.room.speak event.target.value # サーバー側に処理をお願いした為、入力フォームを空にする(valueで初期値を空に) event.target.value = '' # サーバー側に処理をお願いした為、入力フォームでのデータ送信(クライアント側でのフォーム送信)処理は止める # preventDefault:直前のイベントをキャンセルという意味 event.preventDefault() direct_message.rb class DirectMessage < ApplicationRecord belongs_to :user belongs_to :room has_many :notifications, dependent: :destroy validates :message, presence: true # 処理⑥ after_create_commit { DirectMessageBroadcastJob.perform_later self } end direct_message_broadcast_job.rb class DirectMessageBroadcastJob < ApplicationJob queue_as :default # 処理⑦ def perform(direct_message) ActionCable.server.broadcast "room_channel_#{direct_message.room_id}", direct_message: render_direct_message(direct_message) end private def render_direct_message(direct_message) ApplicationController.renderer.render(partial: 'public/direct_messages/direct_message', locals: { direct_message: direct_message }) end end さいごに なぐり書きですが、一人でも誰かの参考になれば嬉しいです。 閲覧ありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ActiveHashのまとめ

内容的には Pikawakaの「【Rails】active_hashを使って疑似モデルを作ろう」を作るがとっても詳しいので参考にしてください。 https://pikawaka.com/rails/active_hash 問題点1 カラム名が複数単語で命名の場合 きちんと命名規則にのっとて命名しないと怒られる 自サイトの命名の調査 データベース作成段階でカラム名に 日本語 カラム名 配送料負担者 delivery_fee_payment カラム命名規則:小文字英数字とアンダースコアだけ使う。大文字は避ける。(スネークケース)=テーブル名も同じ ■対応するモデル内のrbファイル名 models/delivery_fee_payment.rb class Delivery_fee_payment < ActiveHash::Base self.data = [ { id: 1, delivery_fee_payment_id: '--' }, { id: 2, delivery_fee_payment_id: '着払い(購入者負担)' }, { id: 3, delivery_fee_payment_id: '送料込み(出品者負担)' } ] include ActiveHash::Associations has_many :items end この部分 class モデルクラス名 < ActiveHash::Base あと対応するViewの views/items/new.html.erb #              ①保存される情報のカラム名  ②モデルクラス名(表示情報の配列) *③ ④選択に表示されるカラム <%= f.collection_select(:delivery_fee_payment_id, DeliveryFeePayment.all, :id, :delivery_fee_payment_id, {}, {class:"select-box", id:"item-shipping-fee-status"}) %> *③はカラムへ引き渡すデータの中身:今回は id名(番号)を保存します。 単語1語の場合の命名規則 種類 説明 例 モデル名 lemon モデルクラス名 先頭は大文字で単数形 Lemon モデルのファイル名 先頭は小文字で単数形 lemon.rb テーブル名 先頭は小文字で複数形 lemons 参考:Railsドキュメント https://railsdoc.com/model 単語複数の場合の命名規則 名称 例 解説 モデル名 melon lemon モデルクラス名 MelonLemon 先頭大文字・キャメル・単数形 ファイル名 melon_lemon.rb 先頭小文字・スネーク・単数形 テーブル名 melon_lemons 先頭小文字・スネーク・複数形 ファイル名は、モデル名の単語区切りを「_」にし、すべて小文字にしたもの 参考:@gakkieさんありがとうございます。「Railsにおける命名規則」 https://qiita.com/gakkie/items/3afcd505c786364aa5fa 問題点1 解答 モデルファイル名 models/delivery_fee_payment.rbはOK モデルマイル内 (誤) models/delivery_fee_payment.rb class Delivery_fee_payment < ActiveHash::Base キャメルケースへ変更 (正) models/delivery_fee_payment.rb class DeliveryFeePayment < ActiveHash::Base Viewファイル内 (誤) views/items/new.html.erb <%= f.collection_select(:delivery_fee_payment_id, DeliveryFeePayment.all, :id, :delivery_fee_payment_id, {}, {class:"select-box", id:"item-shipping-fee-status"}) %> キャメルケースへ変更 (正) views/items/new.html.erb <%= f.collection_select(:deliveryFeePayment_id, DeliveryFeePayment.all, :id, :delivery_fee_payment_id, {}, {class:"select-box", id:"item-shipping-fee-status"}) %> 入力補助としてお使いください class Prefecture < ActiveHash::Base self.data = [ { id: 1, prefecture_id: '--' }, {id: 2, prefecture_id: '北海道'}, {id: 3, prefecture_id: '青森県'}, {id: 4, prefecture_id: '岩手県'}, {id: 7, prefecture_id: '宮城県'}, {id: 6, prefecture_id: '秋田県'}, {id: 5, prefecture_id: '山形県'}, {id: 8, prefecture_id: '福島県'}, {id: 9, prefecture_id: '茨城県'}, {id: 10, prefecture_id: '栃木県'}, {id: 11, prefecture_id: '群馬県'}, {id: 12, prefecture_id: '埼玉県'}, {id: 13, prefecture_id: '千葉県'}, {id: 14, prefecture_id: '東京都'}, {id: 15, prefecture_id: '神奈川県'}, {id: 16, prefecture_id: '新潟県'}, {id: 17, prefecture_id: '富山県'}, {id: 18, prefecture_id: '石川県'}, {id: 19, prefecture_id: '福井県'}, {id: 20, prefecture_id: '山梨県'}, {id: 21, prefecture_id: '長野県'}, {id: 22, prefecture_id: '岐阜県'}, {id: 23, prefecture_id: '静岡県'}, {id: 24, prefecture_id: '愛知県'}, {id: 25, prefecture_id: '三重県'}, {id: 26, prefecture_id: '滋賀県'}, {id: 27, prefecture_id: '京都府'}, {id: 28, prefecture_id: '大阪府'}, {id: 29, prefecture_id: '兵庫県'}, {id: 30, prefecture_id: '奈良県'}, {id: 31, prefecture_id: '和歌山県'}, {id: 32, prefecture_id: '鳥取県'}, {id: 33, prefecture_id: '島根県'}, {id: 34, prefecture_id: '岡山県'}, {id: 35, prefecture_id: '広島県'}, {id: 36, prefecture_id: '山口県'}, {id: 37, prefecture_id: '徳島県'}, {id: 38, prefecture_id: '香川県'}, {id: 39, prefecture_id: '愛媛県'}, {id: 40, prefecture_id: '高知県'}, {id: 41, prefecture_id: '福岡県'}, {id: 42, prefecture_id: '佐賀県'}, {id: 43, prefecture_id: '長崎県'}, {id: 44, prefecture_id: '熊本県'}, {id: 45, prefecture_id: '大分県'}, {id: 46, prefecture_id: '宮崎県'}, {id: 47, prefecture_id: '鹿児島県'}, {id: 48, prefecture_id: '沖縄県'} ] include ActiveHash::Associations has_many :items end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails tでMissingHelperError、rails g controllerでalready usedとエラーが出た場合の解決方法

解決方法 IDEを再起動しrails destroy controllerとrails generate controller を実行したところエラーは解消されました。 エラー発生から解決までの手順 rails test実行時、ヘルパーが無いというエラーが発生しました。 ubuntu:~/environment/sample_app (following-users-redo) $ rails t Running via Spring preloader in process 15498 Traceback (most recent call last): 47: from -e:1:in `<main>' 46: from /home/ubuntu/.rvm/rubies/ruby-2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require' 45: from /home/ubuntu/.rvm/rubies/ruby-2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require' 44: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:54:in `load' 43: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:54:in `load' 42: from /home/ubuntu/environment/sample_app/bin/rails:9:in `<main>' 41: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/zeitwerk-2.4.0/lib/zeitwerk/kernel.rb:34:in `require' 40: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require' 39: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi' 38: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register' 37: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi' 36: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require' 35: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/commands.rb:18:in `<main>' 34: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/command.rb:46:in `invoke' 33: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/command/base.rb:69:in `perform' 32: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/thor-1.0.1/lib/thor.rb:392:in `dispatch' 31: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/thor-1.0.1/lib/thor/invocation.rb:127:in `invoke_command' 30: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/thor-1.0.1/lib/thor/command.rb:27:in `run' 29: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/commands/test/test_command.rb:33:in `perform' 28: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/test_unit/runner.rb:39:in `run' 27: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/test_unit/runner.rb:50:in `load_tests' 26: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/test_unit/runner.rb:50:in `each' 25: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/test_unit/runner.rb:50:in `block in load_tests' 24: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/zeitwerk-2.4.0/lib/zeitwerk/kernel.rb:34:in `require' 23: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require' 22: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi' 21: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register' 20: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi' 19: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require' 18: from /home/ubuntu/environment/sample_app/test/helpers/application_helper_test.rb:3:in `<main>' 17: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/zeitwerk-2.4.0/lib/zeitwerk/kernel.rb:34:in `require' 16: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require' 15: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi' 14: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register' 13: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi' 12: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require' 11: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionview-6.0.3/lib/action_view/test_case.rb:10:in `<main>' 10: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionview-6.0.3/lib/action_view/test_case.rb:12:in `<module:ActionView>' 9: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionview-6.0.3/lib/action_view/test_case.rb:13:in `<class:TestCase>' 8: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionpack-6.0.3/lib/action_controller/railties/helpers.rb:19:in `inherited' 7: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionpack-6.0.3/lib/abstract_controller/helpers.rb:109:in `helper' 6: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionpack-6.0.3/lib/action_controller/metal/helpers.rb:94:in `modules_for_helpers' 5: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionpack-6.0.3/lib/abstract_controller/helpers.rb:145:in `modules_for_helpers' 4: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionpack-6.0.3/lib/abstract_controller/helpers.rb:145:in `map!' 3: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionpack-6.0.3/lib/abstract_controller/helpers.rb:150:in `block in modules_for_helpers' 2: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/activesupport-6.0.3/lib/active_support/dependencies/zeitwerk_integration.rb:51:in `require_dependency' 1: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/zeitwerk-2.4.0/lib/zeitwerk/kernel.rb:34:in `require' /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:33:in `require': cannot load such file -- relationships_helper (LoadError) 45: from -e:1:in `<main>' 44: from /home/ubuntu/.rvm/rubies/ruby-2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require' 43: from /home/ubuntu/.rvm/rubies/ruby-2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require' 42: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:54:in `load' 41: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:54:in `load' 40: from /home/ubuntu/environment/sample_app/bin/rails:9:in `<main>' 39: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/zeitwerk-2.4.0/lib/zeitwerk/kernel.rb:34:in `require' 38: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require' 37: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi' 36: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register' 35: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi' 34: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require' 33: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/commands.rb:18:in `<main>' 32: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/command.rb:46:in `invoke' 31: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/command/base.rb:69:in `perform' 30: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/thor-1.0.1/lib/thor.rb:392:in `dispatch' 29: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/thor-1.0.1/lib/thor/invocation.rb:127:in `invoke_command' 28: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/thor-1.0.1/lib/thor/command.rb:27:in `run' 27: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/commands/test/test_command.rb:33:in `perform' 26: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/test_unit/runner.rb:39:in `run' 25: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/test_unit/runner.rb:50:in `load_tests' 24: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/test_unit/runner.rb:50:in `each' 23: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/test_unit/runner.rb:50:in `block in load_tests' 22: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/zeitwerk-2.4.0/lib/zeitwerk/kernel.rb:34:in `require' 21: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require' 20: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi' 19: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register' 18: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi' 17: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require' 16: from /home/ubuntu/environment/sample_app/test/helpers/application_helper_test.rb:3:in `<main>' 15: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/zeitwerk-2.4.0/lib/zeitwerk/kernel.rb:34:in `require' 14: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require' 13: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi' 12: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register' 11: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi' 10: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require' 9: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionview-6.0.3/lib/action_view/test_case.rb:10:in `<main>' 8: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionview-6.0.3/lib/action_view/test_case.rb:12:in `<module:ActionView>' 7: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionview-6.0.3/lib/action_view/test_case.rb:13:in `<class:TestCase>' 6: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionpack-6.0.3/lib/action_controller/railties/helpers.rb:19:in `inherited' 5: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionpack-6.0.3/lib/abstract_controller/helpers.rb:109:in `helper' 4: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionpack-6.0.3/lib/action_controller/metal/helpers.rb:94:in `modules_for_helpers' 3: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionpack-6.0.3/lib/abstract_controller/helpers.rb:145:in `modules_for_helpers' 2: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionpack-6.0.3/lib/abstract_controller/helpers.rb:145:in `map!' 1: from /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionpack-6.0.3/lib/abstract_controller/helpers.rb:149:in `block in modules_for_helpers' /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/actionpack-6.0.3/lib/abstract_controller/helpers.rb:152:in `rescue in block in modules_for_helpers': Missing helper file helpers/relationships_helper.rb (AbstractController::Helpers::MissingHelperError) ubuntu:~/environment/sample_app (following-users-redo) $ ですがrelationships_helper.rb は既に存在しています。 直前でrails generate controller 実行したためここでエラーが発生したことを疑い、生成したファイルを削除します。 ubuntu:~/environment/sample_app (following-users-redo) $ rails destroy controller Relationships Running via Spring preloader in process 15967 remove app/controllers/relationships_controller.rb invoke erb remove app/views/relationships invoke test_unit remove test/controllers/relationships_controller_test.rb invoke helper remove app/helpers/relationships_helper.rb invoke test_unit invoke assets invoke scss remove app/assets/stylesheets/relationships.scss ubuntu:~/environment/sample_app (following-users-redo) $ 再度rails testを実行したところエラーは発生しなくなりました。 ubuntu:~/environment/sample_app (following-users-redo) $ rails t Running via Spring preloader in process 16013 Started with run options --seed 28970 63/63: [===========================================================] 100% Time: 00:00:06, Time: 00:00:06 Finished in 6.37105s 63 tests, 294 assertions, 0 failures, 0 errors, 0 skips ubuntu:~/environment/sample_app (following-users-redo) $ ところが再度rails generate controller したところ下記エラーが発生しました。 ubuntu:~/environment/sample_app (following-users-redo) $ rails generate controller Relationships Running via Spring preloader in process 16096 create app/controllers/relationships_controller.rb invoke erb create app/views/relationships invoke test_unit create test/controllers/relationships_controller_test.rb invoke helper The name 'RelationshipsHelper' is either already used in your application or reserved by Ruby on Rails. Please choose an alternative or use --force to skip this check and run this generator again. ubuntu:~/environment/sample_app (following-users-redo) $ "RelationshipsHelperという名前は、アプリケーションですでに使用されているか、Ruby on Railsによって予約されています。代替案を選択するか、--forceを使用してこのチェックをスキップし、再度このジェネレータを実行してください。" IDEを再起動しrails destroy controllerとrails generate controller を実行したところエラーは解消されました。 ubuntu:~/environment/sample_app (following-users-redo) $ rails destroy controller Relationships Running via Spring preloader in process 4130 remove app/controllers/relationships_controller.rb invoke erb remove app/views/relationships invoke test_unit remove test/controllers/relationships_controller_test.rb invoke helper remove app/helpers/relationships_helper.rb invoke test_unit invoke assets invoke scss remove app/assets/stylesheets/relationships.scss ubuntu:~/environment/sample_app (following-users-redo) $ rails generate controller Relationships Running via Spring preloader in process 4153 create app/controllers/relationships_controller.rb invoke erb create app/views/relationships invoke test_unit create test/controllers/relationships_controller_test.rb invoke helper create app/helpers/relationships_helper.rb invoke test_unit invoke assets invoke scss create app/assets/stylesheets/relationships.scss なぜこの手順で解決できたかまでは詰めることができませんでした。 調べたところ同じような事象で解決されている方がいましたが、場合によって解決方法が異なるようでした。 参考: https://qiita.com/KuroganeHey/items/962fc74669ef7f4221dd
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

クラスとインスタンス

定義 class あるものを作る時の設計図のこ設計図のこと class クラス名  #(処理の内容) end インスタンス 設計図からつくられた「もの」のこと 処理の手順 ① クラスの作成 ② クラス内に情報を書き込む ③ クラスを元にインスタンスを作る ④ インスタンスに情報を与える 実例 class Human attr_accessor :name attr_accessor :Height end human = Human.new human.name = A太郎
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】database.ymlの「気になる」を調べてみた

背景 Railsのデータベースを作成する時にdatabase.ymlを修正したりしますが、その中で気になっていたところについて関連記事を探してまとめてみました。 database.ymlの中身 まずはdatabase.ymlファイルを開いてみました。保存場所は「hoge/config/database.yml」にあります。 アプリ名は「hoge」という名前で作成。 default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: socket: /tmp/mysql.sock development: <<: *default database: hoge_development test: <<: *default database: hoge_test production: <<: *default database: hoge_production username: root password: <%= ENV['DATABASE_PASSWORD'] %> socket: /var/lib/mysql/mysql.sock ファイルの中身は大きく分けて①default②development③test④productionとなっていることが分かります。①のdefaultは基本設定で②のdevelopmentは開発環境、③のtestはテスト環境、④のproductionは開発環境であることが何となく分かります。上記の中でも気になった記述がいくつかあったので調べてみました。 「&default」、「<<:」、「*default」について ①「&」はアンカー 「&」の部分はアンカーという「YAML」の記述方法。「YAML」とは今回でいうと拡張子が「.yml」になっているファイルのこと。今回の場合、「database.yml」を指します。「&」に続けて「default」という名前をつけると、「default」という名前でハッシューのデータを保存することができます。つまり、「&default」とすると、 default: adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: socket: /tmp/mysql.sock の内容が「default」という名前で丸ごと保存されることになります。 ②「」はエイリアス 「」をつけることによって、アンカーの内容を呼び出します。 ③「<<:」の意味は? エイリアスで呼び出した内容を付け足すという意味。「マージ」するといいます。 要するに同じ内容を繰り返し書くのではなくて、「default」という名前で変数みたいに保存しておいて、重複しそうな箇所に付け加えることですね。 ENV.fetch("RAILS_MAX_THREADS"){ 5 }とは ENVはルビのオブジェクトであり、ENV["環境変数名"]で環境変数を呼び出すことができます。「.fetch」はENVオブジェクトが持つメソッド。「.fetch("環境変数名"){ 値 }」とすると「"環境変数名"=key」が存在すれば環境変数の値を返し、存在しなければデフォルト値として{ 値 }を返す意味になります。環境変数はMACの場合ターミナルで「vim ~/.zshrc」と入力すれば確認できます。「export RAILS_MAX_THREADS='値'」がなければ「pool: 5」になりますね。 poolとは 「コネクションプール」。データベースへ接続した時の接続状態を保存しておく役割をします。データベースに再接続する場合、この「コネクションプール」を利用することによって接続時間を短縮する仕組みらしいです。この「コネクションプール」の数が足りないとリクエストに対する待ち時間が増えてしまい、「ActiveRecord::ConnectionTimeoutError」などが発生するんだとか。デフォルト値は5。 adapter 接続するデータベースの種類。Railsで利用できるデータベース公式ドキュメントでは DB2 Firebird Frontbase MySQL Openbase Oracle PostgreSQL SQLite SQL Server Sybase になっています。 socketとは ネットとプログラムを繋げる出入り口を示します。mysqlの場合、localhost(自分のpc)では「/tmp/mysql.sock」で、 RPM【Red Hat Package Manager】のCentOS上だと「/var/lib/mysql/mysql.sock」になるみたいです。 結論 ネットワークの知識は知っておくとプログラミングとは直接関係はないけど、知っておくことによってより理解が深まり学習が楽しくなります。特にバックエンドエンジニアにとってはサーバーとのやりとりでデータベースは欠かせないものなので、関連知識を身につけるのは非常に良いと思いました。また、ymlというファイル形式についても学習を進めたいと思います。 参考サイト&記事 https://railsdoc.com/config https://qiita.com/ryouya3948/items/ba3012ba88d9ea8fd43d https://qiita.com/katsuyuki/items/42b3c69bcd76c44ad64a https://qiita.com/sukebeeeeei/items/576f109d57218c8397d5 https://qiita.com/terufumi1122/items/b5678bae891ba9cf1e57 https://www.wakuwakubank.com/posts/488-it-yaml/ https://docs.ruby-lang.org/ja/latest/method/ENV/s/fetch.html https://qiita.com/megadreams14/items/32a3eed4661e55419e1c https://dev.mysql.com/doc/refman/5.6/ja/problems-with-mysql-sock.html
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む