20200731のRubyに関する記事は30件です。

Rails googleを使ったSNS認証

ゴール

googole認証のリンクをクリック
image.png

アカウントを選択する
image.png

認証成功!!
image.png

ベースの作成

  • deviseを導入する
  • scaffoldで投稿機能を作成 ezgif.com-video-to-gif (1).gif

ログインして、投稿を作成できるアプリケーションを作成しました。

googleの設定をする

image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
URLは開発環境の場合、こちらを入力してください
http://localhost:3000/users/auth/google_oauth2/callback
本番環境でも使われる場合は、こちらを入力してください
http://本番環境URL/users/auth/google_oauth2/callback

コード編集していきます

環境変数の設定をします。

devise.rb
# ==> OmniAuth
# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
config.omniauth :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET']

私は環境変数の管理にdotenv-railsを使用しました。

gemfile
gem 'dotenv-rails'

bundle installします。
アプリケーションのルートディレクトリ直下に.envを作成します

以下のクライアントID,クライアントシークレットをコピーして

image.png

.envに以下のように貼り付けします

.env
GOOGLE_CLIENT_ID='クライアントIDを入力'
GOOGLE_CLIENT_SECRET='クライアント シークレット'

環境変数は、githubにpushする場合は.env.ignoreに追加しておくと良いかと思います。

.ignore
# 以下を追記
.env

gemfile編集

gemfile
gem 'omniauth-google-oauth2'

上記のgemを追加して

bundle install

ルーティング編集

gemfile
Rails.application.routes.draw do
  # deviseのコントローラを編集するときは以下を記述しないと変更が反映されないので注意
  devise_for :users, controllers: {
    # deviseの階層を編集した場合は適宜pathを編集してください
    omniauth_callbacks: "users/omniauth_callbacks"
  }

  resources :posts

  root 'posts#index'
end

データベースにカラムを追加する

認証に必要なカラムproviderカラムと、uidカラムを作成するためのマイグレーションファイルを作成します

$ rails g migration AddOuthColumnToUsers provider:string uid:string

rails db:migrate

userモデルを編集

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,
         # 以下を追加
         # google以外の認証をする場合は %i[twitter, facebook]などとなります
         :omniauthable, omniauth_providers: %i[google_oauth2]

  # クラスメソッドを作成します
  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
      # deviseのuserカラムに name を追加している場合は以下のコメントアウトも追記します
      # user.name = auth.info.name
      user.email = auth.info.email
      user.password = Devise.friendly_token[0,20]
    end
  end
end

ここで出てくるfirst_or_createが初めて使うメソッドでした。
結構便利だなと、、、

DBにwhereで検索したオブジェクトが存在しなければ、何も処理を行わず、
DBにwhereで検索したオブジェクトが存在していれば、userオブジェクトにdo以降の処理を入力してDBに保存する処理になってます。

一度rails console -sなどを使っていろいろ試してみると良いかと!
rails console -sを使えばデータベースに変更が加わらないので安心です。

omniauthの処理を編集します

omniauth_callbacks_controller.rb
# frozen_string_literal: true

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  # callback for google
  def google_oauth2
    callback_for(:google)
  end

  def callback_for(provider)
    # 先ほどuser.rbで記述したメソッド(from_omniauth)をここで使っています
    # 'request.env["omniauth.auth"]'この中にgoogoleアカウントから取得したメールアドレスや、名前と言ったデータが含まれています
    @user = User.from_omniauth(request.env["omniauth.auth"])
    sign_in_and_redirect @user, event: :authentication
    set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
  end

  def failure
    redirect_to root_path
  end
end

以上でgoogleでsns認証ができるかと思います!!

参考

Facebook/Twitter/Googleでのユーザー登録をDevise & Omniauthを使って爆速で実装する

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

プログラミングスクール行って良かったなっていう話。

※この記事、若干前置き長いです。

こんにちは、Shotaです!

僕がプログミングを勉強してからついに7カ月が経ちました。時が過ぎるのはあっという間ですね。。。
ちなみに、Ruby歴は4カ月程度です

7月にプログラミングスクールを卒業して、今ではRubyで簡単なアプリを作れるようになった僕ですが、はじめはなかなかうまくいきませんでした。

最初の挫折は、Progateの道場です。

プログラミングをやろう!と思って、
まず最初に安定のProgateから始めてみました。

しかし、大学生ということで勉強・2つの部活・バイト・遊び など、
やることも少なくなかったため、ずいぶんスローペースで進めてました。

確か2カ月くらいでHTML,CSS,JS,jQueryを1~2周ずつくらいしたと思います。

一通りProgateやった僕は、腕試しにと、初めてHTMLの道場編をやりました。
そして、絶望しました。(笑)

プログラミングで初めて、
「めちゃめちゃ難しくね???」
と感じた瞬間です。

これを機に、僕がパソコンの前に座る回数は減っていきました。

典型的な挫折パターンです。

しかし僕は、プログラミングに対する思いを捨てきれず、挫折の4カ月後に
またProgateを再開しました。

今度は冬休みということもあり、結構時間もあったので、1~2カ月独学でほぼ毎日プログラミングの勉強をしました。

でも、やっていくうちに気づいたんです。
「独学じゃプログラミングスクール行ってる人に勝てないんじゃないか。」
ということに。

Twitterなんか見ると、
「独学でも案件取れる」とか「独学でもエンジニアになれる」
というのは、結構言われてる気はします。

そういったものを見ると、
「独学でも案外行けんじゃね」
って簡単に思ってしまいます。

たしかに、それは可能だとは思います。
でも個人的な意見としては、スクールに行った方が、成長できるし、得られるものが多いと思います。
また、案件を取れる確率やエンジニアになれる確率も、間違いなくスクールに行った方が上がるはずです。

スポーツを例にすると分かりやすいですね。

例えば、テニススクールに通っている子と、テニススクールには通ってないけどテニスをしている子がいたとします。

テニススクールに行っている子は、
毎日、監督・コーチに教えてもらいながら、仲間と一緒に良い環境で練習や試合をやります。
フォームがおかしかったり、新しいプレーにチャレンジしたりするときは、基本からしっかり教えてもらえます。

一方、テニススクールに行っていない子は、
毎日テニスの上手い人の動画や、解説動画を見ながら、壁当てをやり続けます。
自分だけでは、おかしいフォームになっても気づきづらいです。

では、この2人が試合するとします。
皆さんもお分かりだと思いますが、スクールに行っていない子が
勝つ確率は、非常に低いでしょう。

そりゃそうです。
スクールの方が練習環境がいいし、指導してもらえるから。
さらに言うと、スクールに行ってない子が見たテニスの動画は、スクールに行ってる子も見て参考にできます。

これと同じことがプログラミングスクールの世界にも言えると、僕は思います。

だから、プログラミングスクールは行く価値があるのです。


「多くの人に影響を与え、前向きにさせるようなサービス開発をする」

というのが僕の目標です。
そのためには、スキルのある立派なエンジニアになる必要があります。

そしてそれを実現するためには、

よりエンジニアになりやすい、プログラミングスクールに行った方が良い

ということになります。

これに気づいた僕は、すぐにプログラミングスクールに申し込みました。

プログラミングスクールの感想としましては、

「とにかく行って良かった」

この一言に尽きます。

一体なにが良かったのか。
ポイントは主に2つです。

1つ目、分からないことをすぐに聞けること
2つ目、継続できること

1つ目、分からないことがあればすぐに聞ける

独学だと、いくら調べてもなかなかエラーから抜け出せない
ということがあると思います。

でも、分からないところを聞ける環境があれば、そこで多くの時間足止めをされる心配がなくなります。
メンターさんに質問した時、返ってくるのは答えではなく、ヒントでした。
だから無駄に時間をかけることなく、思考停止もせず、エラーを解決することができました。
運よく、僕の専属のメンターさんは非常にお優しい方で
とてもやりやすかったです。

2つ目、継続できる

プログラミングは継続が大事といいますが、本当にそうだと思います。
独学だと挫折しやすいです。ほんとに。
まぁ現に僕も挫折しましたし、笑
プログラミングの独学で挫折する確率は90%と言われています。
プログラミングスクールって結構お金かかりますよね?
でもスクールに行くと、損したくない気持ちが出てくるおかげで、より継続しやすいと思います。
スクールには、受講生を継続させるシステムも整ってますし。

とまぁ、こんな感じで、
すぐ聞ける、継続できる

という点が非常に良かったかなと、僕は思います。

結論、
プログラミングスクール行って良かった。

なるべく早く結果を出したい人や、プログラミングで何か高い目標がある人は、
プログラミングスクールに行くことを僕はオススメします!

ちなみに、僕は
「テックアカデミーのWebアプリケーションコース」
で、12週間のプランでした。

一応リンク貼っておきますね!
テックアカデミーのリンクはこちら ☞ https://techacademy.jp/

長くなりましたが、最後まで読んでくださりありがとうございました!

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

slateとaglioというAPI Document toolを使ってみた

はじめに

API Documentページを作成するにあたって slate, aglio というtoolを実際に触ったときの手順と感想です。

slate について

rubyで作成されたAPIドキュメントを作成するための ツールでマークダウンでドキュメントを記述できます。

slate 導入手順

1 リポジトリの準備
本家のリポジトリを開いて[use this template]をクリックし任意の場所にリポジトリを作成します。

作成したリポジトリをローカル環境へgit cloneします。

2 開発環境セットアップ
README.mdを見て頂くと分かるのですが起動方法は以下の3つが準備されています。
* Natively
* Using Vagrant
* Using Docker

手順もこちらへ記載してあり非常に親切ですね。

今回はNativelyUsing Dockerの手順をやってみたいと思います。

2-1 Natively(local環境へ直接installする) 手順
こちらに記載の手順を実行します。
※ 私の環境ではRuby、nodejsの開発環境は整っていたのでinstall部分は省略しました。

cd slate

bundle install

# middlemanはrubyのgemで静的なサイトを簡単に生成してくれます
bundle exec middleman server

以上です!

これで
http://localhost:4567/
へアクセスすると以下のようなAPI Documentのテンプレートが表示されます。

スクリーンショット 2020-07-26 19.55.51.jpg

2-2 Using Dockerの手順
こちらに記載の手順を実行します。

cd slate

docker build . -t slate

docker run -d --rm --name slate -p 4567:4567 -v $(pwd)/build:/srv/slate/build -v $(pwd)/source:/srv/slate/source slate

以上でNativelyと同じように
http://localhost:4567/
へアクセスするとAPI Documentのテンプレートが表示されます。

マークダウンファイルは sourceディレクトリにあるのでドキュメントの内容を修正する場合はこれを書き換えます。

3 Deploy手順
ここではこちらに記載してある手順でDeployしてみます。
ここに記載してあるのはGitHub Pagesに公開する手順で実行方法は下記コマンドを実行するだけです。

./deploy.sh

何とこれだけ!

これで実際に自分のGitHub Pagesのプロジェクトサイトが公開されているので確認してみて下さい。
URLは http://yourusername.github.io/slate です。
実際にdeployした私のGitHub Pagesはこちらです。

簡単に deploy.sh の内容を見ると

bundle exec middleman build --clean

