20210412のRailsに関する記事は24件です。

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

これは何? React+Railsで簡単なタスク管理アプリを作っています。 一覧画面からタスク名のリンクをクリックすると、詳細画面が現れます。 実行環境は以下の通りです。 Rails 6.0.3 React 17.0.2 また、今回のディレクトリ構成は以下の通りです。(関係のある箇所だけ表示) . ├── controllers │   └── api │      └── tasks_controller.rb └── javascript    └── pages    ├── Task.jsx    └── Tasks.jsx Rails側 spaではないRailsのアプリとほぼ変わりありません。/api配下に置いたコントローラーにindex(実装については前回の記事をご参照ください)とshowアクションを記載します。 render json: ...でJSON形式でビューを描画します。 app/controllers/api/tasks_controller.rb class Api::TasksController < ApplicationController def index @tasks = current_user.tasks render json: @tasks end def show @task = current_user.tasks.find(params[:id]) render json: @task end end SPA側(一覧表示画面) タスク一覧表示画面(Tasksコンポーネント)に実際に書いたコードがこちらです。 app/javascript/pages/Tasks.jsx import React, {useState} from 'react' import { Link, withRouter } from 'react-router-dom' import axios from 'axios' export const Tasks = withRouter(() => { // ★2解説します const [tasks, setTasks] = useState([]) React.useEffect(async () =>{ const response = await axios.get('/api/tasks'); setTasks(response.data) }, []) return ( <div> <h1>タスク一覧</h1> <table> // 中略 <tbody> {tasks.map(task => ( <tr key={task.id}> <td> <Link to={{ // ★1解説します pathname: "/spa/tasks/" + task.id, state: {id: task.id}, }}>{task.name}</Link> </td> // 中略 </tr> ))} </tbody> </table> </div> ) }) react-router と react-router-dom まず、調べていて迷ったのが、react-routerとreact-router-domがあるっぽいということ。その点は、こちらの記事が非常に丁寧に解説してくれていました。 react-routerとreact-router-domの違い 要するに、react-router-domの方が新しくて使い勝手も良いそうなので、react-router-domを使いましょう、とのことでした。 Link to ポイントの一つ目はこの部分(★1)で、 <Link to={{ pathname: "/spa/tasks/" + task.id, state: {id: task.id}, }}>{task.name}</Link> react-router-domのLinkという関数で、遷移先や遷移先のページに送るデータなどが指定できます。詳しくは公式のAPIドキュメントがわかりやすかったですが、 Link 上記を指定することで、受取手側のコンポーネントではlocatitonで以下のような情報が取得できました。 console.log(location) => {pathname: "/spa/tasks/1", state: {id: 1}, search: "", hash: "", key: "5ox837"} withRouter ただし、上記だけではlocationのstateがundefined になります。調べてみるとwithRouterでラップしてねという回答がたくさん出てきたので、今回も以下のように全体をラップしてみました(★2)。 export const Tasks = withRouter(() => { // 略 }) 公式のドキュメントもみてみると、 withRouter withRouter will pass updated match, location, and history props to the wrapped component whenever it renders. (withRouterは、レンダリングされるたびに、更新されたmatch、location、およびhistoryのpropsをラップされたコンポーネントに渡します。) とのことでした。Functional ComponentでのwithRouterの使い方は、こちらを参考にしました。 Functional ComponentでもReact RouterのwithRouterを使う方法 完成 以上で、実装は終わりになります。 まさかShowアクションでここまで調べることになるとは思わなかった...^^ 本日はDestroyアクションも試してみたのですが、そちらはまた別の機会に記事にしたいです。 ではでは。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

(Ubuntu)Ruby on Rails6 環境構築のやり方【自分用メモ】

はじめに 本記事はRuby on Rails を gem install rails コマンドを使わない方法で環境構築を行っていくものです。 また、本記事は自分用メモとして記述しています。ご容赦下さい。 開発環境 Ubuntu 20.04.2 コンパイラおよび必要なツールのインストール コンパイラおよび必要なツールをインストール # パッケージ一覧を更新 (リポジトリ追加・削除時には必ず実行すること) $ sudo apt update -y # パッケージを更新 (通常のパッケージ更新時はこのコマンドを仕様する) $ sudo apt upgrade -y # 開発に必須のビルドツールを提供しているパッケージ $ sudo apt install build-essential $ sudo apt install -y libssl-dev libreadline-dev zlib1g-dev データベース管理システムのインストール データベース管理システム # SQLite3を利用する場合にインストールするコマンド $ sudo apt install libsqlite3-dev # MySQLを利用する場合にインストールするコマンド $ sudo apt-get install libmysqlclient-dev # PostgreSQLを利用する場合にインストールするコマンド $ sudo apt-get install Postgresql-common $ sudo apt-get install libpq-dev Rubyをインストール Ruby # rbenv (パッケージ管理ツール) のインストール $ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv # 環境変数にPathを設定する $ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc $ echo 'eval "$(rbenv init -)"' >> ~/.bashrc #シェルを再起動 $ exec $SHELL -l #ruby-buildをインストール $ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build #Rubyをインストール(Rails6を動かすには、Ruby Version 2.5以上が必要) $ rbenv install 2.6.2 $ rbenv global 2.6.2 #Rubyのバージョンを確認 $ ruby -v #ruby 2.6.2 になっていることを確認 Node.jsをインストール Node.js # node.jsとnpmをインストール $ sudo apt install -y nodejs npm #n packageをインストール $ sudo npm install n -g #n packageを使ってnodeをインストール $ sudo n stable # 最初に入れた古いnode.js, npmを削除 $ sudo apt purge -y nodejs npm #シェルを再起動 $ exec $SHELL -l # yarn packageをインストール $ sudo npm install yarn -g # node.jsのバージョンが最新か確認 $ node -v Railsのセットアップ セットアップ # プロジェクトのディレクトリを作成 $ mkdir example_folder # 作成したディレクトリに移動する $ cd example_folder # bundle init を実行してGemfileを作成 $ bundle init # Gemfileを開き【# gem 'rails'】の部分をコメントアウトする $ nano Gemfile # rails をインストールするために bundle install $ bundle install --path vendor/bundle # rails new コマンドを実行して、rails に関する gem をまとめてインストールする $ bundle exec rails new . サーバーを起動する 起動 # サーバーを起動するコマンド $ bundle exec rails s 終わりに プログラムの勉強をサボらないようにするために、Qiitaの投稿を1週間に1回投稿できたら良いな〜と思いました。 参考資料 aptコマンドチートシート Rubyのインストール方法(Ubuntu編) Ubuntuに最新のNode.jsを難なくインストールする
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cloudinaryで使える日本語フォント

こんな人におすすめ cloudinaryで日本語をオーバーレイさせたい。 見た目に特に拘らない(最低限でいい) 設定触るのがめんどくさい 困ったこと CloudinaryのテキストオーバーレイがGoogleのウェブフォントをサポートしていると書いてあるが実際に使えるフォントが見つからない。(Noto系が使えないのが致命的すぎる。。。) 公式でsupports all of Google's fontsって書いてるのに、、、、 https://support.cloudinary.com/hc/en-us/articles/203352832-What-is-the-list-of-supported-fonts-for-text-overlay-transformation- 対応手段 カスタムフォントを使う なんとか使える日本語フォントを探す 対応としてはカスタムフォントを使うのが一般的みたい。 でも、otfファイルDLしたり、uploadの設定したり必要なのが手間。 きっと同じく困ってる人いるんじゃないかな?ってことで意地で探すことに。 結果 この67種類は大丈夫っぽい。(2021/04/12時点) TakaoExGothic, TakaoExMincho, TakaoGothic, TakaoMincho, TakaoPGothic, TakaoPMincho Sawarabi Gothic こんな感じで試してみてください。 (フォント名に半角スペースを含む場合は「%20」で置き換えるが必要) ~/l_text:TakaoGothic_40:くらうでぃなりー/~.png ~/l_text:Sawarabi%20Gothic_40:くらうでぃなりー/~.png 最後に cloudinaryは設定がすごく簡単で個人開発程度なら無料枠で全然余裕でいいなと。 ただ、既に動かしてるサイトに導入する際はこの辺気をつけた方がいいです。 S3使ってると読み込みできなくなる。(設定すれば問題ない) railsのimage_tagバグる。(ymlで設定すれば問題ない)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rubyの環境構築の備忘録(アプリケーション開発のための環境構築編)

Rubyの環境構築(OSがMojave以前) Command Line Toolsをインストール ターミナル $ xcode-select --install Homebrewをインストール ターミナル $ cd #ホームディレクトリに移動 $ pwd #ホームディレクトリにいるかどうか確認 $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" # コマンドを実行 Password:と表示されたらPCのパスワードを入力 brew -vでインストールされているか確認 ターミナル $ brew -v Homebrew 2.5.1 Homebrewをアップデート ターミナル $ brew update Homebrewの権限を変更 ターミナル $ sudo chown -R `whoami`:admin /usr/local/bin 新しいバージョンのRubyをインストール rbenv と ruby-buildをインストール ターミナル $ brew install rbenv ruby-build rbenvをPCにおけるどこの場所からも使用できるようにする ターミナル $ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile bash_profileの変更を反映 ターミナル $ source ~/.bash_profile readlineをinstall ターミナルのirb上で日本語入力を可能にする設定を行うため ターミナル $ brew install readline readlineをどこからも使用できるようにする ターミナル $ brew link readline --force rbenvを利用してRubyをインストール Webアプリケーション開発用のRubyをインストール ターミナル $ RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline)" $ rbenv install 2.6.5 利用するRubyのバージョンを指定 インストールしたRuby 2.6.5を使用するために、以下のコマンドを実行 ターミナル rbenv global 2.6.5 rbenvを読み込んで変更を反映 ターミナル $ rbenv rehash Rubyのバージョンを確認 ターミナル $ ruby -v MySQLをインストール MySQLをインストール ターミナル $ brew install mysql@5.6 MySQLの自動起動設定 ターミナル $ mkdir ~/Library/LaunchAgents $ ln -sfv /usr/local/opt/mysql\@5.6/*.plist ~/Library/LaunchAgents $ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql\@5.6.plist mysqlコマンドをPCのどこからでも実行できるようにする ターミナル # mysqlのコマンドを実行できるようにする $ echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.bash_profile $ source ~/.bash_profile # mysqlのコマンドが打てるか確認する $ which mysql # 以下のように表示されれば成功 /usr/local/opt/mysql@5.6/bin/mysql mysqlの起動の確認 ターミナル # mysqlの状態を確認するコマンド $ mysql.server status # 以下のように表示されれば成功 SUCCESS! MySQL running Railsを用意 bundlerをインストール ターミナル $ gem install bundler --version='2.1.4' Railsをインストール ターミナル $ gem install rails --version='6.0.0' rbenvを再読み込みして変更を反映 ターミナル $ rbenv rehash Railsが導入できたか確認 ターミナル % rails -v Rails 6.0.0 Node.jsを導入 Node.jsのインストール ターミナル $ brew install node@14 Node.jsへのパスを設定 ターミナル $ echo 'export PATH="/usr/local/opt/node@14/bin:$PATH"' >> ~/.bash_profile $ source ~/.bash_profile Node.jsが導入できたか確認 ターミナル $ node -v v14.15.3 yarnを導入 yarnをインストール ターミナル brew install yarn yarnが導入できたか確認 ターミナル $ yarn -v 終了
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

アプリケーション開発のための環境

Rubyの環境構築(OSがMojave以前) Command Line Toolsをインストール ターミナル $ xcode-select --install Homebrewをインストール ターミナル $ cd #ホームディレクトリに移動 $ pwd #ホームディレクトリにいるかどうか確認 $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" # コマンドを実行 Password:と表示されたらPCのパスワードを入力 brew -vでインストールされているか確認 ターミナル $ brew -v Homebrew 2.5.1 Homebrewをアップデート ターミナル $ brew update Homebrewの権限を変更 ターミナル $ sudo chown -R `whoami`:admin /usr/local/bin 新しいバージョンのRubyをインストール rbenv と ruby-buildをインストール ターミナル $ brew install rbenv ruby-build rbenvをPCにおけるどこの場所からも使用できるようにする ターミナル $ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile bash_profileの変更を反映 ターミナル $ source ~/.bash_profile readlineをinstall ターミナルのirb上で日本語入力を可能にする設定を行うため ターミナル $ brew install readline readlineをどこからも使用できるようにする ターミナル $ brew link readline --force rbenvを利用してRubyをインストール Webアプリケーション開発用のRubyをインストール ターミナル $ RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline)" $ rbenv install 2.6.5 利用するRubyのバージョンを指定 インストールしたRuby 2.6.5を使用するために、以下のコマンドを実行 ターミナル rbenv global 2.6.5 rbenvを読み込んで変更を反映 ターミナル $ rbenv rehash Rubyのバージョンを確認 ターミナル $ ruby -v MySQLをインストール MySQLをインストール ターミナル $ brew install mysql@5.6 MySQLの自動起動設定 ターミナル $ mkdir ~/Library/LaunchAgents $ ln -sfv /usr/local/opt/mysql\@5.6/*.plist ~/Library/LaunchAgents $ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql\@5.6.plist mysqlコマンドをPCのどこからでも実行できるようにする ターミナル # mysqlのコマンドを実行できるようにする $ echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.bash_profile $ source ~/.bash_profile # mysqlのコマンドが打てるか確認する $ which mysql # 以下のように表示されれば成功 /usr/local/opt/mysql@5.6/bin/mysql mysqlの起動の確認 ターミナル # mysqlの状態を確認するコマンド $ mysql.server status # 以下のように表示されれば成功 SUCCESS! MySQL running Railsを用意 bundlerをインストール ターミナル $ gem install bundler --version='2.1.4' Railsをインストール ターミナル $ gem install rails --version='6.0.0' rbenvを再読み込みして変更を反映 ターミナル $ rbenv rehash Railsが導入できたか確認 ターミナル % rails -v Rails 6.0.0 Node.jsを導入 Node.jsのインストール ターミナル $ brew install node@14 Node.jsへのパスを設定 ターミナル $ echo 'export PATH="/usr/local/opt/node@14/bin:$PATH"' >> ~/.bash_profile $ source ~/.bash_profile Node.jsが導入できたか確認 ターミナル $ node -v v14.15.3 yarnを導入 yarnをインストール ターミナル brew install yarn yarnが導入できたか確認 ターミナル $ yarn -v 終了
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

アプリケーション開発のための環境構築

Rubyの環境構築(OSがMojave以前) Command Line Toolsをインストール ターミナル $ xcode-select --install Homebrewをインストール ターミナル $ cd #ホームディレクトリに移動 $ pwd #ホームディレクトリにいるかどうか確認 $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" # コマンドを実行 Password:と表示されたらPCのパスワードを入力 brew -vでインストールされているか確認 ターミナル $ brew -v Homebrew 2.5.1 Homebrewをアップデート ターミナル $ brew update Homebrewの権限を変更 ターミナル $ sudo chown -R `whoami`:admin /usr/local/bin 新しいバージョンのRubyをインストール rbenv と ruby-buildをインストール ターミナル $ brew install rbenv ruby-build rbenvをPCにおけるどこの場所からも使用できるようにする ターミナル $ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile bash_profileの変更を反映 ターミナル $ source ~/.bash_profile readlineをinstall ターミナルのirb上で日本語入力を可能にする設定を行うため ターミナル $ brew install readline readlineをどこからも使用できるようにする ターミナル $ brew link readline --force rbenvを利用してRubyをインストール Webアプリケーション開発用のRubyをインストール ターミナル $ RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline)" $ rbenv install 2.6.5 利用するRubyのバージョンを指定 インストールしたRuby 2.6.5を使用するために、以下のコマンドを実行 ターミナル rbenv global 2.6.5 rbenvを読み込んで変更を反映 ターミナル $ rbenv rehash Rubyのバージョンを確認 ターミナル $ ruby -v MySQLをインストール MySQLをインストール ターミナル $ brew install mysql@5.6 MySQLの自動起動設定 ターミナル $ mkdir ~/Library/LaunchAgents $ ln -sfv /usr/local/opt/mysql\@5.6/*.plist ~/Library/LaunchAgents $ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql\@5.6.plist mysqlコマンドをPCのどこからでも実行できるようにする ターミナル # mysqlのコマンドを実行できるようにする $ echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.bash_profile $ source ~/.bash_profile # mysqlのコマンドが打てるか確認する $ which mysql # 以下のように表示されれば成功 /usr/local/opt/mysql@5.6/bin/mysql mysqlの起動の確認 ターミナル # mysqlの状態を確認するコマンド $ mysql.server status # 以下のように表示されれば成功 SUCCESS! MySQL running Railsを用意 bundlerをインストール ターミナル $ gem install bundler --version='2.1.4' Railsをインストール ターミナル $ gem install rails --version='6.0.0' rbenvを再読み込みして変更を反映 ターミナル $ rbenv rehash Railsが導入できたか確認 ターミナル % rails -v Rails 6.0.0 Node.jsを導入 Node.jsのインストール ターミナル $ brew install node@14 Node.jsへのパスを設定 ターミナル $ echo 'export PATH="/usr/local/opt/node@14/bin:$PATH"' >> ~/.bash_profile $ source ~/.bash_profile Node.jsが導入できたか確認 ターミナル $ node -v v14.15.3 yarnを導入 yarnをインストール ターミナル brew install yarn yarnが導入できたか確認 ターミナル $ yarn -v 終了
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby on Rails × Shopify Customer API で顧客情報を操作してみる

概要 業務の一環でShopifyのCustomer APIを使い外部からShopify側で保持する顧客情報を操作する機会があったので、手順などについてメモ書きしておきたいと思います。 前提条件 Shopify Multipass APIを用いたSSO(シングル・サイン・オン)が実装されている事。 参照記事: Ruby on Rails × Shopify Multipass APIでSSO(シングル・サイン・オン)を試してみる 本記事は↑の続きを想定しつつ書いていくつもりです。もしまだ読んでいない場合は目を通しておいてください。 Tipsにも書いてある通り、Multipass APIによるSSOを実運用する場合、Shopify ⇄ SSO基盤におけるデータの整合性を担保する必要があります。 特にメールアドレスはユニーク識別子とされているため、常に一意のものでなければなりません。もし仮に両者の整合性が取れなくなってしまうと、全く別のユーザーとしてログインしてしまう事になります。 そこで、たとえばSSO基盤側で登録情報を変更した場合などは、同時にShopify側の情報も変更するような仕組みを作っておかなければならないというわけですね。 https://shopify.dev/docs/admin-api/rest/reference/customers/customer Shopifyが提供するCustomer APIを使えばその要件が満たせるので、今回はそちらを試してみようと思います。 下準備 まず、Shopify APIを使用するための各種キーを発行しなければなりません。 Shopify管理画面から「アプリ管理」→「プライベートアプリを管理する」へと進んでください。 右上の「新しいプライベートアプリを作成する」をクリック。 プライベートアプリ名 わかりやすい名前でOK 緊急連絡用開発者メール 連絡のつきやすいメールアドレス Admin API権限 顧客管理(読み取りおよび書き込み) Webhook APIのバージョン とりあえず最新のものでOK それぞれ必要な情報を記入し、プライベートアプリを作成してください。 上手くいくとこんな感じで APIキー パスワード が発行されるので、メモなどに控えておきましょう。(後ほど使用します。) 実装 では、コードを書いていきます。 https://github.com/kazama1209/shopify-multipass-api-on-rails ↑の続きとなっているので、手元にコードが無い場合はgit cloneなどしておいてください。 なお、今回Shopify Customer APIを叩くタイミングとして想定しているのは メールアドレス変更時 ユーザー退会時 の2つです。 SSO基盤側でのメールアドレス変更時にShopify側のメールアドレスも変更しておかないと、次回ログインする際に別人として認識されてしまいますし、ユーザー退会時も何かしらの形でShopify側のメールアドレスを書き換えておかないと、もし後に同じメールアドレスを用いて再度SSO基盤側でユーザーを作成した際、Multipassログインができなくなってしまうからです。(Shopifyにおいて同一メールアドレスは複数存在し得ないため) したがって、その辺のアクション実行時にAPI処理を挟んでいきます。 gemをインストール Shopify公式からAPI用のgemがリリースされているので、そちらをインストールしましょう。 ./Gemfile gem 'shopify_api' $ docker-compose build ライブラリを作成 $ touch lib/shopify_customer.rb ./lib/shopify_customer.rb class ShopifyCustomer # 初期設定 def initialize shop_url = "https://<APIキー>:<パスワード>@<ストアのドメイン>" ShopifyAPI::Base.site = shop_url ShopifyAPI::Base.api_version = "2021-04" ShopifyAPI::Shop.current end # SSO基盤側でユーザー情報の変更(メールアドレスなど)を行った際、Shopify側の顧客情報を変更する。 # 引数はキーワード引数形式で渡す(email: hoge@example.com, address: hogefugapiyo)。 def update(multipass_identifier, **args) # Multipassログイン時に渡している「multipass_identifer」をもとに顧客情報を取得。 customer = ShopifyAPI::Customer.search(multipass_identifier: multipass_identifier)[0] return false if customer.nil? customer.update_attributes(args) true rescue => e return false, e end end 使えるメソッドなどについては公式ドキュメントを参照。 https://github.com/Shopify/shopify_api/blob/master/lib/shopify_api/resources/customer.rb メールアドレス変更時のAPI処理 ./app/controllers/users/registrations_controller.rb # PUT /resource def update super ShopifyCustomer.new.update(resource.id, email: resource.email) end 「Devise::RegistrationsController」を継承した「Users::RegistrationsController」内のupdateメソッドのコメントアウトを外し、オーバーライドします。 http://localhost:3000/users/edit にアクセスすると登録情報を変更できる画面に飛ぶので、試しに適当にメールアドレスを変更してみてください。 Shopify管理画面を見るとAPI経由で同時にメールアドレスが変更されているのを確認できるはず。 ユーザー退会時のAPI処理 ./app/controllers/users/registrations_controller.rb # DELETE /resource def destroy super ShopifyCustomer.new.update(resource.id, email: "retired_user_#{resource.id}@example.com", tags: "withdrawn" # 退会した事がわかるようにタグを付与 ) end 先ほどと同じ要領で「destroy」メソッドのコメントアウトを外してオーバーライド。 現状、Multipassログインによって作成されたShopifyのユーザーはAPI経由で削除できないみたいなので(おそらく仕様?)、メールアドレスを適当な文字列で上書きする事で実質削除する「論理削除」的な処理で対応します。 http://localhost:3000/users/edit の最下部にある「Cancel my account」をクリックしましょう。 Shopify管理画面を見るとメールアドレスが「retired_user_{SSO基盤側のユーザーID}@example.com」で上書きされ、退会した事が一目でわかる「withdrawn」タグが付与されているのを確認できます。 あとがき 以上、Shopify Customer APIを使って外部から顧客情報を操作してみました。実運用においてはもっと詳細なエラーハンドリングなどを行う必要があるでしょうが、ひとまず最低限の構成にはなっていると思います。 Shopify Multipass APIを用いたSSOは非常に手軽で便利なのですが、Shopify ⇄ SSO基盤間のデータの整合性を保つための工夫をしないと後々不具合が生じかねないため、上手くやりくりしたいところです。 もちろん、Shopifyでは顧客情報以外にも色々なリソースを操作できるので、公式ドキュメントを参考に色々試してみると良いかもしれません。 今回作成したアプリのソースコード:: https://github.com/kazama1209/shopify-customer-api-on-rails
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

railsの仕組み

こんばんは、taroです! 今日は自分用のメモとしてrailsのアウトプットをしていきます。 まずrailsには親玉としてapp/というディレクトリが存在します。 そして、その子分としてmodels」「views」「controllers」 という3つのサブディレクトリがいます。 ブラウザがRailsアプリと通信するとき、Webサーバーにリクエストを送ります。 リクエストはコントローラに渡されます。(そこでリクエストを処理。) コントローラは、ビューを作ってHTMLをブラウザに送ります。 以上になります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【ActiveStorage】アソシエーションを組んでいるのに画像が表示されない。

こんにちは、プログラミング初学者のkoheiです。 今日は Active Storageをインストールし、アソシエーションを組んでいるのに画像が表示されない。 ということがありました。 ビューファイルを制作するためにtestで1つだけレコードを作成。 Active Storageで画像は保存できています。 それなのにimage_tagで画像を呼び出せませんでした。 結論から言うと、 変数に代入したパラメーターへの認識の甘さが原因でした。 今回登場するのは"parts"コントローラーとビューのみです。 まず partsコントローラーにて def index @parts = Part.all end ビューファイルにて <%= image_tag @parts.image if @parts.image.attached? %> と記述しました。 するとNoMethodErrorがでます。 上記で既に間違っているので、慣れている方は普通に気付くんだと思います。 しかし、初心者の私は焦ります。笑 エラー文に undefined method `image' for #Part::ActiveRecord_Relation:0x00007f8566f76140 とあったため @partsのパラメーターを確認したところ、 imageが含まれていないじゃないか! ということでモデルからマイグレーションファイルまで覗き始めました。笑 ↑ちなみに含まれてないことは問題ではありませんでした! 色々探して最終的に間違いはコントローラーにあることに気づきます。 以下のように記述すべきでした。 def index @parts = find(2) end Part.allがダメだった理由としては allとすることで@partsに代入される値がハッシュ構造となってしまうためです 確認するとパラメーターは以下の様になっていました。 @parts => [#<Part:0x00007fb31f995b90 id: 2, name: "test", info: "test"] Part.find(2)だと以下の様になります。 @parts => #<Part:0x00007fb31ffc6758 id: 2, name: "test", info: "test" アプリとしてはpartsを一覧表示させたいので 最終的にはPart.allとeach文で進めていきます。 とにかく、allの中身が1つでも配列で出力されるということが分かり、自分としてはとても勉強になりました。 同じく初心者の方はお気をつけ下さい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HerokuからAWSに移行後のActionCableの設定方法

概要 本日、本番環境をHerokuからAWSに移行後、ブラウザ上で動作を確認したら、コメント機能の非同期通信で実装した所がうまく動作をしなかったので解決策をシェアしたいと思います。 起きていたこと Herokuでのデプロイ時とAWSでのデプロイ時でのproduction.rbの記述方法が異なる。 Herokuでの場合 production.rb ActionCable.server.config.disable_request_forgery_protection = true config.action_cable.url = "wss://【Herokuアプリ名】.herokuapp.com/cable" config.action_cable.allowed_request_origins = ['https://【Herokuアプリ名】.herokuapp.com', 'http://【Herokuアプリ名】.herokuapp.com' AWSでの場合 production.rb ActionCable.server.config.disable_request_forgery_protection = true config.action_cable.url = "ws://【Elastic IP】/cable" config.action_cable.allowed_request_origins = ['http://【Elastic IP】'] 上記に加えてAWSの場合必要な対応 /etc/nginx/conf.d/rails.conf upstream app_server { server unix:/var/www/アプリケーション名/shared/tmp/sockets/unicorn.sock; } server { listen 80; server_name Elastic IP; root /var/www/アプリケーション名/current/public; location ^~ /assets/ { gzip_static on; expires max; add_header Cache-Control public; root /var/www/アプリケーション名/current/public; } try_files $uri/index.html $uri @unicorn; location @unicorn { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://app_server; } # -------------------ここから------------------- # /cableのパスに対してwebsocketの仕組みを用いるための設定 location /cable { proxy_pass http://app_server/cable; proxy_http_version 1.1; proxy_set_header Upgrade websocket; proxy_set_header Connection Upgrade; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # -------------------ここまでを追記------------------- error_page 500 502 503 504 /500.html; まとめ 今回の件ではAWSの場合だとWebサーバーとしてNginxを用意していたので、ActionCableを用いる場合、サーバーサイドへのリクエストを受け取る役目のあるWebサーバーにて、websocketの仕組みを用いるための設定をする必要があることを認識することが出来ました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsチュートリアル 第一章

クラウドIDE クラウドIDEにはWeb開発に必要な三種の神器であるテキストエディタ、ファイルブラウザ、コマンドラインターミナルもしっかり組み込まれている。 AWS Cloud9ではRubyやRubyGems、Gitなど、Ruby on Railsの開発環境の構築に必要なソフトウェアがほとんど組み込まれている。 IDEとは がテキストエディタ、コンパイラ、デバッガを1つにまとめた「IDE」です。 IDEを日本語に訳すると、統合開発環境 コンパイラとは コンパイラは人間が書きやすい言葉や数式で書いたプログラムを、コンピューターが理解して実行できる機械語に翻訳してくれる編集者だといえるでしょう。 コンパイルとは 人間がかいたプログラムをコンピューターがわかる言葉に書き換えること デバッガとは デバッガとは、プログラミングの際に用いる開発ツールの一つで、プログラムの欠陥(バグ)を発見・修正するデバッグ(debug)作業を支援するソフトウェア。 Yarn JavaScriptソフトウェアの依存関係を管理するプログラム JavaScriptのパッケージマネージャ JavaScriptのパッケージマネージャーとは JavaScriptのフレームワークは、基本的に大量のプログラムで構成されています。その大量のプログラムを一まとめにしたものをパッケージと呼び、そのパッケージを管理するツールがパッケージマネージャーです。 Yarn公式 https://yarnpkg.com/ パッケージマネージャーを使うと、フレームワークのインストールなどを高速に、正確に行うことができます。現在、パッケージマネージャー無しでフレームワークをインストールすることは、ほとんど無いというほど普及しています。 アセットパイプライン Webブラウザ上で表示されるものは、HTMLとCSS、JavaScriptが紐付くことによって、描かれている この仕組みがアセットパイプラインによって実現される アセットパイプラインの仕組み(概要) アセットパイプラインは、Ruby on Railsのアプリケーション内で使用したいJavaScriptやCSS、画像ファイルを「開発作業がしやすいようにファイルを分割してコーディングができるようにしつつ、最終的に一つのファイルに連結・圧縮する」仕組み アセットパイプラインは、複数のディレクトリやファイルに分かれたassetsディレクトリ内のファイルをひとつに連結・圧縮する機能です。 ひとつのファイルに連結・圧縮され、erbテンプレートからHTML化されたファイルとひも付いてからWebブラウザ画面上に表示されるようになります。この仕組みによって、Webアプリケーション内への効率的にアクセスすることもできます。 以上が、アセットパイプラインの役割です。 Bundler bundlerとは、gemのバージョンやgemの依存関係を管理してくれるgemです。bundlerを使うことで、複数人での開発やgemのバージョンが上がってもエラーを起こさずに開発できます。 Bundler公式 バージョン指定の仕方 Model-View-Controller(MVC) ブラウザがRailsアプリと通信する際、一般的にWebサーバーにリクエスト(request)を送信し、これはリクエストを処理する役割を担っているRailsのコントローラ(controller)に渡されます。コントローラは、場合によってはすぐにビュー(view)を生成してHTMLをブラウザに送り返します。動的なサイトでは、一般にコントローラは(ユーザーなどの)サイトの要素を表しており、データベースとの通信を担当しているRubyのオブジェクトであるモデル(model) と対話します。モデルを呼び出した後、コントローラは、ビューを描画し、完成したWebページをHTMLとしてブラウザに返します。 Bitbucket Bitbucket は、ソースコードおよび開発プロジェクト向けに、Web ベースのバージョン管理リポジトリホスティングサービスである。 GitHubとBitbucket GitHubとBitbucketは、Gitリポジトリを扱う2つの著名なサービスです。両者のサービスは非常に似通っています。どちらもGitリポジトリのホスティングと共同作業を行うことができ、リポジトリの表示や検索を行いやすくしてくれます。両者の重要な違いは、GitHubは「リポジトリを一般公開する場合は無料、公開しない場合は有料」なのに対し、Bitbucketは「共同作業者が一定数以下ならリポジトリを公開しなくても無料、共同作業者が一定数を超えると有料」である点です。なお、どちらも容量制限はありません。  ※現在はGitHubもプライベートリポジトリは無料 git configで設定 インストールしたGitを使う前に、最初に1回だけ設定を行う必要があります。これはsystemセットアップと呼ばれ、コンピュータ1台につき1回だけ行います。 $ git config --global user.name "Your Name" $ git config --global user.email your.email@example.com Herokuのセットアップ HerokuではPostgreSQLデータベースを使う。 HerokuではSQLiteがサポートされていない 以下のような書き方で 開発環境とテスト環境には、sqlite 本番環境では、PostgreSQLを指定する。 group :production do gem 'pg', '0.20.0' end group :development, :test do gem 'sqlite3', '1.3.13' gem 'byebug', '9.0.6', platform: :mri end bundle installに特殊なフラグ「--without production」を追加すると 本番用のgem (この場合はpg gem) をローカルの環境にはインストールしないようにできる。 bundle intall --without production CoffeeScript 変換するとJavaScriptのソースコードに生まれ変わる、 JavaScriptよりも書くのが楽なプログラミング言語
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

転売目的の商品大量購入を防止するアプリとしてTenba×Iyaというアプリを作りました。アプリの詳しい使い方や、意味などを説明します。

転売のための商品大量購入防止アプリとしてTenba×IyaというWebアプリを作りました。 アプリの使い方、画面の説明などを説明します。 アプリの説明ページ https://tenba-iya.hatenablog.com/entry/about アプリへのリンク https://tenba-iya.herokuapp.com/ アプリを作った理由についての記事 https://qiita.com/Tenba_Iya/items/82ff5c988aaa71dff71c アプリの概要 このアプリの概要としては以下の三つの機能があります。 ①商品を選んで電話番号を記入し、SMSを通してチケットを発行する。 ②商品の登録を行う ③チケットの検索を行う 以上の機能の説明を画面変遷の流れに沿って説明をしていきます。 ①チケットの発行 チケットの発行は以下の流れで行います。 1、商品一覧から商品を選択する。 2、電話番号を記入する 3、SMSでチケットIDが送信される 4、チケットIDを登録し、チケットが発行される 5、チケットを使用する 以下、詳細な説明です。 1、商品一覧 商品の検索、商品名、最近追加された商品が確認できるページです。 商品を選択すると、次のSMS送信ページに進みます。 以下ページ内の項目の説明です。 商品検索 検索欄に記入すると、商品一覧から商品を検索できます。 商品名 商品名とその商品の過去の販売数がカッコ内に示されます。 過去の販売数とは、実際の販売数ではなく、アプリ内でその商品のチケットが発行された数となります。 商品は上から順に、販売数が多い順に並びます。 商品名はMAXで20しか表示されず、商品登録数が増えると、販売数が少ない商品は検索しないと出てきません。 商品名が似通っている場合は、商品の販売数が多い物を選ぶことで、信頼性のある商品を選択できるように意図しました。 商品の名前をクリックすると、SMS送信のページに飛びます。 最近追加された商品 商品登録した時に商品一覧ページに表示されないと、分かりにくいと思ったので、最近追加された商品として3件まで表示されます。 2、SMS送信 選んだ商品名と、販売数が表示されます。 販売数が少ない場合は、チケット登録が少ない商品となるので、信頼性が下がると考えています。 似た名前の商品がある場合は、販売数が多い物を選んだ方がいいです。 販売者側も、チケット登録が少なすぎる場合は、信頼性が低いかもしれないと判断できるといいと考えています。 電話番号を記入して、送信を押すと、SMSが送信されます。 なお、電話番号は無料の電話番号を取得されると、アプリの意味がなくなるので、今後番号冒頭を080、090などに限定することを考えています。 電話番号は数字のみで記入し、ハイフンは入れません。 文字などで記入すると、SMSが送信できませんでしたとでます。 番号の桁数が11桁(例123-1234-1234)以外の場合も送信できませんと出ます。 3、携帯にSMSが届く 届く文面のサンプルは以下です。 Tenba×Iya チケットID:1234123 URLを入れて、URLをクリックすれば、次の確認画面にチケットIDが入力されるようにしようと思いましたが、SMSの文字数制限に引っかかり、できませんでした。 4、チケットID入力 商品名と携帯電話番号が記載されてます。 電話番号は全て表示されず、123-1234-1234の場合***-****-**34と表示されます。 ここでSMSで送られたチケットIDを記入して確定ボタンを押すと、チケットが発行されます。 IDを間違えたりすると、IDが違いますとなり、ID登録ができません。 5、チケット IDがあっているとチケットが発行されます。 ここには、チケットID、商品名、商品販売数、電話番号、商品の購入回数(総計、月合計、一日合計)、チケット発行日、チケットを使うボタンがあります。 商品の購入回数を販売者は見て、売るかどうかを決めます。 購入回数は総計、月合計、一日合計を表示しています。 PS5などは総計で1台とする。獺祭などお酒は、月3本まで制限する。マスクは1日人箱までとする。みたいな感じで、販売者が想定する販売数を登録するといいと思います。 詳しくは商品登録で説明します。 チケット発行日はとりあえず入れています。 チケットを使うボタンを押すと、チケットが使用済みになります。 チケットを使用済みにすると、元に戻せません。 販売者はチケット使用済みになっている場合は、このチケットは使われていますと判断します。 チケットが発行されると、商品の販売数が+1になります。 6、チケット使用済み チケットを使うと、画面のチケットを使うボタンが、チケット使用済みに変わります。 追加で、チケット使用日が表示されます。 チケットの登録の手順は以上になります。 ②商品登録 次に商品登録ページについて説明します。 このページでは商品を登録できます。 商品の名前は自由に決決めれます。 なるべく分かりやすいように、任天堂スイッチの場合は、任天堂スイッチ Nintendo Switch などいくつかの読み方で登録するといいと思います。 このように登録すれば、商品の検索でスイッチでもSwitchでも出てきます。 同じ名前は登録できませんが、少し文字を変えれば、登録できます。 似たような商品が増えた場合は、販売数で商品を選ぶようにします。 商品の登録の際に、希望する販売数(総計、月合計、一日合計)を1/総計、3/月、4/日などとすれば、いいと思っています。 ③チケット検索 次にチケットの検索ページについての説明です。 チケットIDを検索すると、チケットを探すことができます。 IDが違うと、検索できません。 SMSにIDが届いて、チケットID確定ボタンを押すと、チケットが発行され、IDを検索できるようになります。 確定ボタンを押さないで、終わると、チケットが登録されず、検索もできません。 チケット検索が成功すると、チケット表示画面になります。 チケットの情報と、チケットが使用済みか未使用かが分かります。 チケット検索の結果から、チケットを使用済みにすることもできます。 ネット販売などでは、チケットを購入者が登録し、IDを販売者に連絡し、検索してもらい、使用済みにすればいいと思っています。 以上です。 最後まで読んでいただきありがとうございます。 分かりにくところなどあれば、コメントをいただけると幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Railsチュートリアル] 9章の内容を自分なりに落とし込む

何回読んでも「あれ、今何してるんだっけ?」と分からなくなるので 特に頭がごちゃごちゃになる、rememberメソッドを作るまでの流れを 自分なりにざっくりまとめてみました。 (詳細の説明はRailsチュートリアルにお任せします。) 間違っている箇所ありましたらご教示ください。 目的 8章で行ったsessionを使ったログイン方法だとブラウザを閉じるごとにログインが必要になるので 永続的cookie(permanent cookies)を使ってログイン情報を長く記憶しておける(ブラウザを再起動してもログインしたままにしておける)ようにする。 単にcookieを使うだけだとセキュリティ的に問題があるので、トークンやらハッシュ化やらして、セキュリティを強固にする。 その後、[remember me]チェックボックスを作ってユーザーがログイン情報を保持するかどうか選べるようにする。 出てくる用語の意味をさらっておく 「なんとなくこうだったよね」で理解していると途中でついていけなくなるので意味を改めて確認しておきましょう cookie ブラウザ上に保存できる少量のデータ。 cookiesメソッドを使ってアクセス(保存したり読み出したり)できる。 署名付きcookie cookieをブラウザに保存する前に暗号化する処理。signedメソッドを使う。 記憶トークン(remember token) コンピュータが作成・管理するパスワードのようなもの。状態保存されない(毎回変わる)。 ランダムな文字列を生成して作る。 ハッシュ値 とあるデータ(今回の場合は記憶トークン)を なんやかんや(今回はダイジェストに変換)して、 生成した適当そうに見える値のこと。 とあるデータからハッシュ値を作ることをハッシュ化と呼ぶ。 attr_accessorメソッド インスタンス変数の値を読み書きするメソッド attr = attribute(属性)なので、 指定したattribute(属性)へアクセスできるようにするメソッドってことかと。 下記記事がわかりやすかったです。 - Railsから入った人へ【attr_accessor】って? 複合化 暗号化の逆。暗号を元のデータに戻すこと。 出来上がりのイメージ ユーザーがremember meにチェックを入れてログイン 記憶トークンが生成される ブラウザのcookiesにトークンと暗号化したユーザーIDが保存される(トークンの有効期限も設定される) 併せてトークンはハッシュ化してDBに保存される クライアントからリクエストがあると、 Webアプリケーションがcookiesに保存されたユーザーの情報(暗号化されたユーザーIDとトークン)を受け取り、 DBのユーザーIDとハッシュ化されたトークンに一致するかを確認 ざっくりした手順 ①「ハッシュ化した記憶トークン」を保存しておくカラム[ remember_digest ]を作成 ②ランダムなトークンを返すメソッドUser.new_tokenを用意  ※インスタンスに対してこのメソッドを使うことはないのでクラスメソッドにする ③渡された文字列をハッシュ化するメソッドUser.digestを用意(8章で作ってあった)  ※こちらもインスタンスに対してこのメソッドを使うことはないのでクラスメソッドにする ④トークンにアクセスできるように、[ remember_token ]という仮想の属性を用意  * User.new_tokenで作成したトークンを入れておきトークンにアクセスできるようにする  * 生のトークンをDBに保存したくないので[ remember_token ]という仮の箱を用意するイメージ  * attr_accessorを使うことで[ remember_token ]という仮想の属性を用意することを実現する class User attr_accessor :remember_token ⑤トークンをハッシュ化してDBに保存するメソッドrememberを用意 def remember self.remember_token = User.new_token  update_attribute(:remember_digest, User.digest(remember_token)) end ここで何が起こってるかというと 例えば、@userさんがログインした時、 @user.remember_tokenにUser.new_tokenで生成されたトークンを代入(保存)。 (attr_accessor :remember_tokenで、@userの[ remember_token ]をいじくれるようになってる) update_attribute:指定された属性を上書きメソッド で、 @userのデータベースの[ remember_digest ]カラムに、 User.digest(remember_token)で[ remember_token ]をハッシュ化した値 を保存してます。 ⑥渡されたトークンとDBに保存されたダイジェスト(=ハッシュ化されたトークン)が同じが確認(認証)するメソッドauthenticated?を用意 def authenticated?(remember_token) BCrypt::Password.new(remember_digest).is_password?(remember_token) end ここで出てくるremember_tokenはattr_accessorで定義された[ remember_token ]とは別物。 ただのメソッド内のローカル引数なので、ここの名前を例えばnとか適当な名前に変えても動く。 ⑦ユーザー情報(ユーザーIDと記憶トークン)を永続的cookieに保存するrememberメソッドをsessions_helper.rbに用意 ⑧rememberメソッドをsessions_controller.rbに設置してログインしたらcookiesにユーザー情報が保存されるようにする ⑨current_userをcookieを使った場合にも使えるように変更する その後、このままだとログアウト出来なくなるのでログアウトの処理も追記したり、 remember meのチェックボックスを用意してユーザーがcookieを使うか選択できるようにしたりしていきます。 詳細はRailsチュートリアルにてご確認ください。 参考 Railsチュートリアル Railsガイド -Action Controllerの概要 Railsガイド -Railsセキュリティガイド Railsから入った人へ【attr_accessor】って?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails aタグのリンクに変数を入れる方法

リンクを書く際になんども調べる事が多いので、備忘録として… users/:id/showへのリンクをaタグを使って書きたい場合… <a href="/users/<%= @user.id %>/show"> ※Rubyの場合(二重引用符" "の中で式展開) <%= link_to "詳細", "/users/#{@user.id}/show" %>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

human_attribute_name

前提条件 ruby 2.5.1 rails 5.2.5 結論 ActiveRecord::Baseのクラスメソッドであり、I18nモジュール(翻訳機能)を利用する為のもの。 config/locales/ja.ymlに定義してあるものを翻訳する。  モデル名.human_attribute_name(:カラム名)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Herokuデータベース内の行数が増えた時の対処(cloud9)

Database disruption imminent, row limit exceeded for hobby-dev database いきなりHrokuから【[warning] Database disruption imminent, row limit exceeded for hobby-dev database…】とメールがきました。 翻訳したところ、「データベースの中断が差し迫っています。hobby-devの行制限を超えています。」とのことです… heroku pg:infoで中身を確認します。 === DATABASE_URL Plan: Hobby-dev Status: Available Connections: 0/20 PG Version: 13.2 Created: 2021-03-17 01:49 UTC Data Size: 10.5 MB Tables: 10 Rows: 10668/10000 (Above limits, access disruption imminent) Fork/Follow: Unsupported Rollback: Unsupported Continuous Protection: Off Add-on: postgresql-curly-61190 すでに超えています… まだテストデータを保存したりしたくらいなのに、なぜか… 調べてみると、データベース内の全件削除などをすると、行数がかさんでいくとの事でした。 解決策 メールにはHooby Basicプランに変更するよう書かれていましたが、まだ誰も使っていないのと、お金を掛けたくないので、データベースのリセットをしました。 ターミナルで以下を実行 heroku pg:reset DATABASE To proceed, type…と出るので、herokuのアプリ名を入力し実行 ・再度データベースを構築 heroku run rails db:migrate ・確認 heroku pg:info === DATABASE_URL Plan: Hobby-dev Status: Available Connections: 0/20 PG Version: 13.2 Created: 2021-03-17 01:49 UTC Data Size: 8.6 MB Tables: 10 Rows: 17/10000 (In compliance) Fork/Follow: Unsupported Rollback: Unsupported Continuous Protection: Off Add-on: postgresql-curly-61190 スカスカに戻りました(笑)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Next.js、Rails とFirebase AuthenticationでJWT認証を実装する

はじめに JWT認証に関して、Next.js Rails Firebase Authenticationという組み合わせでの実装をした記事があまりないとのことなので、今回は実際にやっていこうと思う。 ちなみに、今回は https://simple-minds-think-alike.hatenablog.com/entry/rails-firebase-authentication を参考にしながらやっていく。 実際のファイル構成等は下記から閲覧していただけると幸いです。 (まだアプリ自体は作成中なので悪しからず・・・) https://github.com/yumaasato/m-api https://github.com/yumaasato/m-frontend 環境 Ruby: 2.6.5 Rails 6.0.3.6 firebase-auth-rails Redis *ちなみに今回、user認証でよく用いられるdeviseは必須ではありません。 今回は使わずに実装を進めていきます。 1. Redisをインストールする mac版の場合は、 $ brew install redis-server Linuxでは、 $ sudo apt install redis-server ですかね。 内部でfirebase_id_tokenを使っているためこのRedisをインストールする必要があるとのことです。 2. firebase-auth-railsの追加 今回、firebase-auth-railsというgemを利用することでjwt認証を比較的簡単に行うことができます。 Gemfile gem 'firebase-auth-rails' を追加します。 そして、 $ bundle install を実行します。 3-1. 実装(プロジェクトの設定) まずはじめに、Reidsとfirebaseプロジェクトの設定をおこないます。 config/initializers/firebase_id_token.rb FirebaseIdToken.configure do |config| config.redis = Redis.new config.project_ids = [ENV['FIREBASE_PROJECT_ID']] end 3-2. uidを追加 firebaseのUIDを保存するカラムを追加します。 $ rails g migration AddUidToUsers uid:string その後、 $ rails db:migrate を実行する。 3-3. Application Controller api/v1側にApplication Controllerを app/controllers/api/v1/application_controller.rb module Api class V1::ApplicationController < ActionController::API include Firebase::Auth::Authenticable before_action :authenticate_user end end としており、元のApplication Controllerについては触れられていないが、 私は下記のようにした ```rails:app/controllers/application_controller.rb class ApplicationController < ActionController::Base end つまり、application_controller.rbを2つ書いたというわけだが、これで正しいのかは正直怪しい。 しかし、しっかり実装できているため、一つの参考にはなるだろう。 3-3. ユーザー登録用のコントローラー実装 次に、ユーザー登録用のコントローラー実装する。正直名前は何でもよいが、今回はusers_controller.rbとする。 app/controllers/pi/v1/auth/users_controller.rb require_dependency 'api/v1/application_controller' module Api module V1 module Auth class UsersController < V1::ApplicationController skip_before_action :authenticate_user def create FirebaseIdToken::Certificates.request raise ArgumentError, 'BadRequest Parameter' if payload.blank? @user = User.find_or_initialize_by(uid: payload['sub']) do |user| user.name = payload['name'] end if @user.save render json: @user, status: :ok else render json: @user.errors, status: :unprocessable_entity end end private def token params[:token] || token_from_request_headers end def payload @payload ||= FirebaseIdToken::Signature.verify token end end end end end 今回は、Userのnameにnull:falseと設定しているため、 @user = User.find_or_initialize_by(uid: payload['sub']) do |user| user.name = payload['name'] end という記述になっている。 そうでない場合は、参考記事通りに @user = User.find_or_initialize_by(uid: payload['sub']) でもよいかと思われる。 3-4. Routeの追加 私は、下記の通りに実装した。 app/config/routes.rb Rails.application.routes.draw do namespace 'api' do namespace 'v1' do resources :players resources :games, only: %i(index) namespace 'auth' do post 'users' => 'users#create' end end end end 4-1. 実装後のオペレーション(重要) 実装後、$ rails cとして、firebase_id_tokenのDownloading Certificates以下に記載してある内容を実行する必要がある。 irb(main):001:0>FirebaseIdToken::Certificates.request ・ ・ ・ irb(main):002:0>FirebaseIdToken::Certificates.present? => true となってはじめて、jwt認証を使うことができる。 5-1. Next側の実装(補足) 次にNext.js側の実装を行う。フロント側の実装方法が省かれている記事が多いが、ここではNext側についても実装方法を記述する。 詳しい記述方法は https://github.com/yumaasato/m-frontend  を参照していただきたい。 あくまで参考だが、pages/login/index.tsxで export default function LoginPage() => { const [user, loading] = useAuthState(getAuth()); const router = useRouter();   ・   ・   // google認証 const signInGoogle = async () => { await auth.signInWithPopup(provider).catch((err) => alert(err.message)); router.push('/') }; const handleGoogleLogin = () => { const request = async () => { const user = await signInGoogle(); const auth = getAuth(); const currentUser = auth.currentUser; if (auth && auth.currentUser) { const token = await currentUser.getIdToken(true); const config = { token }; try { await axios.post('/api/v1/auth/users', config); } catch (error) { console.log(error); } } }; request(); }; } return ( <div className='w-2/3 py-20 mx-auto'> <p className='font-bold text-4xl py-5 text-center'>Login</p> <Button fullWidth variant="contained" color="default" className={classes.submit} startIcon={<CameraIcon />} onClick={handleGoogleLogin} > SignIn with Google </Button> </div> ); とすればいいのではないか。 これは、signInGoogleでfirebase AuthでのGoogle認証を行い、 handleGoogleLoginでRails側にAPIのデータを送るというものである。 ちなみに、ここでは axios.defaults.baseURL ='http://localhost:3000' としている。 これで一通りの実装は終えたことになる。 補足 Railsにおいて、.envファイルで環境変数を管理する際には、 gem 'dotenv-rails' をインストールする必要があるため、忘れずに設定しておこう。 (これで認証に時間がかかったので・・・) おわりに エンジニアの方からすれば、この認証は大したことはないのかもしれないが、記事を参考にしながら実装を進めている初学者からすれば、なかなか骨の折れる作業である。事実、私もこの実装だけでかなりの時間を費やしてしまった。 私と同じようにNext.js、Rails とFirebase AuthenticationでのJWT認証で困っている人たちの助けになれば幸いである。また、どこか誤りがありましたら、伝えてもらえると助かります。最後まで閲覧していただきまして、誠にありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerの環境構築でエラー文`find_spec_for_exe': Could not find 'bundler' の解決方法

Docker ローカルでは環境構築はうまく言ってるが Dockerで環境を作成する際に docker-compose run web rails new . --force --database=mysql --skip-bundle を実行すると エラー文が以下のように出た。 /usr/local/lib/ruby/2.6.0/rubygems.rb:283:in `find_spec_for_exe': Could not find 'bundler' (2.2.15) required by your /hogehoge/Gemfile.lock. (Gem::GemNotFoundException) To update to the latest version installed on your system, run `bundle update --bundler`. To install the missing version, run `gem install bundler:2.2.15` from /usr/local/lib/ruby/2.6.0/rubygems.rb:302:in `activate_bin_path' from /usr/local/bin/bundle:23:in `<main>'  解決策 Dockerにbundlerがインストールされてない。 RUN gem install bundlerを追記すればいいとのこと。 gem install bundler:2.2.15と出ているがローカル環境にはbundlerはあるのになぜ・・・・ と思ったら Dockerにbundlerがインストールされてないため出ているエラーだった。 Dockerfileに上記の記述を追記し、コマンドを再度打つことでエラーが解決できた。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

10週間の学習で制作しているポートフォリオ(未経験者)

?Dialy 日記アプリ ?機能一覧 機能 概要 ユーザー管理機能 新規登録・ログイン・ログアウトが可能 投稿機能 タイトル・日記・画像が投稿可能 投稿詳細表示機能 日記の詳細情報が閲覧可能 ユーザー詳細機能 各ユーザーの全ての投稿が閲覧可能 投稿編集・削除機能 投稿の削除と編集が可能 投稿・更新日表示機能 投稿詳細画面で投稿、更新日を表示 EC2サーバー 画像をAWSのEC2で保存 コメント機能 投稿詳細画面でコメントが可能 ページネーション機能 投稿数が増えると一覧画面下に次ページ表示 画像複数投稿機能 POSTとEDITから画像を複数枚投稿可能 投稿検索機能 一覧画面の検索窓からタイトル名で検索可能 ?開発環境 VScode Ruby Rails mysql JavaScript gem heroku ?参考資料 1冊ですべて身につくHTML & CSSとWebデザイン入門講座
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

10週間の学習で制作中のポートフォリオ(未経験者)

?Dialy 日記アプリ ?機能一覧 機能 概要 ユーザー管理機能 新規登録・ログイン・ログアウトが可能 投稿機能 タイトル・日記・画像が投稿可能 投稿詳細表示機能 日記の詳細情報が閲覧可能 ユーザー詳細機能 各ユーザーの全ての投稿が閲覧可能 投稿編集・削除機能 投稿の削除と編集が可能 投稿・更新日表示機能 投稿詳細画面で投稿、更新日を表示 EC2サーバー 画像をAWSのEC2で保存 コメント機能 投稿詳細画面でコメントが可能 ページネーション機能 投稿数が増えると一覧画面下に次ページ表示 画像複数投稿機能 POSTとEDITから画像を複数枚投稿可能 投稿検索機能 一覧画面の検索窓からタイトル名で検索可能 ?開発環境 VScode Ruby Rails mysql JavaScript gem heroku ?参考資料 1冊ですべて身につくHTML & CSSとWebデザイン入門講座
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rspec System Specでconfirmダイアログのテスト記述方法

はじめに system spec でテストをするとき、confirmのダイアログのテスト方法が分からなかった記述方法をまとめます。 到達点 以下の1点を達成する ・confirmのダイアログのテストの記述方法を理解する 流れ ① confirmのダイアログのテスト ① confirmのダイアログのテスト 投稿記事を削除するとき、ダイアログが表示され、okをクリックすると削除されるかテストを記述します。 結論から言うと、 expect(page.accept_confirm).to eq "本当に削除しますか?" という記述をするとよいです。 spec/systems/posts_spec.rb it "削除ボタンを押すと、削除されること" do find(".alarm").click *投稿削除ボタンをクリック expect do expect(page.accept_confirm).to eq "本当に削除しますか?" expect(page).to have_content "test_titleを削除しました" *flashメッセージ end.to change(Post, :count).by(-1) is_expected.not_to have_content post.title *記事一覧に削除した投稿がないことを確認 end 参考記事 使えるRSpec入門・その4「どんなブラウザ操作も自由自在!逆引きCapybara大辞典」
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerComposeをdevelopmentで実行する

これまで、production環境で開発をしてきた。 Dockerを導入し、AWSでのデプロイを試みている。 しかしそれは、他の記事を参考に作っていた為、 意味もわからず、本番環境でやってきただけで、 必要な構成も理解していないので上手く進まなかった。 そこで、development環境に戻し、 まずはDockerの導入にフォーカスして理解度を高めていく。 各ファイルの修正 docker-compose.yml services: local-redis: image: redis container_name: rails-redis container_name: rails-redis local-rails: build: . @@ -15,9 +14,31 @@ services: - local-redis env_file: - env_file.env container_name: rails-rails container_name: rails-rails command: bundle exec rails s -b 0.0.0.0 # bundle exec rails s -e production environment: RAILS_DATABASE_PASSWORD: blago18 RAILS_DATABASE_HOST: db RAILS_DATABASE_USER: blago18 RAILS_ENV: development volumes: - .:/var/www/footomo db: image: mysql volumes: - mysql-data:/var/lib/mysql # ports: # - 3306:3306 environment: MYSQL_ROOT_PASSWORD: MySQL8.0 MYSQL_DATABASE: app_development MYSQL_USER: blago18 MYSQL_PASSWORD: blago18 command: - --default-authentication-plugin=mysql_native_password volumes: mysql-data: コンテナに入ってmigrationを実行 Kotaro18:footomo kotaro18$ docker-compose up --build Creating network "footomo_default" with the default driver Building local-rails [+] Building 0.3s (16/16) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 37B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/ruby:2.6.6 0.0s => [ 1/11] FROM docker.io/library/ruby:2.6.6 0.0s => [internal] load build context 0.1s => => transferring context: 24.44kB 0.1s => CACHED [ 2/11] RUN curl -sL https://deb.nodesource.com/setup_11.x | bash - 0.0s => CACHED [ 3/11] COPY ./ /var/www/footomo 0.0s => CACHED [ 4/11] WORKDIR /var/www/footomo 0.0s => CACHED [ 5/11] COPY Gemfile /var/www/footomo 0.0s => CACHED [ 6/11] COPY Gemfile.lock /var/www/footomo 0.0s => CACHED [ 7/11] RUN apt-get update 0.0s => CACHED [ 8/11] RUN apt-get upgrade -y 0.0s => CACHED [ 9/11] RUN gem update bundler 0.0s => CACHED [10/11] RUN apt-get install build-essential patch ruby-dev zlib1g-dev liblzma-dev -y 0.0s => CACHED [11/11] RUN bundle install 0.0s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:80be9ac03901063a087005abd6dda11a3649ae427b8362763ce3dac898f1c523 0.0s => => naming to docker.io/library/footomo_local-rails 0.0s Successfully built 80be9ac03901063a087005abd6dda11a3649ae427b8362763ce3dac898f1c523 Creating rails-redis ... done Creating footomo_db_1 ... done Creating rails-rails ... done Attaching to rails-redis, footomo_db_1, rails-rails db_1 | 2021-04-07 23:35:44+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. db_1 | 2021-04-07 23:35:44+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' db_1 | 2021-04-07 23:35:44+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. db_1 | 2021-04-07T23:35:45.026977Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.23) starting as process 1 db_1 | 2021-04-07T23:35:45.041398Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. rails-redis | 1:C 07 Apr 2021 23:35:44.073 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo rails-redis | 1:C 07 Apr 2021 23:35:44.074 # Redis version=6.0.8, bits=64, commit=00000000, modified=0, pid=1, just started rails-redis | 1:C 07 Apr 2021 23:35:44.074 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf rails-redis | 1:M 07 Apr 2021 23:35:44.105 * Running mode=standalone, port=6379. rails-redis | 1:M 07 Apr 2021 23:35:44.106 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. rails-redis | 1:M 07 Apr 2021 23:35:44.106 # Server initialized rails-redis | 1:M 07 Apr 2021 23:35:44.112 * Ready to accept connections db_1 | 2021-04-07T23:35:45.698289Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended. db_1 | 2021-04-07T23:35:46.033480Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock db_1 | 2021-04-07T23:35:46.142287Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed. db_1 | 2021-04-07T23:35:46.142734Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel. db_1 | 2021-04-07T23:35:46.148257Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory. db_1 | 2021-04-07T23:35:46.195505Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.23' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL. ここで、初歩的なミスをしてしまいました。 一旦、Ctl+Cでキャンセルしてから、 同じターミナルでコンテナに入ろうとしたところ、 railsは既に立ち上がってますとのエラーが。 server.pidを削除したり、 他のターミナルで立ち上がってないかチェックしてました。 単純に、1つのターミナルでコンテナを立ち上げ、 もう1つのターミナルでコンテナに入ればいいだけでした。 Kotaro18:footomo kotaro18$ docker-compose exec local-rails bash root@fc0180c62138:/var/www/footomo# そして、migrationを実行 Kotaro18:footomo kotaro18$ docker-compose exec local-rails bash root@fc0180c62138:/var/www/footomo# rails db:migrate == 20180217122153 CreateBoards: migrating ===================================== -- adapter_name() -> 0.0000s -- adapter_name() -> 0.0000s -- adapter_name() -> 0.0000s -- create_table(:boards, {:options=>"ENGINE=InnoDB", :id=>:integer}) -> 0.0507s == 20180217122153 CreateBoards: migrated (0.0511s) ============================ == 20180315233935 CreateComments: migrating =================================== -- adapter_name() -> 0.0000s -- adapter_name() -> 0.0000s -- adapter_name() -> 0.0000s -- create_table(:comments, {:options=>"ENGINE=InnoDB", :id=>:integer}) -> 0.1153s == 20180315233935 CreateComments: migrated (0.1230s) ========================== == 20180324120737 CreateTags: migrating ======================================= -- adapter_name() -> 0.0000s -- adapter_name() -> 0.0000s -- adapter_name() -> 0.0002s -- create_table(:tags, {:options=>"ENGINE=InnoDB", :id=>:integer}) -> 0.0416s == 20180324120737 CreateTags: migrated (0.0485s) ============================== == 20180324120941 CreateBoardTagRelations: migrating ========================== -- adapter_name() -> 0.0000s -- adapter_name() -> 0.0001s -- adapter_name() -> 0.0000s -- create_table(:board_tag_relations, {:options=>"ENGINE=InnoDB", :id=>:integer}) -> 0.0912s == 20180324120941 CreateBoardTagRelations: migrated (0.0963s) ================= == 20180506115954 CreateUsers: migrating ====================================== -- adapter_name() -> 0.0000s -- adapter_name() -> 0.0000s -- adapter_name() -> 0.0000s -- create_table(:users, {:options=>"ENGINE=InnoDB", :id=>:integer}) -> 0.0376s -- add_index(:users, :name, {:unique=>true}) -> 0.0656s == 20180506115954 CreateUsers: migrated (0.1056s) ============================= == 20181128051946 AddBirthdayToUser: migrating ================================ -- add_column(:users, :birthday, :date, {}) -> 0.0430s == 20181128051946 AddBirthdayToUser: migrated (0.0452s) ======================= Dockerのコンテナに入り、 dbをmigrationできました。 引き続き、開発環境で コンテナの適切な導入を実施していきます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HTTPを理解する(curl,Postman編)

curl, Postman, HTTPを理解する ・実行項目 curlコマンドで特定の記事を更新してください curlコマンドで特定の記事を削除してください postmanで特定の記事を更新してください postmanで特定の記事を削除してください 1.curlコマンドで特定の記事を更新 以下ターミナル部分のコマンドをたたくと 以下 TitlehogeContent hugaのように更新されました! 2.curlコマンドで特定の記事を削除 以下ターミナル部分のコマンドをたたくと TitlehogeContent hugaは削除されました! 3.postmanで特定の記事を更新 postmanを使い以下のように更新のリクエストを送信する Titlei am changemanContent i am updatemanに更新されました! 4.postmanで特定の記事を削除 postmanを使い以下のように削除のリクエストを送信する Titlei am changemanContent i am updatemanは削除されました! まとめ 今回の実行項目を通して理解しなければいけないことは、リクエストを送ることができればツールはなんだっていいんだよ!ということ。 一般ユーザーが理解しやすく、使いやすく感覚的に使用(リクエストを送る)するにはブラウザというインタフェースを作ってあげる必要がある。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Fakerを使って英数混合のパスワードを作る

プログラミングスクールの課題に取り組んでいて、ググって探して当て突き止めた情報を自分なりに深堀りしてみました。よろしければお付き合いください。 deviseを使ってログイン・ログアウト・新規登録を完了して次の課題である「単体テスト」をやっています。 検索結果 ネットで検索して自分の今の知識で理解できる情報は以下です。役に立てれば嬉しいです。 Faker::Lorem.characters(min_alpha: 1, min_numric: 1) 検索目的 Fakerで単体テストコードで英数混在の6文字以上のパスワードをつくる。 *Fakerとはテストに使うダミーデータを用意するGem ここで問題になってくるのが factories/users.rb password { Faker::Internet.password(min_length: 8) } Fakerはメールアドレス、パスワード、URL、スラッグ、IPアドレスなどをインターネット関連としてダミーデータを作成してくれるのですが、6文字の中に数値もしくは、アフファベットのいずれかだけで生成される可能性が非常に高いというリスクがあることです。 Faker::Internet.password(min_length: 8)は諦めて方向転換 *(参考)min_lengthは最低文字数を指定 他に 指定 指定内容   special_characters: true   特殊文字を含む special_characters: false  特殊文字含まない mix_case: true         大文字含む mix_case: false        大文字含まない の設定ができます。 解決策1 参考サイト https://github.com/faker-ruby/faker/blob/master/doc/default/lorem.md Faker::Lorem.characters(min_alpha: 1, min_numric: 1)活躍するのがこれ 基本形(charactersというのは「文字」の意味) Faker::Lorem.characters(number: 10) #=> "ang9cbhoa8" 指定 指定内容   number: 10 ランダムな文字10文字を生成 Faker::Lorem.characters(number: 10, min_alpha: 4) #=> "ang9cbhoa8" 指定 指定内容   number: 10 ランダムな文字10文字を生成 min_alpha: 4 10文字の中に最低4文字以上はアフファベットを含める Faker::Lorem.characters(number: 10, min_alpha: 4, min_numeric: 1) #=> "ang9cbhoa8" 指定 指定内容   number: 10 ランダムな文字10文字を生成 min_alpha: 4 10文字の中に最低4文字以上はアフファベットを含める min_numeric: 1 10文字の中に最低1文字以上数値を含める factories/users.r 回答例 password { Faker::Lorem.characters(number: 6, min_alpha: 1, min_numeric: 1) } 解決策2(以下参考サイト) 参考サイト https://github.com/faker-ruby/faker/blob/master/doc/default/alphanumeric.md 指定方法は違いますが、にています。 Faker::Alphanumeric.alphanumeric(number: 10) #=> "3yfq2phxtb" Faker::Alphanumeric.alphanumeric(number: 10, min_alpha: 3) #=> "3yfq2phxtb" Faker::Alphanumeric.alphanumeric(number: 10, min_alpha: 3, min_numeric: 3) #=> "3yfq2phx8b" *設定の説明は解決策1と同じなので割愛 ご参考までに
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む