で マークダウンファイルより build ディレクトリ配下へ静的ファイルを作成します。
スクリーンショット 2020-07-31 19.39.43.jpg

その後に build ディレクトリの内容を gh-pagesブランチへpushしています。

続いてaglioについて記載します。

aglio について

aglioとはAPI Blueprintで記述されたファイルをhtmlへ変換してくれるツールです。

API Blueprint
API Blueprint とは Web API の仕様を表現するための言語のことです。 API の仕様を表現するための様々な文法を持っています。 書き方は Markdown と同じ形式ですので、書き方も馴染みのあるものです。

aglio 導入手順

1 リポジトリの準備
GitHub上に任意のリポジトリを作成します。
(例: https://github.com/Nobuo-Hirai/api-document-use-aglio)
作成したリポジトリをgit cloneします。

2 開発環境セットアップ
document用のディレクトリ、ファイルを作成します。
root直下にmdディレクトリを作成しその中にdocument用のマークダウンファイルを作成していきます。
Dockerfile, docker-compose.ymlbuildディレクトリdeploy.shは後で説明するのでこの段階では必要ないです。

スクリーンショット 2020-07-31 20.11.49.jpg

環境構築用の Dockerfiledocker-compose.ymlを作成します。

Dockerfile

FROM node:latest

WORKDIR /projects

RUN npm install -g aglio --unsafe-perm

docker-compose.yml

docker-compose.yml
version: '3'

services:
  aglio:
    build: .
    ports:
      - '4000:4000'
    volumes:
      - './md:/projects'
      - './:/docs'
    tty: true
    # htmlを作成するときのテーマを決めれます。
    # https://github.com/danielgtaylor/aglio#example-output
    command: aglio --theme-variables default --theme-template triple -i index.md -s -h 0.0.0.0 -p 4000

dockerコンテナ構築・起動します。

docker-compose up --build

以上で http://localhost:4000/
へアクセスするとAPI Documentのテンプレートが表示されていると思います。

mdディレクトリ配下のマークダウンファイルを修正しAPI documentを作成していきます。

3 静的ファイルの作成
deploy用の静的ファイルを作成するため以下のコマンドを実行します。

# コンテナ内でhtmlを生成するコマンドを実行
docker-compose exec aglio bash

aglio --theme-variables default --theme-template triple -i index.md -o ../docs/index.html

以上で、index.htmlファイルが作成されたと思います。
続いて今回もGitHubPagesへdeployしたいと思います。

4 deploy.sh の作成
ここではslateで使用したdeploy.shを活用します。
slateで使用したdeploy.shをコピーしてroot直下へ配置します。

修正点は以下の部分です。

## slate
run_build() {
  bundle exec middleman build --clean
}
↓
↓
## aglio用に以下に書き換えます
run_build() {
  [[ ! -e ${deploy_directory} ]] && mkdir -p ${deploy_directory}
  cp index.html build/.
}

5 deploy手順

slateと同じように以下のコマンドを実行して終わりです。

./deploy.sh

これで実際にGitHub Pagesのプロジェクトサイトを確認してみて下さい。
実際にdeployした私のGitHub Pagesはこちらです。

2つを試してみての感想

自分がrubyの開発経験があったり環境を既に持っていたというのもありslateの方が簡単でした。
またslateの方がドキュメントが豊富で、star数も多いのでslateが無難かなという印象でした。

他に良いAPI Document toolがあれば紹介お願いします!

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

slateとaglioというAPI Document toolを使ってみたときの手順

はじめに

API Documentページを作成するにあたって slate, aglio というtoolを実際に触ったときの手順と感想です。

slate について

rubyで作成されたAPIドキュメントを作成するための ツールでマークダウンでドキュメントを記述できます。

slate 導入手順

1 リポジトリの準備
本家のリポジトリを開いて[use this template]をクリックし任意の場所にリポジトリを作成します。

作成したリポジトリをローカル環境へgit cloneします。

2 開発環境セットアップ
README.mdを見て頂くと分かるのですが起動方法は以下の3つが準備されています。
* Natively
* Using Vagrant
* Using Docker

手順もこちらへ記載してあり非常に親切ですね。

今回はNativelyUsing Dockerの手順をやってみたいと思います。

2-1 Natively(local環境へ直接installする) 手順
こちらに記載の手順を実行します。
※ 私の環境ではRuby、nodejsの開発環境は整っていたのでinstall部分は省略しました。

cd slate

bundle install

# middlemanはrubyのgemで静的なサイトを簡単に生成してくれます
bundle exec middleman server

以上です!

これで
http://localhost:4567/
へアクセスすると以下のようなAPI Documentのテンプレートが表示されます。

スクリーンショット 2020-07-26 19.55.51.jpg

2-2 Using Dockerの手順
こちらに記載の手順を実行します。

cd slate

docker build . -t slate

docker run -d --rm --name slate -p 4567:4567 -v $(pwd)/build:/srv/slate/build -v $(pwd)/source:/srv/slate/source slate

以上でNativelyと同じように
http://localhost:4567/
へアクセスするとAPI Documentのテンプレートが表示されます。

マークダウンファイルは sourceディレクトリにあるのでドキュメントの内容を修正する場合はこれを書き換えます。

3 Deploy手順
ここではこちらに記載してある手順でDeployしてみます。
ここに記載してあるのはGitHub Pagesに公開する手順で実行方法は下記コマンドを実行するだけです。

./deploy.sh

何とこれだけ!

これで実際に自分のGitHub Pagesのプロジェクトサイトが公開されているので確認してみて下さい。
URLは http://yourusername.github.io/slate です。
実際にdeployした私のGitHub Pagesはこちらです。

簡単に deploy.sh の内容を見ると

bundle exec middleman build --clean

で マークダウンファイルより build ディレクトリ配下へ静的ファイルを作成します。
スクリーンショット 2020-07-31 19.39.43.jpg

その後に build ディレクトリの内容を gh-pagesブランチへpushしています。

続いてaglioについて記載します。

aglio について

aglioとはAPI Blueprintで記述されたファイルをhtmlへ変換してくれるツールです。

API Blueprint
API Blueprint とは Web API の仕様を表現するための言語のことです。 API の仕様を表現するための様々な文法を持っています。 書き方は Markdown と同じ形式ですので、書き方も馴染みのあるものです。

aglio 導入手順

1 リポジトリの準備
GitHub上に任意のリポジトリを作成します。
(例: https://github.com/Nobuo-Hirai/api-document-use-aglio)
作成したリポジトリをgit cloneします。

2 開発環境セットアップ
document用のディレクトリ、ファイルを作成します。
root直下にmdディレクトリを作成しその中にdocument用のマークダウンファイルを作成していきます。
Dockerfile, docker-compose.ymlbuildディレクトリdeploy.shは後で説明するのでこの段階では必要ないです。

スクリーンショット 2020-07-31 20.11.49.jpg

環境構築用の Dockerfiledocker-compose.ymlを作成します。

Dockerfile

FROM node:latest

WORKDIR /projects

RUN npm install -g aglio --unsafe-perm

docker-compose.yml

docker-compose.yml
version: '3'

services:
  aglio:
    build: .
    ports:
      - '4000:4000'
    volumes:
      - './md:/projects'
      - './:/docs'
    tty: true
    # htmlを作成するときのテーマを決めれます。
    # https://github.com/danielgtaylor/aglio#example-output
    command: aglio --theme-variables default --theme-template triple -i index.md -s -h 0.0.0.0 -p 4000

dockerコンテナ構築・起動します。

docker-compose up --build

以上で http://localhost:4000/
へアクセスすると以下のようなAPI Documentのテンプレートが表示されていると思います。

スクリーンショット 2020-07-31 21.10.33.jpg

mdディレクトリ配下のマークダウンファイルを修正しAPI documentを作成していきます。

3 静的ファイルの作成
deploy用の静的ファイルを作成するため以下のコマンドを実行します。

# コンテナ内でhtmlを生成するコマンドを実行
docker-compose exec aglio bash

aglio --theme-variables default --theme-template triple -i index.md -o ../docs/index.html

以上で、index.htmlファイルが作成されたと思います。
続いて今回もGitHubPagesへdeployしたいと思います。

4 deploy.sh の作成
ここではslateで使用したdeploy.shを活用します。
slateで使用したdeploy.shをコピーしてroot直下へ配置します。

修正点は以下の部分です。

## slate
run_build() {
  bundle exec middleman build --clean
}
↓
↓
## aglio用に以下に書き換えます
run_build() {
  [[ ! -e ${deploy_directory} ]] && mkdir -p ${deploy_directory}
  cp index.html build/.
}

5 deploy手順

slateと同じように以下のコマンドを実行して終わりです。

./deploy.sh

これで実際にGitHub Pagesのプロジェクトサイトを確認してみて下さい。
実際にdeployした私のGitHub Pagesはこちらです。

参考リポジトリ

2つを試したリポジトリを以下に公開しています。
https://github.com/Nobuo-Hirai/api-document-use-slate
https://github.com/Nobuo-Hirai/api-document-use-aglio

2つを試してみての感想

自分がrubyの開発経験があったり環境を既に持っていたというのもありslateの方が簡単でした。
またslateの方がドキュメントが豊富で、star数も多いのでslateが無難かなという印象でした。

他に良いAPI Document toolがあれば紹介お願いします!

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

slateとaglioというAPI Document toolを使ったときの手順

はじめに

API Documentページを作成するにあたって slate, aglio というtoolを実際に触ったときの手順と感想です。

slate について

rubyで作成されたAPIドキュメントを作成するための ツールでマークダウンでドキュメントを記述できます。

slate 導入手順

1 リポジトリの準備
本家のリポジトリを開いて[use this template]をクリックし任意の場所にリポジトリを作成します。

作成したリポジトリをローカル環境へgit cloneします。

2 開発環境セットアップ
README.mdを見て頂くと分かるのですが起動方法は以下の3つが準備されています。
* Natively
* Using Vagrant
* Using Docker

手順もこちらへ記載してあり非常に親切ですね。

今回はNativelyUsing Dockerの手順をやってみたいと思います。

2-1 Natively(local環境へ直接installする) 手順
こちらに記載の手順を実行します。
※ 私の環境ではRuby、nodejsの開発環境は整っていたのでinstall部分は省略しました。

cd slate

bundle install

# middlemanはrubyのgemで静的なサイトを簡単に生成してくれます
bundle exec middleman server

以上です!

これで
http://localhost:4567/
へアクセスすると以下のようなAPI Documentのテンプレートが表示されます。

スクリーンショット 2020-07-26 19.55.51.jpg

2-2 Using Dockerの手順
こちらに記載の手順を実行します。

cd slate

docker build . -t slate

docker run -d --rm --name slate -p 4567:4567 -v $(pwd)/build:/srv/slate/build -v $(pwd)/source:/srv/slate/source slate

以上でNativelyと同じように
http://localhost:4567/
へアクセスするとAPI Documentのテンプレートが表示されます。

マークダウンファイルは sourceディレクトリにあるのでドキュメントの内容を修正する場合はこれを書き換えます。

3 Deploy手順
ここではこちらに記載してある手順でDeployしてみます。
ここに記載してあるのはGitHub Pagesに公開する手順で実行方法は下記コマンドを実行するだけです。

./deploy.sh

何とこれだけ!

これで実際に自分のGitHub Pagesのプロジェクトサイトが公開されているので確認してみて下さい。
URLは http://yourusername.github.io/slate です。
実際にdeployした私のGitHub Pagesはこちらです。

簡単に deploy.sh の内容を見ると

bundle exec middleman build --clean

で マークダウンファイルより build ディレクトリ配下へ静的ファイルを作成します。
スクリーンショット 2020-07-31 19.39.43.jpg

その後に build ディレクトリの内容を gh-pagesブランチへpushしています。

続いてaglioについて記載します。

aglio について

aglioとはAPI Blueprintで記述されたファイルをhtmlへ変換してくれるツールです。

API Blueprint
API Blueprint とは Web API の仕様を表現するための言語のことです。 API の仕様を表現するための様々な文法を持っています。 書き方は Markdown と同じ形式ですので、書き方も馴染みのあるものです。

aglio 導入手順

1 リポジトリの準備
GitHub上に任意のリポジトリを作成します。
(例: https://github.com/Nobuo-Hirai/api-document-use-aglio)
作成したリポジトリをgit cloneします。

2 開発環境セットアップ
document用のディレクトリ、ファイルを作成します。
root直下にmdディレクトリを作成しその中にdocument用のマークダウンファイルを作成していきます。
Dockerfile, docker-compose.ymlbuildディレクトリdeploy.shは後で説明するのでこの段階では必要ないです。

スクリーンショット 2020-07-31 20.11.49.jpg

環境構築用の Dockerfiledocker-compose.ymlを作成します。

Dockerfile

FROM node:latest

WORKDIR /projects

RUN npm install -g aglio --unsafe-perm

docker-compose.yml

docker-compose.yml
version: '3'

services:
  aglio:
    build: .
    ports:
      - '4000:4000'
    volumes:
      - './md:/projects'
      - './:/docs'
    tty: true
    # htmlを作成するときのテーマを決めれます。
    # https://github.com/danielgtaylor/aglio#example-output
    command: aglio --theme-variables default --theme-template triple -i index.md -s -h 0.0.0.0 -p 4000

dockerコンテナ構築・起動します。

docker-compose up --build

以上で http://localhost:4000/
へアクセスすると以下のようなAPI Documentのテンプレートが表示されていると思います。

スクリーンショット 2020-07-31 21.10.33.jpg

mdディレクトリ配下のマークダウンファイルを修正しAPI documentを作成していきます。

3 静的ファイルの作成
deploy用の静的ファイルを作成するため以下のコマンドを実行します。

# コンテナ内でhtmlを生成するコマンドを実行
docker-compose exec aglio bash

aglio --theme-variables default --theme-template triple -i index.md -o ../docs/index.html

以上で、index.htmlファイルが作成されたと思います。
続いて今回もGitHubPagesへdeployしたいと思います。

4 deploy.sh の作成
ここではslateで使用したdeploy.shを活用します。
slateで使用したdeploy.shをコピーしてroot直下へ配置します。

修正点は以下の部分です。

## slate
run_build() {
  bundle exec middleman build --clean
}
↓
↓
## aglio用に以下に書き換えます
run_build() {
  [[ ! -e ${deploy_directory} ]] && mkdir -p ${deploy_directory}
  cp index.html build/.
}

5 deploy手順

slateと同じように以下のコマンドを実行して終わりです。

./deploy.sh

これで実際にGitHub Pagesのプロジェクトサイトを確認してみて下さい。
実際にdeployした私のGitHub Pagesはこちらです。

参考リポジトリ

2つを試したリポジトリを以下に公開しています。
https://github.com/Nobuo-Hirai/api-document-use-slate
https://github.com/Nobuo-Hirai/api-document-use-aglio

2つを試してみての感想

自分がrubyの開発経験があったり環境を既に持っていたというのもありslateの方が簡単でした。
またslateの方がドキュメントが豊富で、star数も多いのでslateが無難かなという印象でした。

他に良いAPI Document toolがあれば紹介お願いします!

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

今日のメモ(パーセント記法、文字列演算、シンボル)

パーセント記法

『'』や『"』で囲んできた文字列を、パーセント記法では囲む記号を指定できる。
文字列の中で『"』を使うときにエスケープしなくてもよくなる。

#『"』無し
a = %*TEST*
p a  #=> "TEST"

#『"』あり
a = %*"TEST"*
p a  #=> "\"TEST\""
書式 生成される値
% ダブルクォート文字列
%Q ダブルクォート文字列
%q シングルクォート文字列
%s シンボル
%x コマンド出力
%r 正規表現

文字列演算

文字列では『+』と『*』を適用して連結することができる。

a = "ru" + "by"
puts a    #=> ruby

他にも末尾に連結する場合は『<<』も使用することができる。

a = "ru"
puts a << "by"    #=> ruby

※ですが、異なる文字コード(UTF-8とSJISなど)の連結はエラーが発生します。

追記:文字列の比較はlengthやsizeメソッドで文字数を参照できます。

シンボル

シンボルは主に文字列の前に『:』を置いて定義したもの。
ただし『"』で文字列を囲む必要は無い。

a = "ruby"
b = :study

p str.class    #=> String
p sym.class    #=> Symbol

パーセント記法を使ってもシンボルを生成することができる。

%s*test*    #=> :test

文字列からシンボルを生成する方法

a1 = "test"
a2 = a1.to_sym    # to_symメソッドを使用
p a2.class    #=> Symbol

作成したシンボルは、文字の並びが同じなら同一のオブジェクトIDを参照しますが、
文字列リテラルの場合は、文字の並びが同じでも、毎回新たにオブジェクトを生成するのでオブジェクトIDが変化します。

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

Railsアプリで日時の取得にはどのクラスを使うべきか(Time, DateTime, TimeWithZone)

日時の取得はどのクラスを使うべきか

  • Timeクラス
  • DateTimeクラス
  • TimeWithZoneクラス

Railsでは、特別な理由がない限り、
TimeクラスやDateTimeクラスより、TimeWithZoneクラスで統一した方が良い。

タイムゾーンについて

タイムゾーンを設定する場所は3箇所あります。

  • システム
  • 環境変数 ENV['TZ']
  • application.rb

application.rbにどのタイムゾーンが設定してあるか確認するには、Time.zone.nameを使います。

# application.rb
config.time_zone = 'Tokyo'

Time.zone.name
=> "Tokyo"

どのタイムゾーンが使われるのか

ややこしいことに、クラスやそのクラスに関連するメソッドによってどのタイムゾーンが使われるか変わります。
例えば、
Timeクラスに関連するメソッドnowを使ったTime.nowは環境変数のタイムゾーンを使い、
Timeクラスに関連するメソッドcurrentを使ったTime.currentはapplication.rbのタイムゾーンを使います。

#環境変数が使われ、classはTimeになる
[1] pry(main)> Time.now
=> 2020-07-31 19:39:18 +0900
[2] pry(main)> Time.now.class
=> Time

#application.rbが使われ、classはTimeWithZoneになる
[3] pry(main)> Time.current
=> Fri, 31 Jul 2020 19:39:35 JST +09:00
[4] pry(main)> Time.current.class
=> ActiveSupport::TimeWithZone

現在の日時の取得にはTime.currentかTime.zone.nowを使おう

現在の日時を取得する場合、以下の方法があります。

  1. Time.now (環境変数のタイムゾーンを使う)
  2. DateTime.now (環境変数のタイムゾーンを使う)
  3. Time.current (application.rbのタイムゾーンを使う)
  4. Time.zone.now (application.rbのタイムゾーンを使う)

結論としては、TimeWithZoneクラスである3または4を使っておいた方が良いです(もし国際的なアプリケーションにしようと思ったら色々と器用に扱える為)。

# 環境変数のタイムゾーンが使われる
[1] pry(main)> Time.now
=> 2020-07-31 19:43:14 +0900 #Timeクラス
[2] pry(main)> DateTime.now
=> Fri, 31 Jul 2020 19:43:21 +0900 #DateTimeクラス

# application.rbのタイムゾーンが使われる
[3] pry(main)> Time.current
=> Fri, 31 Jul 2020 19:43:26 JST +09:00 #ActiveSupport::TimeWithZoneクラス
[4] pry(main)> Time.zone.now
=> Fri, 31 Jul 2020 19:43:32 JST +09:00 #ActiveSupport::TimeWithZoneクラス

参考記事

以下の記事を参考にしました。記事ではとても詳しく説明してあります。
https://qiita.com/jnchito/items/cae89ee43c30f5d6fa2c

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

その5「Rails初心者」が5回連続で発生したエラーをなんとか切り抜けた話。「NameError」

前回の「その4」の続きです

前回の記事☞https://qiita.com/Shota_U/items/f41a2e0f2a1e24f98fc9

ついにこれが最後のエラーです。

今回発生したエラーは、

NameError (uninitialized constant)

というエラーです。

このエラーの

uninitialized constant は、
定義したクラスを読み取ることができない。

という意味だそうです。

そこで、まずファイル名とファイルパス、ファイルの中のクラス名を確認。

すると一か所、
単数形でないといけないファイル名をと複数形にしていたことが判明。

すぐ直してエラーが消えました!
これは割とうっかりミス、という感じです。

これまでのエラーよりは解決しやすかったかなと思います。
これで、5つすべてのエラーを解消することができました!

一応、ほかの4つの記事も載せておきます

その1 https://qiita.com/Shota_U/items/1f91709704476618aa0d
その2 https://qiita.com/Shota_U/items/c93eb669b3f8078785eb
その3 https://qiita.com/Shota_U/items/a589a080815032a24092
その4 https://qiita.com/Shota_U/items/f41a2e0f2a1e24f98fc9

これらのエラーと戦い、どうにか解決したうえで
改めて気づいたことが3つありました。(どれも初心者向けですが。。。)

ですので、ここで学んだことをまた次の記事で書こうと思います!

読んでくださり、ありがとうございました!

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

その4「Rails初心者」が5回連続で発生したエラーをなんとか切り抜けた話。「ArgumentError in income_Values#index」

前回の「その3」の続きです

前回の記事☞https://qiita.com/Shota_U/items/a589a080815032a24092

今回発生した新たなエラーは、

ArgumentError in income_Values#index

です

※すみません!エラーのスクショは撮っておりません

こちらのエラーは、

「引数の数があっていないときや、数は合っていて、期待される振る舞いを持ってはいるが、期待される値ではないときに発生する」

みたいです。

エラー文をよく見たところ、

wrong number of arguments (given 1, expected 0)
とありました。

これは、
「引数の数がちがうよー」
「正常な引数の数は0のはずなのに1個入ってるよ」

ってことらしいです

そこで引数を正しい数にしたところ、
やっと、一覧画面を表示することができました!!!

エラー文を知るって大事だなぁ。。。」

しかし、今度は新規投稿ができなくなっていました。

今度はNameErrorです。

せっかく実装できた!と思ったのに、、、

その5に続く?

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

その3「Rails初心者」が5回連続で発生したエラーをなんとか切り抜けた話。「NoMethodError in IncomeValues#index」

前回の「その2」の続きです

前回の記事☞https://qiita.com/Shota_U/items/c93eb669b3f8078785eb

3つ目のエラーです。
image.png

「NoMethodError in IncomeValues#index」

というのがでてきました。

これは、「NillClassにstrftimeなんていうメソッドはないよ」

ということみたいです

そこで、

income_value.year_month.strftime('%Y年%m月')

income_value.year_month&.strftime('%Y年%m月')

としたところ、無事解決できました。

しかし、
また次のエラー「ArgumentError」がでてきてしまいました。。。

これは、正直心折れそうでした(笑)。

その4へ続く?
https://qiita.com/Shota_U/items/f41a2e0f2a1e24f98fc9

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

その2「Rails初心者」が5回連続で発生したエラーをなんとか切り抜けた話。「ActiveRecord::StatementInvalid in IncomeValues#index」

前回の「その1」の続きです

前回の記事はこちら☞https://qiita.com/Shota_U/items/1f91709704476618aa0d

2つ目のエラーは

image.png

ということで、

「ActiveRecord::StatementInvalid in IncomeValues#index」

「データベースがおかしいよ」

ってことみたいです。

色々調べてみましたが、全く解決できませんでした。。
そこでQiitaで質問しました。

すると、ありがたいことに回答をいくつかいただきました。

どうやら、controllerの

IncomeValue.order("year_month asc")

が怪しいみたく、orderの指定の仕方がおかしいようです。

そこで、

IncomeValue.order("year_month asc")

としたところ、
このエラーがなくなりました!

君には苦戦したよ。。。って感じで
エラーが解消されたのはよいものの、、、

また次に
「NoMethodError in IncomeValues#index」
がでてきてしまったのです。。。

その3に続く?
https://qiita.com/Shota_U/items/a589a080815032a24092

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

その1「Rails初心者」が5回連続で発生したエラーをなんとか切り抜けた話。「index (投稿一覧) が表示できない」

ポートフォリオの家計簿アプリ作成中、非常に躓いた箇所がありましたので備忘録として書いていきます。

何に躓いたかというと、同じところで5回連続エラーが起こったのです。

※3~4日ほどでやっと解消できました?

今回はエラーの内容と、それを解決した方法をそれぞれ書いていきます。

苦悩の連続の全てはここから始まりました。

まず、エラー画面はでていないのですが、
投稿一覧が表示されないという事態が起こりました。

関係のあるコードはこちら

index.html.erb
<% require 'active_support/core_ext/numeric/conversions' %>
<h2>収入科目の新規データ登録</h2>
<p>登録年月を設定してください</p>
<%= form_tag({controller: :income_values, action: :new}, {method: :post}) do %>
    <input type="month" name="year_month">
    <input type="submit">
<% end %>

<h2>収入科目 データ一覧 </h2>
<% if @income_value.present? %>
<table>
  <tr>
    <th>登録年月</th>
    <th>名称</th>
    <th>値</th>
    <th>備考</th>
    <th>操作</th>
  </tr>
    <% @income_values.each do |income_value| %>
  <tr>
        <td><%= income_value.year_month.strftime('%Y年%m月') %></td>
        <td><%= @incomes.find(income_value.income_id).name %></td>
        <td><%= income_value.value.to_s(:delimited) %> 円</td>
        <td><%= income_value.description %></td>
        <td><%= link_to "編集", [:edit, income_value] %> | <%= link_to "削除", income_value, method: :delete, data: { confirm: "本当に削除しますか?"} %></td>
  </tr>
  <% end %>
</table>
<% else %>
    <p>登録されているデータがありません。</p>
<% end %>

income_values_controller.rb
class IncomeValuesController < ApplicationController

    def index
      @incomes = Income.order(created_at: :asc)
        @income_values = IncomeValue.order("year_month asc")
    end

    def show
        @income_value = IncomeValue.find(params[:id])
    end

    def new
        year_month_day = params[:year_month] + "-01"
        @year_month = year_month_day.to_date

        @incomes = Income.order(created_at: :asc)
        @form = Form::IncomeForm.new
    end

    def edit
        @income_value = IncomeValue.find(params[:id])
        @income = Income.find(@income_value.income_id)
    end

    def create
        @form = Form::IncomeForm.new(income_form_params)
        if @form.save
            redirect_to :income_values, notice: "登録しました"
        else
            redirect_to :income_values, notice: "登録に失敗しました"
        end
    end

    def income_form_params
        params
            .require(:form_income_form)
            .permit(income_values_attributes: Form::IncomeValue::REGISTRABLE_ATTRIBUTES)
    end

    def update
        @income_value = IncomeValue.find(params[:id])
        @income_value.assign_attributes(params[:income_value])
        if @income_value.save
            redirect_to :income_values, notice: "情報を更新しました"
        else

一覧が表示されなかった原因は、

index.html.erb

<% if @income_value.present? %>

の変数が単数形だったからでした。

<% if @income_values.present? %>

として、解決!

しっかり確認することの大切さを改めて実感しました。

原因が分かって、
「一覧が表示される!」と思いきや、

「ActiveRecord::StatementInvalid」というエラーがでてしまったのです。。。

そして僕はこのエラーにとてつもなく苦しみました。

その2に続く?
https://qiita.com/Shota_U/items/c93eb669b3f8078785eb

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

木構造のacts_as_treeで、N+1を消し去る

木構造

古いコードを見ると、アンチパターンが多いですね。今回も同様にアンチパターンの一つである隣接リストが使われていました。さらに、N+1問題が放置され、パフォーマンス的に悪いということで対応することになりました。
今回は、たった2階層だったので、隣接リストでもあまり問題がなさそうです。

GitHub

https://github.com/amerine/acts_as_tree

使い方

https://github.com/amerine/acts_as_tree#example 引用

class Category < ActiveRecord::Base
  acts_as_tree order: "name"
end

root      = Category.create("name" => "root")
child1    = root.children.create("name" => "child1")
subchild1 = child1.children.create("name" => "subchild1")

root.parent   # => nil
child1.parent # => root
root.children # => [child1]
root.children.first.children.first # => subchild1

前提

parent_id (あるいは、任意のキー) を木構造の親キーとします。

schema例

  create_table "technologies", force: :cascade do |t|
    t.string "name"
    t.bigint "parent_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["parent_id"], name: "index_technologies_on_parent_id"
  end

N+1の消し去り方

modelに追加した acts_at_tree によって、 children メソッドが生えますので、そちらをincludesして関連付け、事前に最小限のクエリ回数にて読み込まれるようにします。

解消コード

# model
class Technology < ApplicationRecord
  acts_as_tree

  def dig
    if children.empty?
      self
    else
      children.map(&:dig)
    end
  end
end

includesを付与してあげます。

# console
Technology
  .where(parent: nil)
  .includes(children: { children: [:children] }))
  .map(&:dig)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby on Railsの木構造Gemのacts_as_treeで、N+1を消し去る

手元動作環境

当然、サービスインしているコードを乗せるわけにはいかないので、手元環境で似たようなコードを書いて動作検証しています。

  • ruby 2.7.1p83
  • Rails 6.0.3.2
  • acts_as_tree (2.9.1)

木構造

古いコードを見ると、アンチパターンが多いですね。今回も同様にアンチパターンの一つである隣接リストが使われていました。さらに、N+1問題が放置され、パフォーマンス的に悪いということで対応することになりました。
今回は、たった2階層だったので、隣接リストでもあまり問題がなさそうです。

GitHub

https://github.com/amerine/acts_as_tree

使い方

https://github.com/amerine/acts_as_tree#example 引用

class Category < ActiveRecord::Base
  acts_as_tree order: "name"
end

root      = Category.create("name" => "root")
child1    = root.children.create("name" => "child1")
subchild1 = child1.children.create("name" => "subchild1")

root.parent   # => nil
child1.parent # => root
root.children # => [child1]
root.children.first.children.first # => subchild1

前提

parent_id (あるいは、任意のキー) を木構造の親キーとします。

schema例

  create_table "technologies", force: :cascade do |t|
    t.string "name"
    t.bigint "parent_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["parent_id"], name: "index_technologies_on_parent_id"
  end

N+1の消し去り方

modelに追加した acts_at_tree によって、 children メソッドが生えますので、そちらをincludesして関連付け、事前に最小限のクエリ回数にて読み込まれるようにします。

解消コード

# model
class Technology < ApplicationRecord
  acts_as_tree

  def dig
    if children.empty?
      self
    else
      children.map(&:dig)
    end
  end
end

includesを付与してあげます。

# console
Technology
  .where(parent: nil)
  .includes(children: { children: [:children] }))
  .map(&:dig)

response

2階層のコードを抜き出して見ると、このような形になります。

{
  "id":6,
  "name":"AWS",
  "parent_id":null,
  "children":[
    {
      "id":7,
      "name":"コンピューティング",
      "parent_id":6,
      "children":[
        {
          "id":8,
          "name":"EC2",
          "parent_id":7
        },
        {
          "id":9,
          "name":"Elastic Beanstalk",
          "parent_id":7
        },
        {
          "id":10,
          "name":"Lambda",
          "parent_id":7
        }
      ]
    }
  ]
}

発行SQLの比較

includesがない場合の例

60件ぐらいデータを入れてみた
データに応じて、SQLの数が増加していく

SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" IS NULL
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 1], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 2], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 3], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 4], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 5], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 6], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 6]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 7], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 7]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 8], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 9], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 10], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 11], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 11]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 12], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id  SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id  SELECT 1 AS one F_i  SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id  SE= $1  [["parent_id", 14]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 15], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 16], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 16]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 17], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["paren  SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["paren  SELECT 1 AS one FROM "ent_id", 19], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 20], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 20]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 21], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 22], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 23], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIM  SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIM  SELECT 1 AS one FROM "technologies" W" = $1  [["parent_id", 24]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 25], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 26], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 27], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 28], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 29], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIM  SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIM  SELECT 1 AS one FROM "technologies" WIMIT $2  [["parent_id", 31], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 31]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 32], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 33], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 34], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 34]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 35], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 36], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 37], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 38], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 39], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 39]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 40], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 41], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 42], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 42]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 43], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 44], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 44]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 45], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 46], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 46]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 47], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 48], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 49], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["paren  SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["paren  SELECT 1 AS one FROM "ent_id", 51], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 51]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 52], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 53], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 54], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 55], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id"   SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id"   SELECT "technologies".* FROM "technolent_id", 56], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 57], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 58], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 59], ["LIMIT", 1]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" = $1  [["parent_id", 59]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["paren  SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["paren  SELECT 1 AS one FROM "ent_id", 61], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 62], ["LIMIT", 1]]
SELECT 1 AS one FROM "technologies" WHERE "technologies"."parent_id" = $1 LIMIT $2  [["parent_id", 63], ["LIMIT", 1]]

N+1問題解消時の例

SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" IS NULL
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" IN ($1, $2, $3, $4, $5, $6)  [["parent_id", 1], ["parent_id", 6], ["parent_id", 46], ["parent_id", 51], ["parent_id", 55], ["parent_id", 59]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" IN ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29)  [["parent_id", 2], ["parent_id", 3], ["parent_id", 4], ["parent_id", 5], ["parent_id", 7], ["parent_id", 11], ["parent_id", 14], ["parent_id", 16], ["parent_id", 20], ["parent_id", 24], ["parent_id", 31], ["parent_id", 34], ["parent_id", 39], ["parent_id", 42], ["parent_id", 44], ["parent_id", 47], ["parent_id", 48], ["parent_id", 49], ["parent_id", 50], ["parent_id", 52], ["parent_id", 53], ["parent_id", 54], ["parent_id", 56], ["parent_id", 57], ["parent_id", 58], ["parent_id", 60], ["parent_id", 61], ["parent_id", 62], ["parent_id", 63]]
SELECT "technologies".* FROM "technologies" WHERE "technologies"."parent_id" IN ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)  [["parent_id", 8], ["parent_id", 9], ["parent_id", 10], ["parent_id", 12], ["parent_id", 13], ["parent_id", 15], ["parent_id", 17], ["parent_id", 18], ["parent_id", 19], ["parent_id", 21], ["parent_id", 22], ["parent_id", 23], ["parent_id", 25], ["parent_id", 26], ["parent_id", 27], ["parent_id", 28], ["parent_id", 29], ["parent_id", 30], ["parent_id", 32], ["parent_id", 33], ["parent_id", 35], ["parent_id", 36], ["parent_id", 37], ["parent_id", 38], ["parent_id", 40], ["parent_id", 41], ["parent_id", 43], ["parent_id", 45]]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Controllerに定義するアクション一覧

Controllerに定義するアクション一覧

RailsではWebアプリケーションの基本となる以下の7つの役割を持つアクションを用います。

アクション名 役割
new データを新規作成する
create データを追加(保存)する
index データの一覧を表示する
show データの内容(詳細)を表示する
edit データを更新するためのフォームを作成する
update データを更新する
destroy データを削除する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails入門】renderの使い方

rendearの使い方

renderメソッドを用いることで、別のアクションを経由せずに、直接ビューを表示することができます。
render("フォルダ名/ファイル名")のように表示したいビューを指定します。
renderメソッドを使うと、redirect_toメソッドを使った場合と違い、そのアクション内で定義した@変数をビューでそのまま使うことができます。

user_controller.rb
class UserController < ApplicationController
  def top
    @user = User.find_by(email: params[:email], password: params[:password])
    if @user

    else
      render ("home/signup")
    end

  end
end

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

【初心者】Rubyの配列に対する繰り返し処理色々

実行環境

超基本的な内容なので、実行環境に左右されないと思いますが、一応明記しておきます。
OS : macOS Catalina ver10.15.5
Ruby : 2.7.1p83

each

基本的な繰り返し処理。要素を一つづつ取り出して処理を行なっていく。
do ~ end で囲むのが基本。変数のスコープに注意。

sample.rb
numbers = [1, 2, 4, 5, 6]

total = 0
numbers.each do |num|
  total += num
end
p total # 18 

map

配列を返してくれることが特徴。下記の処理は要素に10を足して出力している。
簡単な処理ならばdo ~ end の代わりに { }で記入可能。

sample.rb
numbers = [1, 2, 4, 5, 6]

nuadd_num = numbers.map {|num| num + 10}

p add_num
# [11, 12, 14, 15, 16]

select

処理内の判定に合致した値を配列として返している。

sample.rb
numbers = [1, 2, 4, 5, 6]

numbers2 = numbers.select {|num| num % 2 == 0}

p numbers2
# [2, 4, 6]

reject

処理内の判定に合致しない値を配列として返している。selectの逆。

sample.rb
numbers = [1, 2, 4, 5, 6]

numbers2 = numbers.reject {|num| num % 2 == 0}

p numbers2
# [1, 5]

inject

たたみ込み処理。num と i にそれぞれ要素が代入され処理を行なっていく。

sample.rb
numbers = [1, 2, 4, 5, 6]

numbers2 = numbers.inject {|num, i| num + i}

# 1回目のループ num = 1, i = 2
# 2回目のループ num = 3, i = 4
# 3回目のループ num = 7, i = 5
# 4回目のループ num = 12, i = 6

p numbers2
# 18

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

Ruby: CouchDB のデータを削除 (Delete)

couch_delete.rb
#! /usr/bin/ruby
# -*- encoding: utf-8 -*-
#
#   couch_delete.rb
#
#                   Jul/31/2020
#
# ---------------------------------------------------------------------
require 'faraday'
require 'json'
#
# ---------------------------------------------------------------------
STDERR.puts "*** 開始 ***"
#
key_in = ARGV[0]
puts key_in

URL="http://localhost:5984/nagano/" + key_in
#
res = Faraday.get URL

puts    res.status

if res.status == 200 then
    json_str = res.body

    data_aa=JSON.parse(json_str)
#
    puts data_aa
    puts data_aa["_rev"]
#
    url_del = URL + "?rev=" + data_aa["_rev"]

    res = Faraday.delete url_del

    puts res.status
end

STDERR.puts "*** 終了 ***"
# ---------------------------------------------------------------------

実行

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

Ruby: CouchDB のデータを更新 (Update)

couch_update.rb
#! /usr/bin/ruby
# -*- encoding: utf-8 -*-
#
#   couch_update.rb
#
#                   Jul/31/2020
#
# ---------------------------------------------------------------------
require 'faraday'
require 'json'
require 'date'
#
# ---------------------------------------------------------------------
STDERR.puts "*** 開始 ***"
#
key_in = ARGV[0]
population_in = ARGV[1].to_i
puts key_in,population_in

URL="http://localhost:5984/nagano/" + key_in
#
res = Faraday.get URL

puts    res.status

if res.status == 200 then
    json_str = res.body

    data_aa=JSON.parse(json_str)
#
    puts data_aa
    puts data_aa["_rev"]
    puts data_aa["name"]
#
    args = {}
    args["name"] = data_aa["name"]
    args["population"] = population_in
    args["date_mod"] = Date.today

    url_up = URL + "?rev=" + data_aa["_rev"]

    con = Faraday.new 
    res = con.put do |req|
        req.url url_up
        req.headers['Content-Type'] = 'application/json'
        req.body = JSON.pretty_generate(args)
    end

    puts res.status
end

STDERR.puts "*** 終了 ***"
# ---------------------------------------------------------------------

実行

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

Ruby: CouchDB のデータを読む (Read)

couch_read.rb
#! /usr/bin/ruby
# -*- encoding: utf-8 -*-
#
#   couch_read.rb
#
#                   Jul/31/2020
#
# ---------------------------------------------------------------------
require 'faraday'
require 'json'
#
# ---------------------------------------------------------------------
STDERR.puts "*** 開始 ***"
#
URL="http://localhost:5984/nagano/_all_docs?include_docs=true"
#
res = Faraday.get URL

# puts  res.status

json_str = res.body

dict_data=JSON.parse(json_str)
#
dict_data['rows'].each {|value|
        doc = value["doc"]
        str_out = doc["_id"] + "\t" + doc['name'] + "\t" \
            + doc["population"].to_s + "\t" + doc['date_mod']
        print(str_out,"\n")
    }
#
STDERR.puts "*** 終了 ***"
# ---------------------------------------------------------------------

実行

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

Ruby: CouchDB のデータを作成 (Create)

couch_create.rb
#! /usr/bin/ruby
# -*- encoding: utf-8 -*-
#
#   couch_create.rb
#
#                   Jul/31/2020
#
# ---------------------------------------------------------------------
require 'faraday'
require 'json'
#
# ---------------------------------------------------------------------
def dict_append_proc (dict_aa,key,name,population,date_mod)
    unit = {}
    unit['name'] = name
    unit['population'] = population
    unit['date_mod'] = date_mod
    dict_aa[key] = unit
    return dict_aa
end

# ---------------------------------------------------------------------
def prepare_data_proc ()
dict_aa={}

dict_aa=dict_append_proc(dict_aa,'t2021',"長野",51847,"2006-3-19")
dict_aa=dict_append_proc(dict_aa,'t2022',"松本",23789,"2006-7-27")
dict_aa=dict_append_proc(dict_aa,'t2023',"上田",47251,"2006-2-8")
dict_aa=dict_append_proc(dict_aa,'t2024',"小諸",78623,"2006-1-22")
dict_aa=dict_append_proc(dict_aa,'t2025',"岡谷",91489,"2006-5-11")
dict_aa=dict_append_proc(dict_aa,'t2026',"塩尻",27915,"2006-4-17")
dict_aa=dict_append_proc(dict_aa,'t2027',"茅野",36972,"2006-9-18")
dict_aa=dict_append_proc(dict_aa,'t2028',"飯田",74921,"2006-8-15")
dict_aa=dict_append_proc(dict_aa,'t2029',"中野",81923,"2006-10-11")
dict_aa=dict_append_proc(dict_aa,'t2030',"諏訪",47598,"2006-9-12")
dict_aa=dict_append_proc(dict_aa,'t2031',"駒ヶ根",51738,"2006-7-22")
dict_aa=dict_append_proc(dict_aa,'t2032',"佐久",82514,"2006-8-17")
dict_aa=dict_append_proc(dict_aa,'t2033',"伊那",74361,"2006-12-29")
dict_aa=dict_append_proc(dict_aa,'t2034',"千曲",67293,"2006-10-18")

end
# ---------------------------------------------------------------------
STDERR.puts "*** 開始 ***"
#

URL="http://localhost:5984/nagano"
#
res = Faraday.delete URL
puts    res.status

res = Faraday.put URL
puts    res.status

#
dict_aa=prepare_data_proc()
#
dict_aa.sort.each {|key, value|
    url_aa = URL + "/" + key
    puts url_aa
    con = Faraday.new 
    res = con.put do |req|
        req.url url_aa
        req.headers['Content-Type'] = 'application/json'
        req.body = JSON.pretty_generate(value)
    end
}

STDERR.puts "*** 終了 ***"

# ---------------------------------------------------------------------

実行

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

【エラー】Ruby on Rails のoss(オープンソース)を使うために、環境構築 切り替え

はじめに

OSSから知識をパク...、引き出しを増やす!!

独学で知識を広げるために、先人が開発したオープンソースから技術を学ぶことにしました。
そのため、ruby環境を切り替えなどが必要になりました。dockerで気軽に遊べるので、ローカル環境で直接環境を切り替えるのは、普段避けてきました。

しかしこの際、ローカル環境でやってしまおう!と思い試みました。
結果的に理解が深まり、自分のためになりました。

早速やっていく

まず、Railsで開発されているOSSの記事より、面白そうで、美味しそうなOSSをニヤニヤ眺め、獲物を定めます。

業務システム?
なんとも美味しそうだ

明細を出すシステム? おお、管理画面含めて面白そうかもしれない。
https://github.com/vteams/open-source-billing/
ただ単に明細を出すなら調べて出るが、UIまで学べるのは美味しい

君に決めた!!

$ git clone https://github.com/vteams/open-source-billing.git

相当なコード量なのでしょう。
ダウンロードに恐ろしく時間がかかります。

楽しみでならない。
ウハウハしながら待ちます。

ついに、ダウンロードできた!!

よし、db:createだ!!!

open-source-billing owner$ rake db:create
rake aborted!
LoadError: cannot load such file -- bundler/setup
/Users/owner/projects/oss/open-source-billing/config/boot.rb:3:in `<top (required)>'
/Users/owner/projects/oss/open-source-billing/config/application.rb:1:in `<top (required)>'
/Users/owner/projects/oss/open-source-billing/Rakefile:5:in `<top (required)>'
(See full trace by running task with --trace)

うぇーい
エラー 出ますやん。

LoadError: cannot load such file -- bundler/setup

ままま、 bundlerのバージョンが違うとかだろ。
わかってるよ。

$ bundle -v

これで、バージョン確認だ!!

open-source-billing owner$ bundle -v
Traceback (most recent call last):
    2: from /Users/owner/.rbenv/versions/2.5.1/bin/bundle:23:in `<main>'
    1: from /Users/owner/.rbenv/versions/2.5.1/lib/ruby/2.5.0/rubygems.rb:308:in `activate_bin_path'
/Users/owner/.rbenv/versions/2.5.1/lib/ruby/2.5.0/rubygems.rb:289:in `find_spec_for_exe': can't find gem bundler (>= 0.a) with executable bundle (Gem::GemNotFoundException)

ははーん、バージョン見せてくれませんか
なるほど。

じゃあ、Gemfile.lockから見てみよう

Gemfile.lock
BUNDLED WITH
   2.1.4

やっぱり、載ってますやーん
2.1.4を利用しているのね。

じゃあ、今自分のmacのbundlerは、、、、、

~ owner$ bundle -v
Bundler version 2.0.2

2.0.2を使っているので、だからエラーが起こっているのか。

あれ? 過去に2.1.4使ってなかったっけ?

$ gem list bundler

これで確認だ!!

~ owner$ gem list bundler

*** LOCAL GEMS ***

bundler (2.0.2, 1.3.0)
capistrano-bundler (1.6.0)

使ってないわ笑
思い過ごしか。

じゃあ、2.1.4をインストールしよう!!

bundlerをインストール!!!

~ owner$ gem install bundler -v 2.1.4

これでインストールだ!!

~ owner$ gem install bundler -v 2.1.4
ERROR:  While executing gem ... (Errno::EACCES)
    Permission denied @ rb_sysopen - /Users/owner/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-2.1.4/CHANGELOG.md

なんだって。。。。

Permission denied

Permissionだから、許可されてねーのか。権限関連みたいだな

それより、

ERROR:  While executing gem ... (Errno::EACCES)

このエラーは、なんだろうか???
早速ググってみよう。

ERROR: While executing gem ... (Errno::EACCES)が出た時の解決法
先人の方、ありがとうございます!!!

どれどれ
うんうん、よくわからん。
この人が参考にした元の記事を見よう

$sudo chown -R (ユーザ名):staff /Users/(ユーザ名)/.rbenv

このコマンドをすればいいのね
ownerアカウントを使っているから

$sudo chown -R owner:staff /Users/owner/.rbenv

でいいのかな
早速実行だ

MacBook-Air:~ owner$ sudo chown -R owner:staff /Users/owner/.rbenv
MacBook-Air:~ owner$ gem install bundler -v 2.1.4


Successfully installed bundler-2.1.4
Parsing documentation for bundler-2.1.4
Done installing documentation for bundler after 4 seconds
1 gem installed

成功したやん!!
先人の方、ありがとおおおおう!!

LGTM押しておこう

じゃあ、もう一度 db:createだ!

$ rake db:create

実行!!

MacBook-Air:open-source-billing owner$ rake db:create
Your Ruby version is 2.5.1, but your Gemfile specified 2.7.1

あれま、rubyのバージョンも違うのか。
自分が使っているのが、2.5.1 で, このOSSは2.7.1を利用しているのか。

じゃあ、ruby 2.7.1をインストールだ!!!

とりあえず、どのバージョンをインストールできるか確認してみようか

$ rbenv install -l

で確認っと。

OwnernoMacBook-Air:~ owner$ rbenv install -l
2.5.8
2.6.6
2.7.1
jruby-9.2.11.1
maglev-1.0.0
mruby-2.1.0
rbx-4.15
truffleruby-20.1.0

Only latest stable releases for each Ruby implementation are shown.
Use 'rbenv install --list-all' to show all local versions.

しっかり、2.7.1ありますね

じゃあ、2.7.1を指定して、インストールっと。

$ rbenv install 2.7.1

なかなかに長い。。。。

OwnernoMacBook-Air:~ owner$ rbenv install 2.7.1
Downloading openssl-1.1.1g.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
Installing openssl-1.1.1g...
Installed openssl-1.1.1g to /Users/owner/.rbenv/versions/2.7.1

Downloading ruby-2.7.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.1.tar.bz2
Installing ruby-2.7.1...
ruby-build: using readline from homebrew
Installed ruby-2.7.1 to /Users/owner/.rbenv/versions/2.7.1

ようやく終わった!!!

念のためにリフレッシュして、再読み込みさせておきますかね

再読み込み
$rbenv rehash

あとは、最近はdockerを使っているので、
標準利用しているバージョンをossに合わせよう

rubyは2.7.1を基本的に利用
rbenv global 2.7.1

じゃあ、これで db:createやってみますかね

open-source-billing owner$ rake db:create

Could not find rake-10.5.0 in any of the sources
Run `bundle install` to install missing gems.

ほうほう、Run'bundle install'`と出てるから、

$ bundle install

すればいいのね

bundle install 実行!!

.
.
.
Installing libv8 3.16.14.19 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
.
.
.
An error occurred while installing libv8 (3.16.14.19), and Bundler cannot continue.
Make sure that `gem install libv8 -v '3.16.14.19' --source 'https://rubygems.org/'` succeeds before bundling.

え、、、、。
まだ、エラー出るの???

よくみたら二つエラーがあるみたい。
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
これからググって見よう

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
先人ありがとう><

どうも、このエラーの直前のgemでエラーの原因のようだ

Installing libv8 3.16.14.19 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

この場合だと
libv8が原因みたいだね

さっきのもう一つのエラーもlibv8だったような

An error occurred while installing libv8 (3.16.14.19), and Bundler cannot continue.
Make sure that `gem install libv8 -v '3.16.14.19' --source 'https://rubygems.org/'` succeeds before bundling.

あーー、やっぱりそうだね。

$ gem install libv8 -v '3.16.14.19' --source 'https://rubygems.org/'

上記のコマンドしろって命が書かれているから、まずはこっちからやってみよう。

$ gem install libv8 -v '3.16.14.19' --source 'https://rubygems.org/'
.
.
.
An error occurred while installing libv8 (3.16.14.19), and Bundler cannot continue.
Make sure that `gem install libv8 -v '3.16.14.19' --source 'https://rubygems.org/'` succeeds before bundling.

変わらないかあT^T

どうもよくあるエラーっぽいなあ

In Gemfile:
  therubyracer was resolved to 0.12.3, which depends on
    libv8

うんうん、therubyracerが原因みたいだ

このサイトに同じ症状が載っていたので、実行してみよう

ジッッ香

$ bundle config --local build.libv8 --with-system-v8 You are replacing the current $ bundle config --local build.therubyracer --with-v8-dir=$(brew --prefix v8-315)

お、エラーも何もない

じゃあ、`bundle installしてみましょうかねええ

open-source-billing owner$ bundle install

ん??

An error occurred while installing rmagick (2.15.4), and Bundler cannot continue.
Make sure that `gem install rmagick -v '2.15.4' --source 'https://rubygems.org/'` succeeds before bundling.

今度は、rmagickのエラーですか。
もしかして、、、いろんなgemこれの繰り返しなんじゃ。。。。。

とにかくやってみよう

$gem install rmagick -v '2.15.4' --source 'https://rubygems.org/'
open-source-billing owner$ gem install rmagick -v '2.15.4' --source 'https://rubygems.org/'



Building native extensions. This could take a while...
ERROR:  Error installing rmagick:
    ERROR: Failed to build gem native extension.

    current directory: /Users/owner/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/rmagick-2.15.4/ext/RMagick
/Users/owner/.rbenv/versions/2.7.1/bin/ruby -I /Users/owner/.rbenv/versions/2.7.1/lib/ruby/2.7.0 -r ./siteconf20200730-12130-sp4zhp.rb extconf.rb
checking for clang... yes
checking for Magick-config... no
checking for pkg-config... yes
checking for outdated ImageMagick version (<= 6.4.9)... no
checking for Ruby version >= 1.8.5... yes
checking for stdint.h... yes
checking for sys/types.h... yes
checking for wand/MagickWand.h... no

Can't install RMagick 2.15.4. Can't find MagickWand.h.
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

おーーーー、、、、やはり出たか

んーーーーー。なんだ
よくわからん。

ひとまず
ERROR: Error installing rmagick:
で検索してみよう。

gem install rmagick でインストール失敗

先人ありがとうううう!!!

どれどれ、
うんうん、ダウンロードして、直接macに入れる...。
よし、却下だ。
絶対にコマンドでいけるでしょ。
だって、コマンドでもダウンロードできるのだから。

他に良い記事はないかなと、、、

gem install rmagickでchecking for Magick-config... noがでる解決方法

hecking for Magick-config... noが怪しい?
どれどれ

ERROR:  Error installing rmagick:
    ERROR: Failed to build gem native extension.

    current directory: /Users/owner/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/rmagick-2.15.4/ext/RMagick
/Users/owner/.rbenv/versions/2.7.1/bin/ruby -I /Users/owner/.rbenv/versions/2.7.1/lib/ruby/2.7.0 -r ./siteconf20200730-12130-sp4zhp.rb extconf.rb
checking for clang... yes
checking for Magick-config... no
checking for pkg-config... yes
checking for outdated ImageMagick version (<= 6.4.9)... no
checking for Ruby version >= 1.8.5... yes
checking for stdint.h... yes
checking for sys/types.h... yes
checking for wand/MagickWand.h... no

あ、このエラーのyesは問題なくて、noに問題があるのか!!!
なるほど!!!

で、Magick-configImageMagickが怪しいと!!
なるほどねえええ!!

じゃあ、解決策を参考にさせていただきます。

sudo: yum: command not found

あ、使えないのか

command not foundのエラーの解消方法
何気なくコマンド使っていたけど、こういう違いがあったのか、勉強になりました。
しかも、この人おそらく同じエラーじゃないですか

$ brew install ImageMagick

これでやってみようかな

$ brew install ImageMagick
Error: imagemagick 7.0.10-18 is already installed
To upgrade to 7.0.10-24, run `brew upgrade imagemagick`.

うんうん、すでに入っているみたいですねえ。そうですよねえ、過去に使ったことありますもんねええ

$ brew upgrade imagemagick

ひとまずアップデートしてみます

Error: Your Xcode (10.3) is too outdated.
Please update to Xcode 11.5 (or delete it).
Xcode can be updated from the App Store.

Error: Could not find an SDK that supports macOS 10.15.
You may have have an outdated or incompatible Xcode.
Homebrew found the following SDKs in the Xcode install:
  10.14

なんだか、これ以上やると環境を破壊する気配がする。。。
いや、それはないな。

そもそも、xcodeってiOSのシュミレーター用に入れたアプリだよね

Xcode can be updated from the App Store.

あー、やっぱりそうだよねえ。

ということは、最新バージョンのXcodeにアップデートしなはれと言われているのか。
そういえば、macアップデートしてから、xcodeアップデートしてなかったもんなあ

ということで、Appp Storeから最新版のXcodeをインストール
その後に

$brew reinstall imagemagick@6
$open-source-billing owner$ gem install rmagick
Building native extensions. This could take a while...
Successfully installed rmagick-4.1.2
Parsing documentation for rmagick-4.1.2
Done installing documentation for rmagick after 1 seconds
1 gem installed

お、成功しました!!

これで、bundle installしてみると、、、

Fetching rmagick 2.15.4
Installing rmagick 2.15.4 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.



An error occurred while installing rmagick (2.15.4), and Bundler cannot continue.
Make sure that `gem install rmagick -v '2.15.4' --source 'https://rubygems.org/'` succeeds before bundling.

やっぱり、ダメですね

ん???

よくみるとエラーで要求されているのはrmagick (2.15.4)で、先ほど入れたrmagickはrmagick-4.1.2でしたから、バージョンが違うことでエラーが起こっているかもしれない。

Gemfile
gem 'rmagick', '4.1.2' 

に変更します。

これでいけるかなあ?とbundle install

An error occurred while installing therubyracer (0.12.3), and Bundler cannot continue.
Make sure that `gem install therubyracer -v '0.12.3' --source 'https://rubygems.org/'` succeeds before bundling.

therubyracerまた君かい(笑)
さっき解決したでしょう(笑)

therubyracerも今の環境に合わせて、バージョンを指定すればいけるかな?
と思いぐぐるとある記事に遭遇する

時代はmini_racerだった

ッッハ!!

gem: 'therubyracer'は削除!!

Gemfile
gem 'mini_racer'

代わりにmini_racer足しましたよ

これでどうだ!!

$ bundle install

Using slim-rails 3.1.0
Using stripe 1.56.0
Fetching tinymce-rails 4.3.13
Installing tinymce-rails 4.3.13
Fetching to_words 1.1.1
Installing to_words 1.1.1
Fetching trackstamps 0.0.9
Installing trackstamps 0.0.9
Fetching twitter-bootstrap-rails 2.1.9
Installing twitter-bootstrap-rails 2.1.9
Fetching uglifier 3.0.0
Installing uglifier 3.0.0
Fetching unix_utils 0.0.15
Installing unix_utils 0.0.15
Fetching whenever 0.9.7
Installing whenever 0.9.7
Fetching wicked_pdf 2.0.2
Installing wicked_pdf 2.0.2
Fetching wkhtmltopdf-binary 0.9.9.3
Installing wkhtmltopdf-binary 0.9.9.3
Fetching xlsx_writer 0.4.4
Installing xlsx_writer 0.4.4
Fetching yajl-ruby 1.3.1
Installing yajl-ruby 1.3.1 with native extensions
Bundle complete! 104 Gemfile dependencies, 230 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Post-install message from twitter-bootstrap-rails:
Important: You may need to add a javascript runtime to your Gemfile in order for bootstrap's LESS files to compile to CSS. 

**********************************************

ExecJS supports these runtimes:

therubyracer - Google V8 embedded within Ruby

therubyrhino - Mozilla Rhino embedded within JRuby

Node.js

Apple JavaScriptCore - Included with Mac OS X

Microsoft Windows Script Host (JScript)

**********************************************

いちよう、成功したみたいです。

ただ、

Important: You may need to add a javascript runtime to your Gemfile in order for bootstrap's LESS files to compile to CSS. 
#重要: bootstrapのLESSファイルをCSSにコンパイルするために、javascriptランタイムをGemfileに追加する必要があるかもしれません。

**********************************************

ExecJS supports these runtimes:

therubyracer - Google V8 embedded within Ruby

therubyrhino - Mozilla Rhino embedded within JRuby

Node.js

Apple JavaScriptCore - Included with Mac OS X

Microsoft Windows Script Host (JScript)

**********************************************

jsが使えるかどうか、確認する必要はあるみたいですね

ExecJS::RubyRacerRuntime is not supported. Please replace therubyracer with mini_racer in your Gemfile or use Node.js as ExecJS runtime.
#ExecJS::RubyRacerRuntimeはサポートされていません。Gemfileでtherubyracerをmini_racerに置き換えるか、ExecJSランタイムとしてNode.jsを使用してください。

モノによっては、上記のよ8うにtherubyracerをmini_racerに置き換えるように指示がある程ですし、問題ないでしょう。

$rails s

ひとまず、サーバー起動できるか確認してみます。

Change:
  >> #<#<Class:0x00007fe292f30580>:0x00007fe29a81d588>.call(template)
To:
  >> #<#<Class:0x00007fe292f30580>:0x00007fe29a81d588>.call(template, source)
 (called from <top (required)> at /Users/owner/projects/oss/open-source-billing/config/application.rb:8)
[DEPRECATION] This gem has been renamed to hashie-forbidden_attributes and will no longer be supported. Please switch to hashie-forbidden_attributes as soon as possible.

何かのgemがサポート終了しているので、hashie-forbidden_attributesに書き換えろと言われています。

怪しいのはこれ

gem 'hashie_rails', '0.0.4'

gem 'hashie_rails'のgithubをみてみます。

HashieRails
Moved to HashieForbiddenAttributes.

お!、やっぱり、hashie-forbidden_attributesに変わっていますね!!

gem 'hashie-forbidden_attributes'

これに、書き換えて、bundle installします。

$ rails s

これで起動できるかな????

$ rails s
DEPRECATION WARNING: Single arity template handlers are deprecated. Template handlers must
now accept two parameters, the view object and the source for the view object.
Change:
  >> #<#<Class:0x00007f9aa1b5e5f8>:0x00007f9aa1b574b0>.call(template)
To:
  >> #<#<Class:0x00007f9aa1b5e5f8>:0x00007f9aa1b574b0>.call(template, source)
 (called from <top (required)> at /Users/owner/projects/oss/open-source-billing/config/application.rb:8)
=> Booting Puma
=> Rails 6.0.2.2 application starting in development 
=> Run `rails server --help` for more startup options

ダメですねえ

DEPRECATION WARNING: Single arity template handlers are deprecated. Template handlers must
now accept two parameters, the view object and the source for the view object.

警告: シングルアリティのテンプレートハンドラは非推奨です。テンプレートハンドラは
ビューオブジェクトとビューオブジェクトのソースの2つのパラメータを受け付けるようになりました。
という意味みたいです。

とりあえず検索してみます。

【Rails6】DEPRECATION WARNING: Single arity template handlers are deprecated. Template handlers must now accept two parameters, the view object and the source for the view object.
出てきましたね

本当にありがたい。

いったん、試してみます

$ bundle update slim

これでダメなら、
https://github.com/rails/rails/issues/35505
の方法を試していきたいと思います。

$ rails s
DEPRECATION WARNING: Single arity template handlers are deprecated. Template handlers must
now accept two parameters, the view object and the source for the view object.
Change:
  >> #<#<Class:0x00007f8216263780>:0x00007f8211d3abe0>.call(template)
To:
  >> #<#<Class:0x00007f8216263780>:0x00007f8211d3abe0>.call(template, source)
 (called from <top (required)> at /Users/owner/projects/oss/open-source-billing/config/application.rb:8)
=> Booting Puma
=> Rails 6.0.2.2 application starting in development 
=> Run `rails server --help` for more startup options
Exiting

ダメですね

Gemfile
gem 'slim', '3.0.7'

これを削除してみます。

$ rails s
DEPRECATION WARNING: Single arity template handlers are deprecated. Template handlers must
now accept two parameters, the view object and the source for the view object.
Change:
  >> #<#<Class:0x00007fe53a1117b0>:0x00007fe53a132ff0>.call(template)
To:
  >> #<#<Class:0x00007fe53a1117b0>:0x00007fe53a132ff0>.call(template, source)
 (called from <top (required)> at /Users/owner/projects/oss/open-source-billing/config/application.rb:8)

ダメですね

じゃあ、この記事を参考にしていきます。

Gemfile
# gem 'jbuilder', '~> 2.0'
gem 'jbuilder', github: 'rails/jbuilder', branch: 'master'

これでやってみましょう
bundle updateするように指示があるので、先にしておきます。

$ rails s
$ rails s
=> Booting Puma
=> Rails 6.0.2.2 application starting in development 
=> Run `rails server --help` for more startup options
Exiting
Traceback (most recent call last):
    50: from bin/rails:4:in `<main>'
    49: from bin/rails:4:in `require'

先ほどのエラーはなくなりましたが、それでもまだ読み込めない様子です。

エラー
`database_configuration': Cannot load database configuration: (RuntimeError)
Could not load database configuration. No such file - ["config/database.yml"]

どうもconfigフォルダにdatabase.ymlが入っていないようです。

database.ymlを追加すれば改善するでしょう。
その前に

先ほど消したslimを戻して検証しておきましょう

Gemfile
gem: 'slim'

これで起動っと

$ rails s
=> Booting Puma
=> Rails 6.0.2.2 application starting in development 
=> Run `rails server --help` for more startup options
Exiting
Traceback (most recent call last):

うんうん、先ほどの

Change:
  >> #<#<Class:0x00007fe53a1117b0>:0x00007fe53a132ff0>.call(template)

がないことから、slimは関係なさそうです。
どうも,rails 6のjbuilderのバグのようですね

では続けてdatabase.ymlを作成していきます。

config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: 
  socket: /tmp/mysql.sock
  host: localhost

development:
  <<: *default
  database: open-source-billing_development

test:
  <<: *default
  database:  open-source-billing_test

これで、ひとまずrails sしてみます。

/Users/owner/.rbenv/versions/2.7.1/lib/ruby/2.7.0/psych.rb:577:in `initialize': No such file or directory @ rb_sysopen - /Users/owner/projects/oss/open-source-billing/config/config.yml (Errno::ENOENT)


ひとまずNo such file or directory @ rb_sysopenでググると記事が出てきました

何か記述が足りないようですね
今回の場合config/config.ymlがないため、発生しているようです。
ただ、config/config.copy.ymlというファイルが用意されていたので、copyの記述を消して、cofig.ymlとしました。

$ rails db:create
Created database 'open-source-billing_development'
Created database 'open-source-billing_test'

$rails db:migrate
ズガガガガガガガ.....
$rails s

Image from Gyazo

でたああああああああああああああああああああああああああ
ようやくですよおお

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

2020年7月 gem Omniauthでgoogleログイン 認証

概要

Devise + omniauth + omniauth-google-oauth2
でgoogle ログインを実装する
色々な記事があったのですが、とりあえず忘れないように、備忘録としてのしておきます

*注意*

*新規登録をしたあと2回目行こうを入力をせずにグーグルのボタンだけでログインできる機能であり、新規登録がGooleでできる訳ではないのであしからず。*
その方法は、また別の時に解説します。

1. まずはGoogle Developers Consoleで登録

1-1. 下準備

こちらを参照してまずは、
クライアントID、クライアントシークレットを発行してください。

Google Maps API を使ってみた

1.2 Gemfile追加

クライアントID、クライアントシークレットが発行されたら 
Gemfileに追加します

Gemfile
#省略
gem 'devise'
gem 'omniauth'
gem 'omniauth-google-oauth2'
...
terminal
$ bundle install

Deviseの設定

terminal
$ rails g devise:install

ユーザ認証用のテーブル作成

termina
$ rails g devise user
2020******_add_column_to_users.rb
class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
    add_column  :users,  :provider,  :string
    add_column  :users,  :uid,       :string
    add_column  :users,  :token,       :string
    add_column  :users,  :meta,       :string
  end
end

$ rake db:migrate

Model修正

app/models/user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
          :recoverable, :rememberable, :validatable, :confirmable,
          :omniauthable, omniauth_providers: %i(google)
...
...
...

  def self.find_for_google_oauth2(auth)
    user = User.where(email: auth.info.email).first

    unless user
      user = User.create(name:     auth.info.name,
                         provider: auth.provider,
                         uid:      auth.uid,
                         email:    auth.info.email,
                         token:    auth.credentials.token,
                         password: Devise.friendly_token[0, 20],
                         meta:     auth.to_yaml)
    end
    user
  end

end

:trackable, :omniauthableだけでOKです。deviseに新たに機能を持たせたいときは、そのとき新たに追記する方がスマートだと思います。今回は、とりあえずログインすることが目的なので、これでよい!

また、def self.find_for_google(auth)は、コールバックを受けた時にユーザが既にアプリケーションの中で認知されているかどうかを判断するメソッドです。後で使います。

config修正

ここが他のサイトに乗っているのとは違うかったとこ!!!

config/initializers/devise.rb
Devise.setup do |config|
    require 'devise/orm/active_record'
    config.omniauth :google_oauth2,
                    GOOGLE_CLIENT_ID="***sdps.apps.googleusercontent.com",
                    GOOGLE_CLIENT_SECRET="***********",
                    name: :google,
                    scope: %w(email) 
  end

GOOGLE_CLIENT_IDのとこがENV=['...']
となっているとこが多い。。
It's Simple!!
scopeについて、デフォルト(ここに記述しない状態)だとemailとprofileになります。ユーザ認証のための必須ではないため、emailだけにしちゃいましょう

ログインボタンを設置するページ作る

app/controllers/views/home.html.erb
= link_to image_tag('#.png'), omniauth_authorize_path(resource_name, provider)

omniauth_callbacks_controller.rbを作成

app/controllers/usersディレクトリを作成して、omniauth_callbacks_controller.rbというコントローラーを作成します。

omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def google
    @user = User.find_for_google_oauth2(request.env['omniauth.auth'])

    if @user.persisted?
      flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Google'
      sign_in_and_redirect @user, event: :authentication
    else
      session['devise.google_data'] = request.env['omniauth.auth']
      redirect_to new_user_registration_url
    end
  end
end

サーバ起動

terminal
$ rails s

で、サーバを起動し、
http://localhost:3000 にアクセスしてするとgoogle loginを押すと...

routes.rbでログイン後に遷移する先を記述していないのでrootに行ってますね。ログイン後、viewなどでcurrent_user.emailなどを表示させてみれば、ログインしているユーザのemailアドレスが表示されるかと思います。!

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

resourcesとresourceを組み合わせて使う時の注意点についてまとめてみた

先日、resourcesとresourceの違いについてまとめてみましたが、組み合わせて使う際の注意点もあったのでまとめてみました。
違いについてはこちら → resourcesとresourceの違い - Qiita

resourcesとresourceを組み合わせて使う場合

resourcesとresourceを組み合わせて使うと、下記のようなルーティングが簡単に生成できます。

  • 全ユーザーの一覧表示
  • 全ユーザーの詳細表示
  • 自ユーザーの詳細表示
  • 自ユーザー情報の編集

全ユーザー一覧、各ユーザーの詳細については、誰でも表示できるが、ユーザー情報の編集は自分のものしかできないという状態。

config/routes.rb
  resources :users, only: [:index, :show]
  resource :user, only: [:show, :edit, :update]

rails routesで生成されたルートを確認すると、下記のような感じ。

ターミナル
   Prefix Verb  URI Pattern          Controller#Action
    users GET   /users(.:format)     users#index
     user GET   /users/:id(.:format) users#show
edit_user GET   /user/edit(.:format) users#edit
          GET   /user(.:format)      users#show
          PATCH /user(.:format)      users#update
          PUT   /user(.:format)      users#update

user GET /users/:id(.:format) users#showの部分、user_pathが/users/:idに割り当てられてしまうことで、/userを返すべきヘルパーメソッドが生成されない。
ということで、順番を逆にして記載してみた。

config/routes.rb
  resource :user, only: [:show, :edit, :update]
  resources :users, only: [:index, :show]

rails routesで生成されたルートを確認すると、下記のような感じ。

ターミナル
   Prefix Verb  URI Pattern          Controller#Action
edit_user GET   /user/edit(.:format) users#edit
     user GET   /user(.:format)      users#show
          PATCH /user(.:format)      users#update
          PUT   /user(.:format)      users#update
    users GET   /users(.:format)     users#index
          GET   /users/:id(.:format) users#show

自ユーザーは、ログイン機能(session管理)で特定できれば、リクエストに:idを含む必要はないので、自ユーザーに関するルーティングはresourceを使用しています。

自分以外のユーザーの詳細画面を見るには、対象となるユーザーのIDを指定する必要があるので、resourcesでリクエストに:idを含むルートを生成しています。

結論

単数形で使用するresourceと、複数形で使用するresourcesを組み合わせてルーティングを作る際は、単数形のresourceを上に書くようにする。

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

Rails 本番環境で画像が読み込まれないエラー

この記事について

本番環境でbackground-imageの画像を読み込む時にはエラーが出ないのに、image_tagのところだけでエラーが出てしまっていたので、そのエラー解決方法について

環境

・Ruby 2.6.6, Rails 6.0.3.2
・Docker,Docker-compose(開発環境)
・AWS/本番環境(EC2, RDS, VPC, EIP, Route53, IAM, S3)

参考URL

https://stackoverflow.com/questions/49440304/rails-asset-is-not-present-in-asset-pipeline-when-using-image-tag
この人と全く同じ現象になってました。

出ていたエラー

qiita.rb
ActionView::Template::Error (The asset "chat_example.jpeg" is not present in the asset pipeline.):

asset へのパイプラインがうまくいっていない様子

解決方法

config/environments/production.rbにある、config.assets.compile = falseをtrueに変えてあげる。

config/environments/production.rb
- config.assets.compile = false
+ config.assets.compile = true
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Controller作成と同時にアクションとviewファイルを作成(rails)

Controller作成と同時にアクションとviewファイルを作成

railsではcontrollerを作成する際、同時にアクションとviewファイルを作成することができます。
実際に手動でアクションやviewファイルを作成する手間を省くことができます。
以下がコマンドの型です。

$ rails g controller コントローラ名 アクション名

例えば、book controllerを作成し、newアクションを追加したい場合、、、

$ rails g controller book new

こんな感じになれば、成功。

[vagrant@localhost sample_app]$ rails g controller books new
Running via Spring preloader in process 25819
      create  app/controllers/books_controller.rb
       route  get 'books/new'
      invoke  erb
      create    app/views/books
      create    app/views/books/new.html.erb
      invoke  test_unit
      create    test/controllers/books_controller_test.rb
      invoke  helper
      create    app/helpers/books_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/books.coffee
      invoke    scss
      create      app/assets/stylesheets/books.scss
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

カラムの追加と削除

カラムとは?

カラムとはデータベースの中のテーブルが持つ要素です。
例えば、ユーザーというテーブルの中の「名前、生年月日、住所」などの項目をカラムと言います。

カラムの追加

新たに別のカラムを追加したいということはよくあると思います。
そんなときは以下のコマンドでカラムを追加です。

$ rails g migration Addカラム名Toテーブル名 カラム名:型名

例えば、「User」というテーブルに「name」というカラムを追加したい場合、

$ rails g migration AddNameToUsers name:string
$ rails db:migrate

ここで「rails db:migrate」を忘れてしまうと、テーブルへ反映されませんので、
気をつけてください。

カラムの削除

カラム名を間違えて登録した時など、カラムを削除したいこともあると思います。
カラムを追加する時とあまり変わりません。

$ rails g migration Removeカラム名Fromテーブル名 カラム名:型名

「User」というテーブルの「name」というカラムを削除したい場合、

$ rails g migration RemoveNameFromUsers name:string
$ rails db:migrate

ここでも「rails db:migrate」は忘れずに。

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

【Rails】エラー解決 Unsupported argument type: 1 (Integer)

はじめに

今回は
Unsupported argument type: 1 (Integer)
こんなこと言われた時の対処方を記述します
お決まりのタイプミスによって発見したエラー文です笑

解決策

intger型の1という引数は期待してません、という感じのエラー文です。

という事は違う物を期待してるところで整数の1を渡してしまっているという事です。

User.find_by(session[:user_id])

犯人はこれでした!

findと書くべきところを間違えてfind_byと書いてますね、なのでfind_byのカラム名を書くところにsession[:user_id]が入っているせいで、今回は[1]という整数が入ってるのでそのまんま[1]って名前のカラムを探しに行こうとしてしまった、そんな感じみたいですね。

↓こんな感じの事ですね!

User.find_by(1)

という事で

User.find(session[:user_id])

findに書き換えて解決!

学び

  • findfind_byと間違えると高確率でUnsupported argument type: ... (Integer)が出ると思うのでこんな感じのエラーを見かけたらfind周りチェックするのがいいかもですね!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

railsでmodelを作成する方法

railsでmodelを作成する方法

modelはデータベースとのやりとりを行ってくれます。
modelを作成するコマンドはこんな感じです。

$ rails g model モデル名

モデル名の命名規則は、「User」のように、英数字の単数形で指定します。
また、先頭は必ず英大文字で記述します。

実際に、modelを作成するためのコマンドを打つとこんな感じです。

$ rails g model User

成功すると、、、

$ rails g model User
Running via Spring preloader in process 4271
      invoke  active_record
      create    db/migrate/2020072951856_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml

作成されるファイルは以下の4つです。

db/migrate/(作成日時)create_lists.rb:「マイグレーションファイル」というデータベースの設計図になるファイルです。
app/models/list.rb:モデルクラスはデータベースに対応したRubyのクラスです。
test/models/list
test.rb:モデルクラスのテストコードのひな形です。
test/fixtures/lists.yml:テストデータ作成のためのひな形です。

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

railsでルーティングを設定する方法

railsでルーティングを設定するには

routing(ルーティング)では、ユーザが特定のURLにアクセスした時に、
どのコントローラのどのアクションに処理を振り分けるかを定義します。
ルーティングは、URLとアクションを結びつける役目をしています。
例えば、「あるURLにアクセスがあった時に、homeコントローラのtopアクションの処理を振り分ける」という定義を、ルーティングに記述します。

ルーティングの設定は、configフォルダ内のroutes.rbファイルに記述します。
routes.rbファイルは、Railsアプリを作成するときに自動作成されるファイルです。
こんな感じです。

HTTPメソッド 'URL' => 'コントローラ#アクション'

※HTTPメソッドについてはこちらの記事で説明しています。
https://qiita.com/yusuke1209kitamura/items/e29787bc2920a656d505

わかりやすく、実際に書いてみます。

Rails.application.routes.draw do
  get 'top' => 'homes#top'
end

この例の場合、URL「top」にアクセスすると、
homesコントローラのtopアクションが呼び出されるように設定しています。

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