20200317のRubyに関する記事は28件です。

アプリ作成 アウトプット

ツイート機能実装アプリ開発

本日
1スケジュール作成していく中で何が実装に必要なのか、整理することが出来た。
2新規アプリの立ち上げrails new など 必要な作業が、何も見ずに作成していくのは難しい。

本日はここまで、データバースの設計等調べながら進めていく。

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

if文の条件式を使いこなしたらかっこいいよね

問題

こんなドリル問題がありました。
20時から翌朝7時までにオウムに喋られると問題があるのでその場合は「NG」、
それ以外は「OK」と出力するメソッドを作成します。
オウムが喋る時をture、喋らない時をfalseと入力することにし、時刻も同時に入力します。

呼び出し方:
parrot_trouble(talking, hour)

出力例:
parrot_trouble(true, 6) → NG
parrot_trouble(true, 7) → OK
parrot_trouble(false, 6) → OK
parrot_trouble(false, 7) → OK

どうやって条件式を書くか

この問題は2つの条件を満たした場合のみOKと出力する条件式を記述する必要があります。
それはtalkingが"true"かつ時間が7時〜19時の場合のみです。
それ以外はtalkingが"true"でattatositemo出力は"NG"です。
実際に条件式を記述してみましょう

条件式

def parot_trouble(talking, hour)
  if (talking == true) && (7..19).cover?(hour)
    puts "OK"
  else
    puts "NG"
  end
end

※ご指摘をいただきまして2行目を一部修正を行いました。
1行目でメソッドを定義して引数talkingとhourを受け取ります
2行目ではtalkingがtrueかつhourが7~19の中の数字である場合を定義し
3行目でOKを出力します。
4行目のelseにてそれ以外の場合を指定し
5行目でNGを出力
この条件式により出題の要件を満たすことができます。

if文を制するものはプログラムを制する?

条件式はrailsではコントローラにてエラーハンドリングを行うのに使用されたり、プログラム中に出力を条件によって変えたりとあらゆる場面で使用します。
この条件式の扱いの理解を深めれば深めるほど複雑なロジックを組むことができたり、それを簡単に実装できたりとプログラマとしてのスキルが上がっていくと感じます。
無駄のなく、チーム開発でも他人が理解しやすいコードがかけるようにどんどん練習していきたいですね

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

【ruby】Docker開発環境へのGoogle Cloud Translation API (v2)導入手順

開発環境

ruby '2.6.3'
rails '6.0.2'

Google Cloud Translation APIとは

  • ウェブサイトやアプリを 100 以上の言語に瞬時に翻訳したい場合などに役立つのが Translation API です。
  • Translation API の料金

  • Translation API の料金

  • Google Cloud の無料枠
    私の場合は12 か月間の無料トライアル(Google Cloud サービスで使用できる $300 相当のクレジット付き)。なので無料です。

導入手順

Cloud Translate API の有効化

サービスアカウントキーの作成

サービスカウント: 「新しいサービスアカウント」を選択
サービスアカウント名: (任意)
役割: オーナー (Project > オーナー)
サービスアカウントID: (任意)
キーのタイプ: JSON

「作成」ボタンを押下すると、jsonファイルがダウンロードされます

サービスアカウントキーの適用,環境変数の設定

  • GOOGLE_APPLICATION_CREDENTIALSという名前の環境変数を作成し、先ほどダウンロードしたjsonファイルのパスを設定します。
ターミナル
vim .zshrc
.zshrc
export GOOGLE_APPLICATION_CREDENTIALS="ダウンロードしたファイルパス"
  • .zshrcの更新。
ターミナル
source ~/.zshrc

これでいつでもローカル環境では参照できるようになります。

保存されているか確認

ターミナル
printenv | grep GOOGLE
=> export GOOGLE_APPLICATION_CREDENTIALS="ダウンロードしたファイルパス"

docker上でGOOGLE_APPLICATION_CREDENTIALSを適応

  1. 開発中のディレクトリにjsonファイルをコピーする。(ファイル名は変更しても問題ありません、今回はkey.jsonという名前で行います。)
  2. .gitignoreに追記する
.gitignore
/key.json
  • DockerfileでDocker内にコピーする
Dockerfile
COPY key.json key.json
ENV GOOGLE_APPLICATION_CREDENTIALS key.json
  • docker-compose build # rails編
  1. gem導入
    gem 'google-cloud-translate'

  2. 私の場合は外部DBから取ってきた英文を日本語にして保存する感じなので下記を変えればいい感じですが。実際にviewから翻訳したい場合はリンクを参照してください。

seeds.rb
# 最初に作ったプロジェクトのIDです。そのまま書くのはあまりよろしくないです。
project_id    = "Your Google Cloud project ID"
# 実際に訳す文です
text          = "The text you would like to translate"
# 何に訳すかを指定します `"The ISO 639-1 code of language to translate to, eg. 'en'"`
language_code = "en"

require "google/cloud/translate"

translate   = Google::Cloud::Translate.new version: :v2, project_id: project_id
translation = translate.translate text, to: language_code

puts "Translated '#{text}' to '#{translation.text.inspect}'"
puts "Original language: #{translation.from} translated to: #{translation.to}"
私の場合
require "google/cloud/translate"

def translate(synopsis:)
  project_id    = Rails.application.credentials.api[:id]
  text          = synopsis
  language_code = 'ja'

  translate   = Google::Cloud::Translate.new version: :v2, project_id: project_id
  translation = translate.translate text, to: language_code

  return translation.text.inspect
end

最後に

今回は(v2)のGoogle Translation APIということをお忘れなく。
おしまい

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

Ruby on RailsでWebAPIの作成

Ruby on RailsでWebAPIの作成

はじめに

この記事では、Ruby on RailsにおけるAPIの作り方を簡単に紹介します。
データベースへのユーザ登録、参照、消去、更新ができるAPIを作成し、いじりながら解説します。

前提知識

  • API
  • JSON
  • HTTPリクエスト、レスポンス
  • GET, POST, DELETE, etc

環境

  • ruby 2.6.5
  • Rails 6.0.2

作り方

なにはともあれAPIの基盤の作成。

[tmp]$ rails new RailsApi --api

ご存知rails new [アプリ名]とすることでアプリの基盤を作成することができるが、 --apiのオプションをつけることでAPIに必要なものだけに絞って作ってくれる。

[tmp]$ cd RailsApi

RailsApiフォルダに移動。

[RailsApi]$ rails g scaffold user user_id:string password:string

rails g (generate) scaffold [モデル名(単数形)] カラム名:データ型 (カラム名:データ型)
今回はユーザテーブルにIDとパスワードを持たせようと思うのでこの様に指定しました。IDのカラム名をidとしない様に注意。(自動生成されるカラム名のidと被るため)

[RailsApi]$ rails db:create
[RailsApi]$ rails db:migrate

データベースの作成とテーブルの作成を行います。

そしてなんと、、、

これでAPIの完成です。(マジ)詳しくはあとで解説するとしてこのAPIを試してみましょう。

作成したAPIを試す

まず、APIをいじるならhttpリクエスト送信とレスポンス受信ができるツールが必要なので、chromeの拡張機能であるAdvanced REST clientをダウンロードしておきましょう。

全件取得

[AppName]$ rails s

上記コマンドでローカルサーバを起動し、
http://localhost:3000/users/GETリクエストを送ってみましょう。これは「データの全件取得」を意味します。
rails g scaffold user ~でuserのモデルを作成したためその複数形をパスに指定。)

すると以下の様な空のレスポンスが返ってきます。これはまだデータ投入していないからです。
スクリーンショット 2020-03-17 21.54.25.png

データ投入

ではデータ投入しましょう。
~/users/POSTリクエストを送ります。これは「bodyのjsonを元にデータを作成する」ことを意味します。その際に、リクエストのBodyを以下の様に指定しましょう。
Body content type : application/json
Body : {"user_id":"hoge","password":"fuga"}
スクリーンショット 2020-03-17 22.11.54.png

すると以下の様なレスポンスが返ってきてユーザが作られたことが分かります。

スクリーンショット 2020-03-17 22.15.45.png

ついでにもう1つデータ投入しておきましょう。
スクリーンショット 2020-03-17 22.19.19.png

この状態で~/users/へGETリクエストを送ると、、、
スクリーンショット 2020-03-17 22.23.38.png

先ほど入れた2件のデータが両方取れます。

1件取得

次は、~/users/2GETリクエストを送ってみましょう。これは「idが2である人のデータを取得する」ことを意味しており、以下の様なレスポンスが返ってきます。
スクリーンショット 2020-03-17 22.26.31.png

削除

次は、~/users/2DELETEリクエストを送ってみましょう。これは「idが2である人のデータを削除する」ことを意味しており、以下の様なレスポンスが返ってきます。
スクリーンショット 2020-03-17 22.39.56.png

この状態で~/users/へGETリクエストを送ると、、、
スクリーンショット 2020-03-17 22.40.49.png

idが2のデータがなくなっていることがわかります。

更新

最後に、~/users/1PATCHリクエスト(PUTでも可)を送ってみましょう。これは「bodyのjsonを元にidが1であるデータを更新する」ことを意味します。その際に、リクエストのBodyを以下の様に指定しましょう。
スクリーンショット 2020-03-17 22.49.11.png

すると以下の様なレスポンスが返ってきます。
スクリーンショット 2020-03-17 22.49.34.png

idが1のデータのuser_idがhogehogeに変更されているのがわかると思います。

メソッドとパスその効果をまとめると以下の様になります。

メソッド パス 効果
GET /users/ 全件取得
POST /users/ bodyのjsonでデータ投入
GET /users/:id/ 該当idのデータを取得
PATCH /users/:id/ 該当idのデータをbodyのjsonで更新
PUT /users/:id/ 該当idのデータをbodyのjson更新
DELETE /users/:id/ 該当idのデータを削除

さいごに

  • なぜrails g scaffold ~するだけでこの様なAPIが作成できるのか
  • ソースコードの中身
  • 自分好みの仕様に作り替えるには

は別の記事で解説したいと思います。

ご質問などあれば気軽にどうぞ。
@ruemura3

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

【5分で出来る】Ruby on RailsでWeb APIの作成

1. はじめに

この記事では、Ruby on RailsにおけるAPIの作り方を簡単に紹介します。
Rails が非常に優秀なので作成は5分もあればできるでしょう。(Rails を使う環境が整っている前提)
データベースへのユーザ登録、参照、消去、更新ができるAPIを作成し、いじりながら解説します。

前提知識

  • API
  • JSON
  • HTTPリクエスト、レスポンス
  • GET, POST, DELETE, etc

環境

  • ruby 2.6.5
  • Rails 6.0.2
  • macOS Catalina 10.15.3

2. 作り方

なにはともあれAPIの基盤の作成。

[tmp]$ rails new RailsApi --api

ご存知rails new [アプリ名]とすることでアプリの基盤を作成することができるが、 --apiのオプションをつけることでAPIに必要なものだけに絞って作ってくれる。

[tmp]$ cd RailsApi

RailsApiフォルダに移動。

[RailsApi]$ rails g scaffold user user_id:string password:string

rails g( or generate) scaffold [モデル名(単数形)] カラム名:データ型 (カラム名:データ型...)
今回はユーザテーブルにIDとパスワードを持たせようと思うのでこの様に指定しました。IDのカラム名をidとしない様に注意。(自動生成されるカラム名のidと被るため)

[RailsApi]$ rails db:create
[RailsApi]$ rails db:migrate

データベースの作成とテーブルの作成を行います。

そしてなんと、、、

これでAPIの完成です。(マジ)詳しくはあとで解説するとしてこのAPIを試してみましょう。

3. 作成したAPIを試す

まず、APIをいじるならhttpリクエスト送信とレスポンス受信ができるツールが必要なので、chromeの拡張機能であるAdvanced REST clientをダウンロードしておきましょう。

全件取得

[AppName]$ rails s

上記コマンドでローカルサーバを起動し、
http://localhost:3000/users/GETリクエストを送ってみましょう。これは「データの全件取得」を意味します。
rails g scaffold user ~でuserのモデルを作成したためその複数形をパスに指定。)

すると以下の様な空のレスポンスが返ってきます。これはまだデータ投入していないからです。
スクリーンショット 2020-03-17 21.54.25.png

データ投入

ではデータ投入しましょう。
~/users/POSTリクエストを送ります。これは「bodyのjsonを元にデータを作成する」ことを意味します。その際に、リクエストのBodyを以下の様に指定しましょう。
Body content type : application/json
Body : {"user_id":"hoge","password":"fuga"}
スクリーンショット 2020-03-17 22.11.54.png

すると以下の様なレスポンスが返ってきてユーザが作られたことが分かります。

スクリーンショット 2020-03-17 22.15.45.png

ついでにもう1つデータ投入しておきましょう。
スクリーンショット 2020-03-17 22.19.19.png

この状態で~/users/へGETリクエストを送ると、、、
スクリーンショット 2020-03-17 22.23.38.png

先ほど入れた2件のデータが両方取れます。

1件取得

次は、~/users/2GETリクエストを送ってみましょう。これは「idが2である人のデータを取得する」ことを意味しており、以下の様なレスポンスが返ってきます。
スクリーンショット 2020-03-17 22.26.31.png

削除

次は、~/users/2DELETEリクエストを送ってみましょう。これは「idが2である人のデータを削除する」ことを意味しており、以下の様なレスポンスが返ってきます。
スクリーンショット 2020-03-17 22.39.56.png

この状態で~/users/へGETリクエストを送ると、、、
スクリーンショット 2020-03-17 22.40.49.png

idが2のデータがなくなっていることがわかります。

更新

最後に、~/users/1PATCHリクエスト(PUTでも可)を送ってみましょう。これは「bodyのjsonを元にidが1であるデータを更新する」ことを意味します。その際に、リクエストのBodyを以下の様に指定しましょう。
スクリーンショット 2020-03-17 22.49.11.png

すると以下の様なレスポンスが返ってきます。
スクリーンショット 2020-03-17 22.49.34.png

idが1のデータのuser_idがhogehogeに変更されているのがわかると思います。

メソッドとパスその効果をまとめると以下の様になります。

メソッド パス 効果
GET /users/ 全件取得
POST /users/ bodyのjsonでデータ投入
GET /users/:id/ 該当idのデータを取得
PATCH /users/:id/ 該当idのデータをbodyのjsonで更新
PUT /users/:id/ 該当idのデータをbodyのjson更新
DELETE /users/:id/ 該当idのデータを削除

4. さいごに

理解するには自分でやってみるのが一番なので自分で作ってみてください。ユーザのAPIができたら投稿記事のAPIなんかも作ってみるといいと思います。

  • なぜrails g scaffold ~するだけでこの様なAPIが作成できるのか
  • ソースコードの中身
  • 自分好みのAPIに作り替えるには

は別の記事で解説したいと思います。

ご質問などあれば気軽にどうぞ。
@ruemura3

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

【5分で出来る】Ruby on RailsでWebAPIの作成

1. はじめに

この記事では、Ruby on RailsにおけるAPIの作り方を簡単に紹介します。
Rails が非常に優秀なので作成は5分もあればできるでしょう。(Rails を使う環境が整っている前提)
データベースへのユーザ登録、参照、消去、更新ができるAPIを作成し、いじりながら解説します。

前提知識

  • API
  • JSON
  • HTTPリクエスト、レスポンス
  • GET, POST, DELETE, etc

環境

  • ruby 2.6.5
  • Rails 6.0.2

2. 作り方

なにはともあれAPIの基盤の作成。

[tmp]$ rails new RailsApi --api

ご存知rails new [アプリ名]とすることでアプリの基盤を作成することができるが、 --apiのオプションをつけることでAPIに必要なものだけに絞って作ってくれる。

[tmp]$ cd RailsApi

RailsApiフォルダに移動。

[RailsApi]$ rails g scaffold user user_id:string password:string

rails g( or generate) scaffold [モデル名(単数形)] カラム名:データ型 (カラム名:データ型)
今回はユーザテーブルにIDとパスワードを持たせようと思うのでこの様に指定しました。IDのカラム名をidとしない様に注意。(自動生成されるカラム名のidと被るため)

[RailsApi]$ rails db:create
[RailsApi]$ rails db:migrate

データベースの作成とテーブルの作成を行います。

そしてなんと、、、

これでAPIの完成です。(マジ)詳しくはあとで解説するとしてこのAPIを試してみましょう。

3. 作成したAPIを試す

まず、APIをいじるならhttpリクエスト送信とレスポンス受信ができるツールが必要なので、chromeの拡張機能であるAdvanced REST clientをダウンロードしておきましょう。

全件取得

[AppName]$ rails s

上記コマンドでローカルサーバを起動し、
http://localhost:3000/users/GETリクエストを送ってみましょう。これは「データの全件取得」を意味します。
rails g scaffold user ~でuserのモデルを作成したためその複数形をパスに指定。)

すると以下の様な空のレスポンスが返ってきます。これはまだデータ投入していないからです。
スクリーンショット 2020-03-17 21.54.25.png

データ投入

ではデータ投入しましょう。
~/users/POSTリクエストを送ります。これは「bodyのjsonを元にデータを作成する」ことを意味します。その際に、リクエストのBodyを以下の様に指定しましょう。
Body content type : application/json
Body : {"user_id":"hoge","password":"fuga"}
スクリーンショット 2020-03-17 22.11.54.png

すると以下の様なレスポンスが返ってきてユーザが作られたことが分かります。

スクリーンショット 2020-03-17 22.15.45.png

ついでにもう1つデータ投入しておきましょう。
スクリーンショット 2020-03-17 22.19.19.png

この状態で~/users/へGETリクエストを送ると、、、
スクリーンショット 2020-03-17 22.23.38.png

先ほど入れた2件のデータが両方取れます。

1件取得

次は、~/users/2GETリクエストを送ってみましょう。これは「idが2である人のデータを取得する」ことを意味しており、以下の様なレスポンスが返ってきます。
スクリーンショット 2020-03-17 22.26.31.png

削除

次は、~/users/2DELETEリクエストを送ってみましょう。これは「idが2である人のデータを削除する」ことを意味しており、以下の様なレスポンスが返ってきます。
スクリーンショット 2020-03-17 22.39.56.png

この状態で~/users/へGETリクエストを送ると、、、
スクリーンショット 2020-03-17 22.40.49.png

idが2のデータがなくなっていることがわかります。

更新

最後に、~/users/1PATCHリクエスト(PUTでも可)を送ってみましょう。これは「bodyのjsonを元にidが1であるデータを更新する」ことを意味します。その際に、リクエストのBodyを以下の様に指定しましょう。
スクリーンショット 2020-03-17 22.49.11.png

すると以下の様なレスポンスが返ってきます。
スクリーンショット 2020-03-17 22.49.34.png

idが1のデータのuser_idがhogehogeに変更されているのがわかると思います。

メソッドとパスその効果をまとめると以下の様になります。

メソッド パス 効果
GET /users/ 全件取得
POST /users/ bodyのjsonでデータ投入
GET /users/:id/ 該当idのデータを取得
PATCH /users/:id/ 該当idのデータをbodyのjsonで更新
PUT /users/:id/ 該当idのデータをbodyのjson更新
DELETE /users/:id/ 該当idのデータを削除

4. さいごに

理解するには自分でやってみるのが一番なので自分で作ってみてください。ユーザのAPIができたら投稿記事のAPIなんかも作ってみるといいと思います。

  • なぜrails g scaffold ~するだけでこの様なAPIが作成できるのか
  • ソースコードの中身
  • 自分好みのAPIに作り替えるには

は別の記事で解説したいと思います。

ご質問などあれば気軽にどうぞ。
@ruemura3

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

【今日の疑問】MVCモデル

こんにちは、今日はTwitterもどきのアプリを作ってたのですがひとまずMVCモデルが理解できてないなと感じたので備忘録代わりに簡単にまとめます。

MVCモデルとは

RailsなどのフレームワークでCRUDを使ったWebアプリを作る上で一番肝になる考え。

ユーザーからHTTPリクエストを受け取り、それに応じたリクエストからコントローラーがビューに表示したいアクションを選択して、モデルがその表示したい情報をDBから引っ張ってきてビューを通してレスポンスする...

流れとしてはこれですがそれぞれの用語についてまとめます笑

ルーティング

HTTPリクエストを受け取って、それを実行するためのコントローラーとアクションを設定しておくことでどういう風にビューに表示することができるか流れを作ることができる。

モデル

DBから表示させたいデータをSQLなどを使うことなくrailsだけで実行することができる。これに合わせて知っておきたいことはマイグレーション。

ビュー

HTTPのレスポンスを返すときにユーザーに表示したいページを構築する部分。

コントローラー

モデルとビューの橋渡し的な役割。モデルにデータをリクエストしたりビューにそれを渡したりもする。

参考文献

MVCモデルとは

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

Railsのバージョンを5から6にしたらBlocked Hostというエラーが出てきてびっくりした話

開発中のサービスのRailsのバージョンを5から6に上げたのですが、Blocked hostというエラーが出るようになりこれまで使えていたユーザーの招待機能が使えなくなる事象に遭遇しました。

Rails 6から導入された新しいセキュリティー対策のようです。
解決策としてエラー画面に表示されている通りconfigファイルに許可するホストを追加しました。

development.rb or production.rb
config.hosts << "app.survelion.com"

バージョンアップの際は気をつけましょう。

参照記事: https://www.tmp1024.com/articles/solve-blocked-host-of-rails

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

Dockerを使った既存のRailsアプリの環境構築に苦労したので、メモを残してみた

1.はじめに

 2020年3月からDockerの勉強を始め、基礎を終えた後、Railsの環境構築に挑戦してみようと思ったが、思いの外、上手くいかなかったので、ここにメモを残すことにしました。誰かの参考になれば幸いです。

2.教材

入門 Docker
・Docker/Kubernetes 実践コンテナ開発入門(書籍)
・Docker Hubの公式イメージ

3.開発環境

Play with Docker
(事前にDockerHubのアカウントが必要です。)
・Ruby:2.5.3
・Ruby on rails:5.2.2
・MySQL

4.手順

4-1 クローンを取得

まずは、GitHubからgit cloneでアプリをクローンしておいてください。

git clone 'クローンしたいアプリのURL(GitHub参照)'

これで、作成済みのアプリをローカルディレクトリに取り込むことができました。

4-2 Dockerfileとdocker-compose.ymlの作成

Dockerfileとdocker-compose.ymlを以下の配置になるように作成してください。
(作成済みのアプリをSampleAppと名付けています。)

SampleApp---|--app
            |--bin
            |--config
            |--db
            |--lib
            |--log
            |--public
            |--storage
            |--tmp
            |--vendor
            |--.gitignore
            |--.ruby-version
            |--Dockerfile   (これを追加)
            |--Gemfile
            |--Gemfile.lock
            |--README.md
            |--Rakefile
            |--config.ru
            |--docker-compose.yml  (これを追加)
            |--package.json

また、Dockerfileとdocker-compose.ymlの中身は以下のようになります。

Dockerfile
FROM ruby:2.5.3

RUN apt-get update -qq && apt-get install -y build-essential libpq-dev node.js 

RUN mkdir /myapp
WORKDIR /myapp 

COPY Gemfile /myapp/Gemfile 
COPY Gemfile.lock /myapp/Gemfile.lock 

RUN bundle install

COPY . /myapp
docker-compose.yml
version: '3'

services: 
  db: 
    image: mysql 
    environment: 
      MYSQL_ROOT_PASSWORD: password 
      MYSQL_DATABASE: root
    command: --default-authentication-plugin=mysql_native_password 

  web: 
    build: . 
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes: 
      - .:/myapp 
    ports:
      - "3000:3000" 
    depends_on: 
       - db 

これで、実行する準備は完了です。

4-3 実行

アプリのディレクトリ内で以下のコマンドを実行してください。

$ docker-compose build

$ docker-compose up -d

$ docker-compose run web rake db:create

$ docker-compose run web rake db:migrate

完了です。

5. 最後に

何か間違えているところがあれば、ご指摘ください。

6. 参考記事

既存のRailsアプリにDockerを導入する手順
railsの環境構築 その1
プログラム好き大学生のDocker+Ruby on rails5で環境構築とgitの設定(初心者向け)

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

Railsアプリが開けない...エラーへの対処法

アプリケーションファイルを作成してプレビューしようとしたところ、
ActiveRecord::ConnectionNotEstablished
とエラーが表示され、進められないといった事態が起こりました...

あるエンジニアさんに質問したところ、原因と解決方法を教えていただけたので簡単に紹介します。かなり端的です。
言語と環境は以下の通りです。
・Ruby 2.6.3
・Rails 6.0.2.1
・AWS Cloud9

原因1:RailsのVer.がうまく指定できていない

[解決方法]
RailsのVer.が6だったので、
ターミナルで、

$ gem install rails -v 5
$ rails _5_ new sample-app(←アプリ名の例)

をそれぞれ入力する。
→Ver.を5に落として指定することで解決

原因2:RailsがSQLite3 1.4.2(最新Ver.)に対応していない

[解決方法]
作成したアプリファイルの中の[Gemfile]を開くと、

Gemfile
gem 'sqlite3'

と書いてあります。
このままだと最新Ver.なので、その後ろに、

Gemfile
gem 'sqlite3','~> 1.3.6'

といったように書き足し、(「,」を書き忘れずに!)
ターミナルで、

$ bundle update

と入力し、変更を保存する。

→Ver.を1.3.6に落として指定することで解決


その後、ターミナルで、

$ rails s -b $IP -p $PORT

と入力すると…起動させることに成功しました!

最終的に、
・Ruby 2.6.3 → 変更なし
・Rails 6.0.2.1 → 5.0.7.2
・sqlite3 1.4.2 → 1.3.6
となりました:thumbsup:

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

Rust でつくるかんたん Ruby Gem

はじめに

Rubyの処理を高速化するためにはC言語でRuby拡張を書く方法が有名です。
先日、海外のインターネット掲示板Redditで、「Rustで書かれたGemをリリースしたよ!」という記事を見つけました。

どうやらRustで処理が書かれたRubyのGemを作ることができるようです。
このGemの中身を観察して、Rustでフィボナッチ数を計算するシンプルなGemを作ってみました。

Gem を作る

bundlerでGemのテンプレートを作成します。

bundle gem fib -t rspec # RSpecのテストを同時作成
cd fib

fib はフィボナッチ(Fibonacci)の略です。

gemspec を編集する

fib.gemspec を編集します。今回は遊びなので、下記のように単純にしました。

fib.gemspec
require_relative 'lib/fib/version'

Gem::Specification.new do |spec|
  spec.name          = "fib"
  spec.version       = Fib::VERSION
  spec.author        = ["kojix2"]
  spec.summary       = "Get the fibonacci number"
  spec.files         = Dir['lib/**/*', 'src/**/*.rs', 'Cargo.toml', 'LICENSE', 'README.md']
  spec.require_paths = ["lib"]
end

cargo init する

Cargo.tomlを作成します。

cargo init --lib

Cargo.toml を編集する

Cargo.tomlに次の2行を書き加えます。

[lib]
crate-type = ["cdylib"]

全体は次のようになります。

Cargo.toml
[package]
name = "fib"
version = "0.1.0"
authors = ["author <soda_mail_siyo@mail.com>"]
edition = "2018"

[lib]
crate-type = ["cdylib"]

[dependencies]

これでGemのテンプレートができました。

フィボナッチ数列を計算する Rust のコードを追加する

を参照して src/lib.rs を開いて下記のように関数を追加します。

lib.rs
#[no_mangle]
pub extern fn fib(n: u32) -> u32 {
    if n <= 1 {
        n
    } else {
        fib(n - 1) + fib(n - 2)
    }
}

Rakefileを編集する

Rakefileに rust_build タスクを追加します。
(共有ライブラリ libfib.so の拡張子は、Macでは libfib.dylib Windowsでは libfib.dll など手元の環境に合わせて書きかえてください。)

Rakefile
task :rust_build do
  `cargo rustc --release`
  `mv -f ./target/release/libfib.so ./lib/fib` # OSによって書き換える
end

task :build => :rust_build
task :spec => :rust_build

動作確認のため rake rust_build してみます。ターミナルに次の表示が現れれば成功です。

   Compiling fib v0.1.0 (/home/kojix2/Ruby/fib)
    Finished release [optimized] target(s) in 3.50s

tree または exa -T コマンドでディレクトリの構成を確かめてみます。
lib/fibディレクトリにlibfib.soが配置されているのがわかりますね。

image.png

同じようにcleanを追加してみます(これは必須ではありません)。

Rakefile
task :rust_clean do
  `cargo clean`
  `rm -f ./lib/fib/libfib.so` # OSによって書き換える
end

task :clean => :rust_clean

rake clean してみましょう。

exa -T

image.png

targetディレクトリとlibfib.soが削除されているのがわかると思います。

FFI

Rubyからrustを呼ぶ方法はForeign function interface (FFI) を使います。
Rubyには主なFFIのライブラリが fiddleruby-ffi の2種類があります。今回のような簡単なケースでは、どちらでも大丈夫です。

FFIモジュールを作成する

Fibモジュールの中に、FFIモジュールを追加します。このFFIモジュールに、rustの関数をRubyのメソッドとして追加します。

lib/fib/ffi.rb
module Fib
  module FFI
  end
end

完成イメージはこんな感じです。
image.png

fiddle を使用する場合

fiddle はRubyの標準ライブラリですのですぐ使えます。

lib/fib/ffi.rb を新規作成します。libfib.so の拡張子に注意してください。

lib/fib/ffi.rb
require 'fiddle/import'

module Fib
  module FFI
    extend Fiddle::Importer
    dlload File.expand_path('libfib.so', __dir__)
    # Mac は libfib.dylib, Win は libfib.dll 等に書き換える。
    extern 'unsigned int fib(unsigned int n)' # C言語の形式で表記する
  end
end

FiddleがWindowsで動作しない場合は、下記のスタックオーバーフローの日本語トピックを参照。

ruby-ffi を使用する場合

ruby-ffi はRubyの標準ライブラリではないので、fib.gemspecを編集して追加します。

fib.gemspec
spec.add_dependency "ffi"

bundle updateしてffiをインストールします。

lib/fib/ffi.rb を新規作成します。

lib/fib/ffi.rb
require 'ffi'

module Fib
  module FFI
    extend FFI::Library
    lib_name = "libfib.#{::FFI::Platform::LIBSUFFIX}"
    ffi_lib File.expand_path(lib_name, __dir__)
    attach_function :fib, [:uint], :uint
  end
end

Rubyらしくfib関数を呼び出せるようにする

最後に使用感をRubyらしく変更します。今回は

Fib[3] # => 2

という風に角括弧をつかったイディオムでフィボナッチ数を呼び出せるようにします。
lib/fib.rb を次のように編集して、Fibモジュールに[]メソッドを追加します。

lib/fib.rb
require "fib/ffi" # 追加
require "fib/version"

module Fib
  def self.[](n)
    FFI.fib(n)
  end
end

最初から Fib モジュールにrustの関数を追加することもできます。しかし、他言語の関数を直接呼び出す前に、Ruby側で何か処理が必要になるケースがほとんどだと思います。だから今回のケースのように専用のモジュール(今回はFib::FFI)を作成して、Fibモジュールからは専用のモジュールのメソッドを間接的に呼び出すようにした方が安全でしょう。

image.png

それでは、動かしてみます。

bundle exec bin/consle

image.png

うまく動いているようです。

テストを追加する

(少しタイミングが遅いと感じる人もいるかも知れませんが)ここでテストを追加します。

spec/fib_spec.rb を編集します。

fib_spec.rb
RSpec.describe Fib do
  it "has a version number" do
    expect(Fib::VERSION).not_to be nil
  end

  it "calculates fibonatti" do
    expect(Fib[10]).to eq(55)
  end
end

インストール

rake install

bundlerなしでもgemが動作するか確認してみましょう。

公開用Gemを作る上での注意点など

  • 処理中の割り込み
    • 今回のフィボナッチ数を計算するプログラムは Ctrl+C を押しても中断ができません。
  • エラー処理
    • rust側で発生したエラーを回収する方法を工夫する必要がありそうです。
  • クロスプラットフォーム対応
    • 実際にGemを作って配布するとなると、色々なOSで動作させたり、共有ライブラリのパスを探す処理も必要になるでしょう。
  • Gem配布のときに共有ライブラリを含めるかどうか
    • これはRubyとRustというよりは、バインディング全般の問題ですね。
      • 全てのOSの共有ライブラリをバージョン決め打ちで最初からGemに含めておく方法。
      • gemをリリースするタイミングで共有ライブラリを生成する方法。
      • Gemをリリースするタイミングで共有ライブラリをどこかからダウンロードする方法。
      • ユーザーがrustを持っているのを前提にしてユーザー側でコンパイルさせる方法。
      • ユーザーがパッケージマネージャー等で事前にlib.soを入手することを前提にして、Ruby側ではそれを探すだけにする方法
      • などなど他にもあるかもしれませんが、目的や想定利用者に応じて選ぶ必要がありそうですね。

Githubに公開されている良作のGemなどをよく観察して、良さそうな方法を少し取り入れていくのがよいと思われます。

最後に

思いのほか簡単にRustを組み込んだRubyのGemが作れる気がしてきました。少しrustの勉強意欲がわきました。
気がついたことなどあったら、コメント欄などになんでもやさしくご指摘ください。

この記事は以上です。

参考文献

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

Rails + GitHub の導入

概要

Ruby on Rails 作成したアプリケーションを GitHub に登録して管理するまでの流れになります。

目次

  1. Rails アプリケーションのローカルリポジトリを作成
  2. GitHub にリモートリポジトリを作成
  3. ローカルリポジトリとリモートリポジトリを結びつける
  4. ローカルリポジトリをリモートリポジトリに反映

1. Rails アプリケーションのローカルリポジトリを作成

ターミナルで rails new コマンドを実行し、ローカルレポジトリを作成します。

ターミナル
$ rails _<railsのバージョン>_ new <アプリの名前> -d <データベースの種類>

# (例)
# $ rails _5.2.3_ new test-github -d mysql
# "5.2.3"バージョンで、データベースに "mysql" を使用し、"test-github" という名前のアプリを作成する。

2. GitHub にリモートリポジトリを作成

GitHub で「+」メニューから「 New repository 」をクリックします。
image

リモートレポジトリ名を入力し、「 Create repository 」ボタンをクリックしてリポジトリを作成します。
image

以下の様な画面になれば、リモートリポジトリの作成は完了です。
image

3. ローカルリポジトリとリモートリポジトリを結びつける

まずURLをコピーします。
image

次にコマンドで操作します。

ターミナル
$ cd ~/test-github
$ git remote add origin <先程コピーしたURL>

# (例)
# git remote add origin https://github.com/username/test-github.git
コマンド説明
git remote add
# ローカルリポジトリにリモートリポジトリの情報を付与して、紐づけを行うためのコマンドです。

origin
# リモートリポジトリの場所の別名です。他の名前をつけることも出来ますが、GitHubのリモートリポジトリに対してはoriginとすることが一般的です。

以上で紐づけは完了です。以下のコマンドで確認しましょう。

ターミナル
$ git remote
origin

ここで origin と出力されれば完了です。

4. ローカルリポジトリをリモートリポジトリに反映

3.で紐づけが完了したので、ローカルリポジトリの現状の情報を、リモートリポジトリに反映します。
以下のコマンドを実行します。

ターミナル
$ cd ~/test-github
$ git add .              # すべて(.)の修正ファイルをインデックスに追加
$ git commit -m "first_commit"  # コミットメッセージを付与してコミット
$ git push origin master
コマンド説明
git add <記録するファイル名>
# インデックスに追加して、変更修正記録の対象とすることができます。

git commit -m "<コミットメッセージ>"
# インデックスに追加されている変更修正を、コミットするためのコマンドです。-mのオプションはコミットメッセージと呼ばれ、どのような変更を行ったのかメモを残せます。

git push
# ローカルリポジトリでのコミットをリモートリポジトリ(origin)に反映させる操作ができます。

最後にブラウザで確認してみましょう。先程のリモートリポジトリ作成後のページをリロードしてください。
image
上記のような表示なっていれば正しく反映できています。

以上で Rails + GitHub の導入は完了です。

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

New credentials encrypted and saved. の対処法

前提条件

Docker
Rails5.2

解決したいこと

Terminal
docker-compose run -e EDITOR="vim" web rails credentials:edit

のコマンドを入力した際に、credentialsを編集できずに

Terminal
New credentials encrypted and saved.

と表示されてしまう。

解決方法

  • credentials.yml.encの削除
  • docker-compose build

をするとうまくいく。

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

一時フォルダ内だからといってファイルを閉じ忘れてはいけない

結論

一時フォルダを消してもそのファイルが完全に消えずハードディスクを圧迫して困ります、ちゃんと閉じましょう

紹介: 一時フォルダ

Rubyでは簡単に一時フォルダが作れてブロックが終わるとフォルダが消えてくれるので作業フォルダとして扱いやすいです

Dir.mktmpdir('test') do |dir|
  # ファイル作ったり開いたり
end

失敗: ファイルを開く(閉じない)

どうせ一時フォルダで消えるのだからと Open して使うだけで閉じるのを忘れていると....

Dir.mktmpdir('test') do |dir|
  # ファイル生成処理
  f = File.open(path)
  # 作業
end

問題: ファイルが消えない

tmp フォルダは空っぽなのにハードディスクがどんどん圧迫されていく...
そう Linux だとプロセスが残る限り完全に消えていないのです
Rails server や Delayed Job Woker の再起動などを行い問題の処理のあるプロセスごと一旦落とさない限り残り続けてしまいます

$ lsof | grep delete
bundle 23931 (略) /tmp/test20200317-23931-cayd6g/test.pdf (deleted)

※)上記例では プロセス 23931 が掴んでいるため仮削除状態

対処: 閉じましょう

ファイルが開放されるので一時フォルダの削除とともに完全に削除されます
これを行っていればプロセスごと落とす必要はありません

Dir.mktmpdir('test') do |dir|
  # ファイル生成処理
  File.open(path) do
    # 作業
  end
end

参考

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

【第1章】Rails チュートリアル サーバー立ち上げまで

はじめに

当記事ではRailsチュートリアルの学習記録をまとめております。
Railsチュートリアルを進めている中でエラーに困っている初心者の方は
もしかしたらこの記事で何かヒントを得られるかもしれません。

※注意※
プログラミング初学者が執筆した記事であるため、
当記事の内容に誤りがある可能性がございます。

前提条件

Ruby on Railsチュートリアル 第4版(5.1)
使用機器:MacBook Air
ブラウザ:google chrome
開発環境:AWS cloud9
リモート:GitHub

アプリケーションの作成

1. railsのインストール

まずは開発環境にrailsをインストール。
と、その前に以下をコマンドラインに入力し実行する。

$ printf "install: --no-document \nupdate:  --no-document\n" >> ~/.gemrc

このコマンドの目的はRubyドキュメントをインストールしないことだが、
今の段階ではコマンドの意味は知らなくても良いとのこと。

意味が気になる?
printf ○○○ >> ~/.gemrc → ○○○の内容を~/.gemrcに反映。


今回の場合、
install: --no-document update: --no-document/.gemrcに反映させろ」
→「インストール時、アップデート時にドキュメントを除外しろ」
というコマンドであることがわかる。


/nは改行の役目を果たしている。

その後、railsをインストールするため以下のコマンドを実行。

$ gem install rails -v 5.1.6

gem install ◯◯ バージョン →指定のバージョンの◯◯というgemをインストール。
つまり、「rails」とはgemの一つであることがわかる。

そもそもgemってなんだっけ?
Rubyのパッケージ(ライブラリ)。便利な機能がパッケージされたもの。
種類は幅広くて、gemをインストールすることで簡単にユーザー認証機能を実装できたりする。
RubyGemsにgemがいっぱい入っているので、暇なときに見てみよう。


スクリーンショット 2020-03-16 21.26.51.png
ジャスティンビーバーの曲くらいダウンロードされている人気者。

2.アプリケーションの作成

まず、environmentディレクトリに移動する。

$ cd ~/environment

補足情報:コマンドラインでは現在自分がどの位置にいるかが$の左側で示されている。
ec2-user:~/environment $

下のコマンドを実行し、アプリケーションを作成。

rails _5.1.6_ new hello_app

これで大量のディレクトリ、ファイルが生成された。

Bundlerのインストール

Bundlerとは?
gemの互換性やバージョン管理をしてくれるgem。

Gemfileを指定の内容に変更する。

注意点
ファイルの内容を変更した後、必ずCtrl + sで変更内容をセーブしよう。
セーブが行われていない場合、ファイルのタイトルバーの右側に●マークがある
スクリーンショット 2020-03-17 13.50.19.png

gemのバージョンを固定することで、チュートリアルを同じ挙動で進めることができる。
その後、Bundle installを実行。

$ bundle install

※カレントディレクトリがhello_appであることを確認してから実行しよう。
※上記のコマンドを実行して、「bundle updateを実行してください」というエラーメッセージが出たら、先にBundle updateを実行しよう。

railsサーバーの実行

これまでの準備で、サーバーを起動する準備が整った。
以下のコマンドで、実際にサーバーを立ち上げよう。

$ cd ~/environment/hello_app/
$ rails server

※今までのターミナルではなく、新しいターミナルで実行しよう。
※サーバーを終了するときはCtrl + C。

これによりブラウザで表示できるようになったので確認してみよう。
スクリーンショット 2020-03-17 14.07.18.png

参考

Bundlerとは:https://pikawaka.com/rails/bundler

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

Rubyによるデザインパターン(2)

Rubyによるデザインパターン(2)

 本記事は初級エンジニアがRubyを使用したデザインパターンをアウトプットしたものになります。また、デザインパターンは種類が多いため、何回かに分けて掲載していきたいと思います。今回はTemplateMethodパターンとFactoryMethodパターンをご紹介します。なお、こちら記事は次のサイトを参考にしております。
TECHSCORE
酒と涙とRubyとRailsと

TemplateMethodパターン

 TemplateMethod パターンは、テンプレートの機能を持つパターンです。親クラスで処理の枠組み(テンプレート)を定め、子クラスでその具体的内容を実装します。親クラスで抽象度の高いロジックを組み込み、子クラスで抽象度の低い詳細なロジックを組み込みことで、役割を分担することができます。

サンプルソース
・Report(抽象的なベースの親クラス): レポートを出力する
・HTMLReport(子クラス): HTMLフォーマットでレポートを出力
・PlaneTextReport(子クラス): PlanTextフォーマットでレポートを出力

レポートの出力を行うReportクラスは次のとおり
(Reportクラスは4つのメソッドを持つ)

class Report
    def initialize
      @title = "html report title"
      @text = ["report line 1", "report line 2", "report line 3"]
    end

    # レポートを出力する順番を規程
    def output_report
        output_start
        output_body
        output_end
    end

    # レポートの先頭で出力
    def output_start
    end

    # レポートの本文で出力
    def output_body
        @text.each do |line|
            output_line(line)
        end
    end

    # output_bodyの内容
    # 今回は個別クラスに規定するメソッドとする。規定されてなければエラーを返す
    def output_line(line)
        raise 'Called abstract method !!'
    end

    # レポートの末尾で出力
    def output_end
    end
end

HTML形式でのレポート出力を行うHTMLReportは以下のとおり
(ReportクラスのメソッドでHTML出力する際に変化する3つのメソッドを持つ)

# HTML形式でのレポート出力を行う
class HTMLReport < Report
    # レポートの先頭を出力
    def output_start
        puts ""
    end

    # output_bodyの内容
    def output_line(line)
        puts "#{line}"
    end

    # レポートの末尾を出力
    def output_end
        puts ""
    end
end

最後にPlaneText形式(*で囲う)での出力を行うPlaneTextReportクラスは以下のとおり
(ReportクラスのメソッドでPlaneText形式で出力する際に変化する2つのメソッドを持つ)

# PlaneText形式(*****で囲う)でレポートを出力
class PlaneTextReport < Report
    # レポートの先頭で出力
    def output_start
      puts "**** #{@title} ****"
    end

    # output_bodyの内容
    def output_line(line)
        puts line
    end
end

以上のコードを実際に実行すると次のようになります。

html_report = HTMLReport.new
html_report.output_report
#
# report line 1
# report line 2
# report line 3
#

plane_text_report = PlaneTextReport.new
plane_text_report.output_report
#**** html report title ****
#report line 1
#report line 2
#report line 3

 結果から抽象度の高いメソッドを持つReportクラスから、HTML形式とPlaneText形式でレポートを出力することができました。なお、オブジェクトを初期化するメソッドinitializeは既存のinitializeをオーバーライドして、自由に初期化処理を行うことができます。つまりinitializeは広義でのTempleteMethodパターンとなります。続いて、FactoryMethodパターンを説明します。

FactoryMethodパターン

 FactoryMethodパターンはオブジェクトの生成方法に一工夫加えることで、より柔軟なオブジェクトを生成することを目的としています。FactoryMethodパターンではインスタンスの生成を子クラスに行わせることでより柔軟に生成するインスタンスを選択することができるようになります。
 それではFactoryMethodをコードを使用して説明していきます。ここではデスクトップパソコンとパソコンを製造する工場を例にします。デスクトップパソコンを表すDesktopクラスは、電源を入れる(start)メソッドを持っており、パソコン工場を表すPersonalComputerFactoryクラスはコンストラクタの引数でパソコンの数を受け取り、またパソコンを出荷するメソッド「ship_out」を持っています。

DesktopクラスとPersonalComputerFactoryクラスは次のとおり

# デスクトップ (Product)
class Desktop
    def initialize(name)
        @name = name
    end

    def start
        puts "デスクトップ #{@name} は電源を入れました"
    end
end

# パソコン工場 (Creator)
class PersonalComputerFactory
    def initialize(number_desktops)
        @desktops = []
        number_desktops.times do |i|
            desktop = Desktop.new("デスクトップ #{i}")
            @desktops << desktop
        end
    end

    # パソコンを出荷する
    def ship_out
        @tmp = @desktops.dup
        @desktops = []
        @tmp
    end
end

上のプログラムを実行

factory = PersonalComputerFactory.new(3)
desktops = factory.ship_out
desktops.each { |desktop| desktop.start }
#=> デスクトップ 0 は電源を入れました
#=> デスクトップ 1 は電源を入れました
#=> デスクトップ 2 は電源を入れました

ここで、新たにラップトップ(Laptop)モデルを追加してみます
(インタフェースはデスクトップとまったく同じもの)

# ラップトップ (Product)
class Laptop
    def initialize(name)
      @name = name
    end

    def start
      puts "ラップトップ #{@name} は電源を入れました"
    end
end

先ほど作ったPersonalComputerFactoryモデルをもう一度確認

# パソコン工場 (Creator)
class PersonalComputerFactory
  def initialize(number_desktops)
    @desktops = []
    number_desktops.times do |i|
      desktop = Desktop.new("デスクトップ #{i}")
      @desktops << desktop
    end
  end

  # パソコンを出荷する
  def ship_out
    tmp = @desktops.dup
    @desktops = []
    tmp
  end
end

 ラップトップモデルを追加する場合、一点問題が発生します。それはPersnalComputerFactoryクラスにおいて、コンストラクタ(initialize)でデスクトップを作っている点です(desktop = Desktop.new("デスクトップ #{i}"))。そこで、PersonalComputerFactoryクラスのデスクトップを生成している部分を子クラス(DesktopFacotory)で実装し、再度、ラップトップを生成するLaptopFactoryクラスを作成してみましょう。

class PersonalComputerFactory
    def initialize(number_personal_computers)
      @computers = []
      number_personal_computers.times do |i|
        computer = new_computer("パソコン #{i}")
        @computers << computer
      end
    end

    # パソコンを出荷する
    def ship_out
      @tmp = @computers.dup
      @computers = []
      @tmp
    end
  end

  # DesktopFactory: デスクトップを生成する (ConcreteCreator)
  class DesktopFactory < PersonalComputerFactory
    def new_computer(name)
      Desktop.new(name)
    end
  end

  # LaptopFactory: ラップトップを生成する (ConcreteCreator)
  class LaptopFactory < PersonalComputerFactory
    def new_computer(name)
      Laptop.new(name)
    end
  end

 上記のPersonalComputerFactoryではnew_computer(パソコンの生成)で処理を抽象化することで、追加されたラップトップモデルに対応することができます。それでは実際にプログラムを実行し、結果を確認してみましょう。

factory = DesktopFactory.new(3)
desktops = factory.ship_out
desktops.each { |desktop| desktop.start }
#=> デスクトップ パソコン 0 は電源を入れました
#=> デスクトップ パソコン 1 は電源を入れました
#=> デスクトップ パソコン 2 は電源を入れました

factory = LaptopFactory.new(3)
laptops = factory.ship_out
laptops.each { |laptop| laptop.start }
#=> ラップトップ パソコン 0 は電源を入れました
#=> ラップトップ パソコン 1 は電源を入れました
#=> ラップトップ パソコン 2 は電源を入れました

 結果のとおり、デスクトップ/ラップトップの作成及び各パソコンの電源を入れることができるようになりました。このようにクラスの選択を子クラスに任せることを「FactoryMethod」と呼びます。
 なお、ファクトリメソッドは次の3つで構成されています。
 ・Creator: ConcreteFactoryの共通部分の処理を行う(PersonalComputerFactory)
 ・ConcreteCreator: 実際にオブジェクトの生成を行う(DesktopFactory, LaptopFactory)
 ・Product: ConcreteFactoryによって生成される側のオブジェクト(desktop、laptop)

以上で今回の説明を終了します。

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

Rails6 のちょい足しな新機能を試す 124(eager loading bug fix編)

はじめに

Rails 6 に追加された新機能を試す第124段。 今回は、eager loading bug fix 編です。
Rails 6.0.0 では、 app ディレクトリの下にファイルを置くと rails server を実行した時に エラーになるというバグがありました。

この事象は、Ubuntu などでは発生しますが、MacOS/X では発生しないようです。

Rails 6.0.1 以降では修正されています。

Ruby 2.6.5, Rails 6.0.2.1, 6.0.1, Rails 6.0.0 で確認しました。(6.0.1で修正が入ってます。)

$ rails --version
Rails 6.0.1

今回は、 rails new して、 app ディレクトリの下にファイルを作って確認してみます。

Rails プロジェクトを作る

Rails プロジェクトを新たに作成します。

$ rails new rails_sandbox
$ cd rails_sandbox

app の下にファイルを作成する

touch コマンドでapp の下にファイルを作成します。

touch app/file.txt

Rails 6.0.1 では

Rails 6.0.1 では、 rails server してもエラーになりません。

Rails 6.0.0 では

Rails 6.0.0 では、エラーになります。

$ rails server
...
         1: from /usr/local/bundle/gems/rb-inotify-0.10.1/lib/rb-inotify/notifier.rb:200:in `new'
         /usr/local/bundle/gems/rb-inotify-0.10.1/lib/rb-inotify/notifier.rb:200:in `initialize': Not a directory @ dir_initialize - /app/app/file.txt (Errno::ENOTDIR)

試したソース

参考情報

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

@importと、requireって何が違うの?

@impirtとは

@importはscssが用意しているメソッドです。そのため、application.scssと拡張子を変更しないと使えません。また、application.scssからscssファイルをインポートするために使用しなけばなりません。

scssはscss専用のメソッドなので、requireとは異なります。

reqireとは

requireはRailsのアセットパイプラインの仕組みを使ってファイルをインポートすることを指します。

アセットパイプラインとは

アセットパイプラインとは、JavaScriptやCSSのアセットを最小化 (minify: スペースや改行を詰めるなど) または圧縮して連結するためのフレームワークです。アセットパイプラインでは、CoffeeScriptやSass、ERBなど他の言語で記述されたアセットを作成する機能を追加することもできます。 アセットパイプラインはアプリケーションのアセットを自動的に他のgemのアセットと結合できます。たとえば、jquery-railsにはRailsでAJAXを使えるようにするjquery.jsが含まれています。

アセットパイプラインはsprockets-rails gemによって実装され、デフォルトで有効になっています。アプリケーションの新規作成中にアセットパイプラインを無効にするには、--skip-sprocketsオプションを渡します。
引用 - rails ガイド

つまりは、cssファイルやJavaScriptのファイルを1つにまとめ、圧縮することで処理速度を早くするための仕組み。sprocketsというgemがこの機能を担ってるってことです。

両者の違い

こう書いてみると、@importもrequireも何かをひっぱてきているような感覚は同じですが、importはscssの専用メソッドで、ファイルを読み込む記述、対してrequireは、cssやjsのファイルを1つにまとめて圧縮したファイルを読み込んでいるという違いがあることが分かりました。

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

プログラミング王に、、俺はなる!!!

前回までのあらすじ

謎の赤髪の男から「このMacBookPRO16インチ(30万ベリー)をお前に預ける。。いつかきっと返しにこい。。。絶対壊すなよ?」
とノートPCをもらったNSぱんだまん。約2ヶ月間progateを学習しクソ雑魚海王類なら一撃で倒せる力を身に着けた。ここからNSぱんだまんの冒険が今始まる!!

世はまさに!!!!大プログラミング時代!!!!

テンテンテンテンテンデッテーン♪ありったけのー言語〜使いこなーし〜
探しもの〜探〜し〜に〜ゆーくーのーさー!

HELLO WORLD!!!!!

というわけで今回は、、、環境構築!!!

に取り掛かっていきたい。そう思うわけですよ。でもね、初心者からしたら訳わかんないのよ。環境構築って何?って感じだよね。

まず環境構築とは。っての調べてみたんだけど。
環境構築・・・環境構築とは、特定の装置やソフトウェア、システムなどが動作するように、コンピュータや情報システムの状態を整えること。特に、コンピュータにソフトウェアを導入したり設定を調整することで、対象のソフトウェアが動作する環境を作り上げる作業を意味する場合が多い。(IT用語辞典 引用)

って書いてあるのをそのままコピペして貼り付けて見たんだけどさ。正直意味分かんないよこれ。笑

とりあえず自分のPCにRubyやRailsをインストール

自分のPCでRubyやRailsを動かせるようにするってことみたい。

うーん。。それはなんとなくわかるよ?このままじゃわからないしprogateみたいな画面にもできないからそもそもコード書けないしさ。

というわけで。。。
すごく親切な方が「環境構築についてはこのサイトがいいですよー」
って教えてくれたのが。。。
Rails Girls ガイド https://railsgirls.jp/
Ruby on Rails チュートリアル https://railstutorial.jp/
です。

るっっっっっRuby on Rails チュートリアル...笑

私はRailsチュートリアルという呪縛から永遠に逃れることはできないようです。。

・・・まあいい。
環境構築さえわかったらこんなサイトすぐ辞めてやるぜ!!!!
というわけで少し見てみます。

どうやら環境構築についてはテキストエディタ(NSぱんだまんはATOM)とコマンドライン(NSぱんだまんはMACなのでターミナル)を使う環境とIDE(統合開発環境)2つに分けることができるらしい。
IDE。。。また意味分かんない単語でてきたな。
IDE(統合開発環境)とは 
プログラミングをする際に必要なソフトウェア(テキストエディタ・コンパイラ・デバッガ・コードバージョン管理等)を統合して、1つの画面で操作できるようにしたもの。英語で「Integrated Development Environment」の略

なるほどね〜つまり

パルスのファルシのルシがパージでコクーンってわけね!

14年前の記憶が蘇りました。笑(注:FF12のネタです)
プログラミングの勉強しててほんと思うんだけど一個の単語調べたときの説明にまた意味分かんない単語あってそれ調べたらまた意味分かんない単語にぶつかって結果的に萎えるってよくありますよね。笑

とりあえずIDEをまとめると

プログラムを作るために必要なものが揃ってるすげー開発環境

ってことです。

ちなみにデバッガとは「デバッグ(テストなどによって発見された誤作動・不具合について、その原因やプログラム上での位置を探索・特定し、意図したとおり動作するように修正する作業)作業を支援するソフトウェア」のこと

コンパイラとは「プログラミング言語で書かれたソースコードを読み込んで解析し、コンピュータが直に実行可能な機械語や、それに相当する中間言語などで記述されたオブジェクトコードに変更する作業(コンパイル)を行うソフトウェア。」のことみたいです。

ちゅーわけで今回はIDEを使用した環境構築をやろうと決めました。
IDEはいっぱい種類があるみたい。
例えば
⇨Eclipse
⇨IntelliJ IDEA
⇨NetBeans
⇨Visual Studio Community
⇨Xcode
⇨Android Studio
とか。上記のやつは無料で使えるらしい。

今回使うのはそれともまた違ってクラウド上での統合開発環境ってやつでこれはPC上に環境を設定しなくて済むので準備が簡単にできるんだって!ちなみにクラウドってのはソルジャークラスfirstで金髪のバスターソード扱う青年のことです。

うん。。興味ないね。。

...すいません。
AWSのCloud9っての使います。
詳しい設定方法はRuby on Rails チュートリアルに載ってますよ。

さ~て!!!速攻でローカル開発環境構築するぞー!!!!!!!!!

〜6時間経過〜
やーできたー簡単だったなーcloud9の設定。6時間で簡単にローカル環境構築できちゃった♡

。。。まじで疲れました。
簡単とか書いてあったのに激ムズじゃねーか。。。
とりあえず流れざっくりと書くと
AWSに登録。(住所とかクレジット番号とか個人情報を入力)

ルートユーザーIDを取得

cloud9を設定しようとするも弾かれる
cloud9「ちょっと君君ー。ルートユーザーじゃだめだよおお?。IAMでアカウント作ってから出直してこいや。」

IAMにてアカウント作成。グループ作成。
IAMアカウントからAWSにログイン。

ここからcloud9へ。
cloud9さん「おっやっときたね〜。(ここまで3時間ほど費やす)Railsに会いにきたんでしょ?でもRails今はいないんだよね。呼んできてくれる?」

railsをインストール(具体的な流れはrailsチュートリアルに記載あり)
とはいうもののRailsがはぐれメタル並に出てこない。

...3時間苦戦しやっとローカル環境完成。
長かった。。。最後泣くほど嬉しかったです。
悩めば悩んだ分だけ解決できた時の嬉しさってはんぱないよね。
とりあえずここからいろいろ作っていこうと思います。

あとやっぱRailsチュートリアルやっといたほうがいいわ。。
なんだかんだこれないとなんもできなかったし。

railsチュートリアルと実際に簡単なアプリ作成を同時進行みたいな感じで進めていきたいと思います。
今回はここまで!!!

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

プログラミング王に、、俺はなる!!!(環境構築編)

前回までのあらすじ

謎の赤髪の男から「このMacBookPRO16インチ(30万ベリー)をお前に預ける。。いつかきっと返しにこい。。。絶対壊すなよ?」
とノートPCをもらったNSぱんだまん。約2ヶ月間progateを学習しクソ雑魚海王類なら一撃で倒せる力を身に着けた。ここからNSぱんだまんの冒険が今始まる!!

世はまさに!!!!大プログラミング時代!!!!

テンテンテンテンテンデッテーン♪ありったけのー言語〜使いこなーし〜
探しもの〜探〜し〜に〜ゆーくーのーさー!

HELLO WORLD!!!!!

というわけで今回は、、、環境構築!!!

に取り掛かっていきたい。そう思うわけですよ。でもね、初心者からしたら訳わかんないのよ。環境構築って何?って感じだよね。

まず環境構築とは。っての調べてみたんだけど。
環境構築・・・環境構築とは、特定の装置やソフトウェア、システムなどが動作するように、コンピュータや情報システムの状態を整えること。特に、コンピュータにソフトウェアを導入したり設定を調整することで、対象のソフトウェアが動作する環境を作り上げる作業を意味する場合が多い。(IT用語辞典 引用)

って書いてあるのをそのままコピペして貼り付けて見たんだけどさ。正直意味分かんないよこれ。笑

とりあえず自分のPCにRubyやRailsをインストール

自分のPCでRubyやRailsを動かせるようにするってことみたい。

うーん。。それはなんとなくわかるよ?このままじゃわからないしprogateみたいな画面にもできないからそもそもコード書けないしさ。

というわけで。。。
すごく親切な方が「環境構築についてはこのサイトがいいですよー」
って教えてくれたのが。。。
Rails Girls ガイド https://railsgirls.jp/
Ruby on Rails チュートリアル https://railstutorial.jp/
です。

るっっっっっRuby on Rails チュートリアル...笑

私はRailsチュートリアルという呪縛から永遠に逃れることはできないようです。。

・・・まあいい。
環境構築さえわかったらこんなサイトすぐ辞めてやるぜ!!!!
というわけで少し見てみます。

どうやら環境構築についてはテキストエディタ(NSぱんだまんはATOM)とコマンドライン(NSぱんだまんはMACなのでターミナル)を使う環境とIDE(統合開発環境)2つに分けることができるらしい。
IDE。。。また意味分かんない単語でてきたな。
IDE(統合開発環境)とは 
プログラミングをする際に必要なソフトウェア(テキストエディタ・コンパイラ・デバッガ・コードバージョン管理等)を統合して、1つの画面で操作できるようにしたもの。英語で「Integrated Development Environment」の略

なるほどね〜つまり

パルスのファルシのルシがパージでコクーンってわけね!

14年前の記憶が蘇りました。笑(注:FF12のネタです)
プログラミングの勉強しててほんと思うんだけど一個の単語調べたときの説明にまた意味分かんない単語あってそれ調べたらまた意味分かんない単語にぶつかって結果的に萎えるってよくありますよね。笑

とりあえずIDEをまとめると

プログラムを作るために必要なものが揃ってるすげー開発環境

ってことです。

ちなみにデバッガとは「デバッグ(テストなどによって発見された誤作動・不具合について、その原因やプログラム上での位置を探索・特定し、意図したとおり動作するように修正する作業)作業を支援するソフトウェア」のこと

コンパイラとは「プログラミング言語で書かれたソースコードを読み込んで解析し、コンピュータが直に実行可能な機械語や、それに相当する中間言語などで記述されたオブジェクトコードに変更する作業(コンパイル)を行うソフトウェア。」のことみたいです。

ちゅーわけで今回はIDEを使用した環境構築をやろうと決めました。
IDEはいっぱい種類があるみたい。
例えば
⇨Eclipse
⇨IntelliJ IDEA
⇨NetBeans
⇨Visual Studio Community
⇨Xcode
⇨Android Studio
とか。上記のやつは無料で使えるらしい。

今回使うのはそれともまた違ってクラウド上での統合開発環境ってやつでこれはPC上に環境を設定しなくて済むので準備が簡単にできるんだって!ちなみにクラウドってのはソルジャークラスfirstで金髪のバスターソード扱う青年のことです。

うん。。興味ないね。。

...すいません。
AWSのCloud9っての使います。
詳しい設定方法はRuby on Rails チュートリアルに載ってますよ。

さ~て!!!速攻でローカル開発環境構築するぞー!!!!!!!!!

〜6時間経過〜
やーできたー簡単だったなーcloud9の設定。6時間で簡単にローカル環境構築できちゃった♡

。。。まじで疲れました。
簡単とか書いてあったのに激ムズじゃねーか。。。
とりあえず流れざっくりと書くと
AWSに登録。(住所とかクレジット番号とか個人情報を入力)

ルートユーザーIDを取得

cloud9を設定しようとするも弾かれる
cloud9「ちょっと君君ー。ルートユーザーじゃだめだよおお?。IAMでアカウント作ってから出直してこいや。」

IAMにてアカウント作成。グループ作成。
IAMアカウントからAWSにログイン。

ここからcloud9へ。
cloud9さん「おっやっときたね〜。(ここまで3時間ほど費やす)Railsに会いにきたんでしょ?でもRails今はいないんだよね。呼んできてくれる?」

railsをインストール(具体的な流れはrailsチュートリアルに記載あり)
とはいうもののRailsがはぐれメタル並に出てこない。

...3時間苦戦しやっとローカル環境完成。
長かった。。。最後泣くほど嬉しかったです。
悩めば悩んだ分だけ解決できた時の嬉しさってはんぱないよね。
とりあえずここからいろいろ作っていこうと思います。

あとやっぱRailsチュートリアルやっといたほうがいいわ。。
なんだかんだこれないとなんもできなかったし。

railsチュートリアルと実際に簡単なアプリ作成を同時進行みたいな感じで進めていきたいと思います。
今回はここまで!!!

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

プログラミング王に、、俺はなる!!!(Railsチュートリアル1章)

前回までのあらすじ

謎の赤髪の男から「このMacBookPRO16インチ(30万ベリー)をお前に預ける。。いつかきっと返しにこい。。。絶対壊すなよ?」
とノートPCをもらったNSぱんだまん。約2ヶ月間progateを学習しクソ雑魚海王類なら一撃で倒せる力を身に着けた。ここからNSぱんだまんの冒険が今始まる!!

世はまさに!!!!大プログラミング時代!!!!

テンテンテンテンテンデッテーン♪ありったけのー言語〜使いこなーし〜
探しもの〜探〜し〜に〜ゆーくーのーさー!

HELLO WORLD!!!!!

というわけで今回は、、、環境構築!!!

に取り掛かっていきたい。そう思うわけですよ。でもね、初心者からしたら訳わかんないのよ。環境構築って何?って感じだよね。

まず環境構築とは。っての調べてみたんだけど。
環境構築・・・環境構築とは、特定の装置やソフトウェア、システムなどが動作するように、コンピュータや情報システムの状態を整えること。特に、コンピュータにソフトウェアを導入したり設定を調整することで、対象のソフトウェアが動作する環境を作り上げる作業を意味する場合が多い。(IT用語辞典 引用)

って書いてあるのをそのままコピペして貼り付けて見たんだけどさ。正直意味分かんないよこれ。笑

とりあえず自分のPCにRubyやRailsをインストール

自分のPCでRubyやRailsを動かせるようにするってことみたい。

うーん。。それはなんとなくわかるよ?このままじゃわからないしprogateみたいな画面にもできないからそもそもコード書けないしさ。

というわけで。。。
すごく親切な方が「環境構築についてはこのサイトがいいですよー」
って教えてくれたのが。。。
Rails Girls ガイド https://railsgirls.jp/
Ruby on Rails チュートリアル https://railstutorial.jp/
です。

るっっっっっRuby on Rails チュートリアル...笑

私はRailsチュートリアルという呪縛から永遠に逃れることはできないようです。。

・・・まあいい。
環境構築さえわかったらこんなサイトすぐ辞めてやるぜ!!!!
というわけで少し見てみます。

どうやら環境構築についてはテキストエディタ(NSぱんだまんはATOM)とコマンドライン(NSぱんだまんはMACなのでターミナル)を使う環境とIDE(統合開発環境)2つに分けることができるらしい。
IDE。。。また意味分かんない単語でてきたな。
IDE(統合開発環境)とは 
プログラミングをする際に必要なソフトウェア(テキストエディタ・コンパイラ・デバッガ・コードバージョン管理等)を統合して、1つの画面で操作できるようにしたもの。英語で「Integrated Development Environment」の略

なるほどね〜つまり

パルスのファルシのルシがパージでコクーンってわけね!

14年前の記憶が蘇りました。笑(注:FF12のネタです)
プログラミングの勉強しててほんと思うんだけど一個の単語調べたときの説明にまた意味分かんない単語あってそれ調べたらまた意味分かんない単語にぶつかって結果的に萎えるってよくありますよね。笑

とりあえずIDEをまとめると

プログラムを作るために必要なものが揃ってるすげー開発環境

ってことです。

ちなみにデバッガとは「デバッグ(テストなどによって発見された誤作動・不具合について、その原因やプログラム上での位置を探索・特定し、意図したとおり動作するように修正する作業)作業を支援するソフトウェア」のこと

コンパイラとは「プログラミング言語で書かれたソースコードを読み込んで解析し、コンピュータが直に実行可能な機械語や、それに相当する中間言語などで記述されたオブジェクトコードに変更する作業(コンパイル)を行うソフトウェア。」のことみたいです。

ちゅーわけで今回はIDEを使用した環境構築をやろうと決めました。
IDEはいっぱい種類があるみたい。
例えば
⇨Eclipse
⇨IntelliJ IDEA
⇨NetBeans
⇨Visual Studio Community
⇨Xcode
⇨Android Studio
とか。上記のやつは無料で使えるらしい。

今回使うのはそれともまた違ってクラウド上での統合開発環境ってやつでこれはPC上に環境を設定しなくて済むので準備が簡単にできるんだって!ちなみにクラウドってのはソルジャークラスfirstで金髪のバスターソード扱う青年のことです。

うん。。興味ないね。。

...すいません。
AWSのCloud9っての使います。
詳しい設定方法はRuby on Rails チュートリアルに載ってますよ。

さ~て!!!速攻でローカル開発環境構築するぞー!!!!!!!!!

〜6時間経過〜
やーできたー簡単だったなーcloud9の設定。6時間で簡単にローカル環境構築できちゃった♡

。。。まじで疲れました。
簡単とか書いてあったのに激ムズじゃねーか。。。
とりあえず流れざっくりと書くと
AWSに登録。(住所とかクレジット番号とか個人情報を入力)

ルートユーザーIDを取得

cloud9を設定しようとするも弾かれる
cloud9「ちょっと君君ー。ルートユーザーじゃだめだよおお?。IAMでアカウント作ってから出直してこいや。」

IAMにてアカウント作成。グループ作成。
IAMアカウントからAWSにログイン。

ここからcloud9へ。
cloud9さん「おっやっときたね〜。(ここまで3時間ほど費やす)Railsに会いにきたんでしょ?でもRails今はいないんだよね。呼んできてくれる?」

railsをインストール(具体的な流れはrailsチュートリアルに記載あり)
とはいうもののRailsがはぐれメタル並に出てこない。

...3時間苦戦しやっとローカル環境完成。
長かった。。。最後泣くほど嬉しかったです。
悩めば悩んだ分だけ解決できた時の嬉しさってはんぱないよね。
とりあえずここからいろいろ作っていこうと思います。

あとやっぱRailsチュートリアルやっといたほうがいいわ。。
なんだかんだこれないとなんもできなかったし。

railsチュートリアルと実際に簡単なアプリ作成を同時進行みたいな感じで進めていきたいと思います。
今回はここまで!!!

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

migrationファイルのnull: falseって?

migrationファイルのnull: falseって?

→指定したカラムが(データベースに)カラの状態で保存されることを防ぐ

rb
class CreateNotifications < ActiveRecord::Migration[5.2]
  def change
    create_table :notifications do |t|
      t.integer :visitor_id, null: false
      t.integer :visited_id, null: false
      t.string :action, default: '', null: false
      t.boolean :checked, default: false, null: false
      t.timestamps
    end
    add_index :notifications, :visitor_id
    add_index :notifications, :visited_id
  end
end

モデルに記載するvalidates :content, presence: trueと何が違うの?

似たバリデーションとして、presence: trueがあります。
これは、

Railsの方でカラの情報を保存させないようにするためのものです。

データベース側ではSQLで保存することができてしまうのですね。

どちらを記載すれば良いのか?

どちらも記載しておくと安全ですね。
migrationファイルでは、データベースに対する設定なのに対して、
modelファイルでは、Rails側の設定。
結論:目的の場所が異なるので両方設定しておくことが良いですね。

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

railsで学ぶサーバーサイド(素人が浅い知識で書かせていただきました)

routingとcontrollerとview

rails newコマンドでアプリを作成するとroutingとcontrollerとviewが出来る。これらを使ってURLでデータを扱った処理ができる。

routingでやっている事
任意のURLに対してどのcontrollerのどの関数に飛ばすかを決める。

controllerでやっている事
controllerの中には複数の関数名があり、routingからの指示を受けてその関数名を持つHTMLファイル(view)に飛ばす。またviewの中で使う変数を定義したりする。

viewでやっている事
ここはHTMLファイルでブラウザでなにを見せるかを書いている。HTMLだけでは変数や構文を扱えないので、rubyやphpを組み込んでいる。

主なコマンド

rails new アプリケーション名:アプリ作成
rails controller コントローラー名 view名: コントローラーとビュー作成

それぞれについて認知しておきたいこと

rootingでの注意

railsでは、ルーティングの中で決めたpathを文字として扱う事ができる
例 /help→help_path

他にも省略したり、特徴的な書き方をすることもある
例 @user→user_url(@user)→/user/:id

またroutingで書かれる移行の指示を一括で提供することができる。

config/routes.rb
Rails.application.routes.draw do
  root   'static_pages#home'
  .
  .
  .
  resources :users
end

これはuserに関して、viewつなげるroot情報が網羅的に入っている。詳しくはRuby on Rails チュートリアル

controllerでの注意

・railsではcontrollerから別の場所に飛ばせる変数は頭に@がついた変数だけ。
・またUsersコントローラーのshowアクションのrootingはusers/:idとして定義されている。そのためshowアクションでURLにあるidを取り出して処理をする。

app/controllers/users_controller.rb
class UsersController < ApplicationController

  def show
    @user = User.find(params[:id]) #rootingにあるidをprramsで取り出して使用して、userを探している。
  end

・form_tagやform_forで送られてきた値を取得するときは、params[送られてきた変数]をする。送られてきた変数の中身がからの時はparams[送られてきた変数]は空として扱う。

app/controllers/users_controller.rb
class UsersController < ApplicationController
  .
  .
  .
  def create
    @user = User.new(params[:user]) #form入力内容を示す:userを取り出している。
    #厳密にはこれではダメ。ストロングパラメーターにしないといけない。
  end
end

・controllerのアクション内でリダイレクトを指示することがある。(アクション名のつくHTMLファイルに飛ばずに、別のrootingに飛ばしてしまうこと)

viewでの注意

お作法としてapplication.htmlには統一レイアウトを置き
yeildという場所を書き、そこに全てのviewの内容が反映される。

app/views/layouts/application.html.erb
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag    'application', media: 'all',
                               'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application',
                               'data-turbolinks-track': 'reload' %>
    <%= render 'layouts/shim' %>
  </head>
  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <%= yield %>
      <%= render 'layouts/footer' %>
    </div>
  </body>
</html>

同様に全てのviewは、別のviewファイルから読みだして自身のviewに反映させてもいい

<%= render '反映させたいviewの場所' %>

これをパーシャルを追加するという。

データベースの取り扱い

①まずデータベースを変更するためのマイグレーションファイルを作る。
rails g model モデル名 列名:種類

モデル名は何用のデータなのかということ、単数形で書くこと。
例 User
列(カラム)はモデルの何のデータかを示す。
例 name
種類はカラムのデータをどんな種類で保存するか
例 string つまり文字列

このコマンドで何が作成されるのか

・モデルのファイルができる。
そこでどんなデータなら保存するなどの制限を記述したりする。

・モデル名(複数形)という名前のマイグレーションファイルができる。
dbを変更する命令が書かれている。
こいつをmigrateすることでdbに行列を作れるようになる。

②rails db : migrate
マイグレーションファイルに書いてある指示を実行して行列(データ)をdbに作成できる

なぜマイグレーションファイルがあるか。

ファイルならgitで管理できるから!データベースは人それぞれ違うので、管理できないから。

モデルファイルでは何をするのか

どんなデータなら保存するなどの制限を記述。
例 存在するか、文字数が多すぎないか、フォーマットがあっているか?
またモデルファイルの中で関数を定義して、データであるインスタンスの関数としてcontrollerで使用できる。

app/models/user.rb
class User < ApplicationRecord
  validates :name,  presence: true, length: { maximum: 50 }
  validates :email, presence: true, length: { maximum: 255 }

  def adult_check #Userモデルの関数
    if self.age >= 20  
       return "お酒が飲めます"
    end
  end 
end
データ保存のイメージ

modelというクラスがありカラムという変数をたくさん持っている。

そこからインスタンスを作り、そのインスタンスにあった値を各カラムに代入して保存する。

モデルAにモデルBを従属させたい時(二つのモデルを繋げて)

以下のようなコードを書くと
モデルAインスタンスはたくさんのモデルBインスタンスを持つことができる。

app/models/micropost.rb
class Micropost < ApplicationRecord
  belongs_to :user
end
app/models/user.rb
class User < ApplicationRecord
  has_many :microposts
end

この後に以下のように
A.Bの複数形.Bの関数or変数を使用することができる。

def setup
    @user = users(:Tsuyoshi)
    @micropost = @user.microposts.build(content: "Hello")
  #これでTsuyoshiはHelloという投稿をする
end

ログインはどうやる?

ログイン画面で入力されたメアドとパスワードを持つデータがあるか探す。

あればログインできるようにする。
そのためにsession変数の中にuser.idの値を入れる!
session変数の値はブラウザ内でなら不変で存在できるので、画面遷移しても存在できるため、ログインしているユーザーのためのページが閲覧できる。ログアウトする時はsession変数の値を空にするか、ブラウザを閉じる。

ログインに関する補足

*sessionとcookieの違いはsessionはブラウザを閉じれば値が破棄されるがcookieは破棄されない。

*ログインやログアウトを命ずる関数(あるいはその中で使うcookiesをいじる関数)はappのコントローラーhelperの中で定義したりする

*ログインしていないユーザーがいじってはいけないページを設定したければ、beforeactionで、権限を確認して、アクションまで到達させるかを見極める。
注意: beforeactionはcontroller内でのみ発動できる
全てのcontrollerのアクションで発動させたければ、controllerの親玉であるapplicationcontrollerで発動してやる

*ログインテストなどでテスト環境のデータベースにデータを置きたい時はfixturesに記述する

*ログインする前にログインしないといじれないページにアクセスした時
ログインした後に直接ログイン前にアクセスしたページに飛ばす工夫

アクセス失敗時に変数にそのurlを代入

ログインしたらそこに飛ばせるようにする

飛べば、変数の値を空にする

その他、補足

ストロングパラメーター

セキュリティーのためにUserのインスタンスに発生させることが多い。インスタンス作成時にどんな引数も受けとってしまうことを防ぐ。これを行わないと、管理者権限があるかないかを示す変数の値を引数として渡し変更されてしまうので、どんなインスタンスでも管理者権限を持てるようになってしまう。

app/controllers/users_controller.rb
@user = User.new(params[:user]) #form入力内容を示す:userを取り出している。

app/controllers/users_controller.rb
class UsersController < ApplicationController
  .
  .
  .
  def create
    @user = User.new(user_params)
  end

  private #外部アクセスを制限

  #user_paramsとは:userの中身をpramsで紐解いているが、入力が許されているのはname,email,password,password_confirmationだけという意味
    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end 
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

railsで学ぶサーバーサイド(rails チュートリアルで学んだことをまとめてみました)

この記事の説明

この記事ではrails チュートリアルで学んだことを私なりにまとめてみました。
理解の浅い部分がありますので、間違いがある場合はどうぞご教授ください。

routingとcontrollerとview

rails newコマンドでアプリを作成するとroutingとcontrollerとviewが出来る。これらを使ってURLでデータを扱った処理ができる。

routingでやっている事
任意のURLに対してどのcontrollerのどの関数に飛ばすかを決める。

controllerでやっている事
controllerの中には複数の関数名があり、routingからの指示を受けてその関数名を持つHTMLファイル(view)に飛ばす。またviewの中で使う変数を定義したりする。

viewでやっている事
ここはHTMLファイルでブラウザでなにを見せるかを書いている。HTMLだけでは変数や構文を扱えないので、rubyやphpを組み込んでいる。

主なコマンド

rails new アプリケーション名:アプリ作成
rails controller コントローラー名 view名: コントローラーとビュー作成

rootingでの注意

railsでは、ルーティングの中で決めたpathを文字として扱う事ができる
例 /help→help_path

他にも省略したり、特徴的な書き方をすることもある
例 @user→user_url(@user)→/user/:id

またroutingで書かれる移行の指示を一括で提供することができる。

config/routes.rb
Rails.application.routes.draw do
  root   'static_pages#home'
  .
  .
  .
  resources :users
end

これはuserに関して、viewつなげるroot情報が網羅的に入っている。詳しくはRuby on Rails チュートリアル

controllerでの注意

・railsではcontrollerから別の場所に飛ばせる変数は頭に@がついた変数だけ。
・またUsersコントローラーのshowアクションのrootingはusers/:idとして定義されている。そのためshowアクションでURLにあるidを取り出して処理をする。

app/controllers/users_controller.rb
class UsersController < ApplicationController

  def show
    @user = User.find(params[:id]) #rootingにあるidをprramsで取り出して使用して、userを探している。
  end

・form_tagやform_forで送られてきた値を取得するときは、params[送られてきた変数]をする。送られてきた変数の中身がからの時はparams[送られてきた変数]は空として扱う。

app/controllers/users_controller.rb
class UsersController < ApplicationController
  .
  .
  .
  def create
    @user = User.new(params[:user]) #form入力内容を示す:userを取り出している。
    #厳密にはこれではダメ。ストロングパラメーターにしないといけない。
  end
end

・controllerのアクション内でリダイレクトを指示することがある。(アクション名のつくHTMLファイルに飛ばずに、別のrootingに飛ばしてしまうこと)

viewでの注意

お作法としてapplication.htmlには統一レイアウトを置き
yeildという場所を書き、そこに全てのviewの内容が反映される。

app/views/layouts/application.html.erb
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag    'application', media: 'all',
                               'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application',
                               'data-turbolinks-track': 'reload' %>
    <%= render 'layouts/shim' %>
  </head>
  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <%= yield %>
      <%= render 'layouts/footer' %>
    </div>
  </body>
</html>

同様に全てのviewは、別のviewファイルから読みだして自身のviewに反映させてもいい

<%= render '反映させたいviewの場所' %>

これをパーシャルを追加するという。

データベースの取り扱い

①まずデータベースを変更するためのマイグレーションファイルを作る。
rails g model モデル名 列名:種類

モデル名は何用のデータなのかということ、単数形で書くこと。
例 User
列(カラム)はモデルの何のデータかを示す。
例 name
種類はカラムのデータをどんな種類で保存するか
例 string つまり文字列

このコマンドで何が作成されるのか
・モデルのファイルができる。
そこでどんなデータなら保存するなどの制限を記述したりする。

・モデル名(複数形)という名前のマイグレーションファイルができる。
dbを変更する命令が書かれている。
こいつをmigrateすることでdbに行列を作れるようになる。

②rails db : migrate
マイグレーションファイルに書いてある指示を実行して行列(データ)をdbに作成できる

なぜマイグレーションファイルがあるか。

ファイルならgitで管理できるから!データベースは人それぞれ違うので、管理できないから。

モデルファイルでは何をするのか

どんなデータなら保存するなどの制限を記述。
例 存在するか、文字数が多すぎないか、フォーマットがあっているか?
またモデルファイルの中で関数を定義して、データであるインスタンスの関数としてcontrollerで使用できる。

app/models/user.rb
class User < ApplicationRecord
  validates :name,  presence: true, length: { maximum: 50 }
  validates :email, presence: true, length: { maximum: 255 }

  def adult_check #Userモデルの関数
    if self.age >= 20  
       return "お酒が飲めます"
    end
  end 
end
データ保存のイメージ

modelというクラスがありカラムという変数をたくさん持っている。

そこからインスタンスを作り、そのインスタンスにあった値を各カラムに代入して保存する。

カラムにインデックスをつけると

rails g migrationで任意のカラムにインデックスを加えるマイグレーションファイルを作る(emailカラムに使われる事が多い)

rails db migrateでデータに反映
emailカラムにインデックスが付く→これによって検索が速くなる(インデックスのおかげでアルファベット順に並べ替えたりできるから)

モデルAにモデルBを従属させたい時(Userがたくさん投稿できるようにしたい)

以下のようなコードを書くと
モデルAインスタンスはたくさんのモデルBインスタンスを持つことができる。

app/models/micropost.rb
class Micropost < ApplicationRecord
  belongs_to :user
end
app/models/user.rb
class User < ApplicationRecord
  has_many :microposts, dependent: :destroy
  #dependent: :destroyをつけると主のインスタンスが消されるとそれに従属した投稿も消されるのでuserのインスタンスが消えるとそこに従属していたmicropostも消える。
end

この後に以下のように
A.Bの複数形.Bの関数or変数を使用することができる。

def setup
    @user = users(:Tsuyoshi)
    @micropost = @user.microposts.build(content: "Hello")
  #これでTsuyoshiはHelloという投稿をする
end

ログインはどうやる?

ログイン画面で入力されたメアドとパスワードを持つデータがあるか探す。

あればログインできるようにする。
そのためにsession変数の中にuser.idの値を入れる!
session変数の値はブラウザ内でなら不変で存在できるので、画面遷移しても存在できるため、ログインしているユーザーのためのページが閲覧できる。ログアウトする時はsession変数の値を空にするか、ブラウザを閉じる。

cookiesとsession

sessionとcookieの違いはsessionはブラウザを閉じれば値が破棄されるがcookieは破棄されないこと。

cookies保存法
記憶トークンを作る
トークンとはPCがランダムに作ったパスワードみたいなもの(普通のパスワードは人間が考えて作るけど)

記憶トークンを暗号化する(記憶トークンのハッシュ値をデータベースに保存するってこと)

それをデータベースに保存する

ブラウザのcookies(これはテキストファイル)の中に
signedで暗号化したユーザーIDと
記憶トークンのハッシュ値を有効期限付きで保存する

再度ブラウザを開いた時に
cookiesに保存した暗号化したIDの暗号化を解く

解いたIDであるユーザーをdbから探し、そこに保存されている記憶トークンのハッシュ値とcookiesが所有している
記憶トークンのハッシュ値が一致していればそのユーザーを変数userとして定義する

ログインを許可する
ログイン処理の中には
session(:user_id) = user_idがあるので
sessionに値が入り、画面遷移してもログインしているアカウント用のページを返すようにする

cookies導入した後にログアウトすると適切にログアウトする方法

cookiesの中身を空にする
sessionの中身を空にする
変数current userをnilにする

ログインに関する補足

*ログインやログアウトを命ずる関数(あるいはその中で使うcookiesをいじる関数)はappのコントローラーhelperの中で定義したりする

*ログインしていないユーザーがいじってはいけないページを設定したければ、beforeactionで、権限を確認して、アクションまで到達させるかを見極める。
注意: beforeactionはcontroller内でのみ発動できる。

  before_action :logged_in_user, only: [:edit, :update] #edit,updateアクション実行の前にlogged_in_userを発動。
  .
  .
  .
  private

    # ログインされているかを確認
    def logged_in_user
      unless logged_in?
        flash[:danger] = "Please log in."
        redirect_to login_url
      end
    end
end

全てのcontrollerのアクションで発動させたければ、controllerの親玉であるapplicationcontrollerでbefore_actionを発動してやる

*ログインテストなどでテスト環境のデータベースにデータを置きたい時はfixturesに記述する。
詳しくはRuby on Rails チュートリアル

*ログインする前にログインしないといじれないページにアクセスした時
ログインした後に直接ログイン前にアクセスしたページに飛ばす工夫

アクセス失敗時に変数にそのurlを代入

ログインしたらそこに飛ばせるようにする

飛べば、変数の値を空にする

アカウントの有効化(新規登録などで行う)

まずUsersのtableデータに以下のカラムを追加する。

*有効化しているかいないか(初期状態は無効にしておく)
*有効化トークン暗号化版
*いつ有効化されたか


行のモデルファイルにbefore関数を使って、
ユーザのインスタンスが作られる前に、
有効化トークンをpcに作らせて暗号化し、それをユーザーのdbに保存する

ユーザーにメールを送信する(appの中にあるmailerとそれに対応するアクションが送信をしてくれる。
rails g mailer メイラー名 アクション名で作れる)

メールの中にはリンクがあり、そのリンクにはあらかじめ引数としてユーザーのメアド、有効化トークンが組み込まれている

つまりリンクを押すだけでappにメアドと有効化トークンを送る、そしてdbに保存された有効化トークンと同じか比べる

同じならば、有効化にしてログインさせる(新規登録完了)

次回からのログインでは
emailとpasswordが認証され、有効化がtrueならばログイン状態にする

メールの送り方

user_mailerの中で、誰にを引数に取り、誰々にメールを送る関数を作る

ユーザーの行モデルの中で
user_mailerで定義したメール送信関数を使って
インスタンスユーザーが自身のメールアドレスにメールを送るという関数を作る

その関数を必要に応じてコントローラーで使う

rails g mailer メイラー名 アクション名 で何ができるのか

名前のついたメイラー(controller みたいなもの)
→別のコントローラーから指示があれば対応したメールを送る
この中にアクションがある
役割は上に書いてある通り

アクション名のhtmlファイルとアクション名のtextファイル
→メールの内容が入っている。メイラーで定義された変数を読み出す

上のアクション名のコントローラー
→メールアドレスのリンクが押された処理をするためのコントローラー

testの中にメイラー名のpreviewファイル
→中にアクション名の関数とそれに対応したリンクがある
→関数の中でユーザーをつくりメールを送信する
→対応したリンクにつなぐとメールが見れる
テストのために行う

previewの使い方

まずブラウザでメール内容を見るために
config/environments/developmentでメールを送るための設定をする

previewの中の関数で
メールで使う変数やメール送信の命令を記述する

対応したurlにつなぐとみれる

またpreviewの実行をテストをする時は
テストのための設定もconfig/environments/testでやってやる

twitterの独特の構造

ここについては未完成

フォローとフォロワーの関係構築
フォロしているとフォロされているを有効にするには

そのユーザーとの関係性を保存するdbを作る。
このdbはuserの行モデルに従属する形にする。

またこの時のhas_many: 〜 , class_name:子行モデル, foreign_key:A
にする事で
user.〜.何かという命令関数を作ることができる。

引数を使ってAにキーを保存するように、フォローしたされたの関係を保存できたり。

ユーザーがフォローしている人、フォロワーを把握するためにする従属

ユーザーモデルの中でhas_many A through B source C

前提としてユーザーがBを従えている時
BはCを複数持つことができる。
そしてその複数形の事をuser.Aとする!

フォローしている人の投稿だけ見るようにするには

has_many A through B source C
でできたfollowing(自分がフォローしている人の複数形)をmicropostsに保存して見せるようにする

その他、補足

ストロングパラメーター

セキュリティーのためにUserのインスタンスに発生させることが多い。インスタンス作成時にどんな引数も受けとってしまうことを防ぐ。これを行わないと、管理者権限があるかないかを示す変数の値を引数として渡し変更されてしまうので、どんなインスタンスでも管理者権限を持てるようになってしまう。

app/controllers/users_controller.rb
@user = User.new(params[:user]) #form入力内容を示す:userを取り出している。

app/controllers/users_controller.rb
class UsersController < ApplicationController
  .
  .
  .
  def create
    @user = User.new(user_params)
  end

  private #外部アクセスを制限

  #user_paramsとは:userの中身をpramsで紐解いているが、入力が許されているのはname,email,password,password_confirmationだけという意味
    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end 
end
クエリとエスケープ

どちらもurlに関する事

クエリとは
urlの最後に?条件と書く事で
?以下の条件に正しく対応していればurlに繋ぐ

エスケープとは
クエリの条件で使われることが多く
urlには書き込めない文字を別の文字列で表現すること

ex @ → %40

パスワード再設定のやり方

ユーザーがpassword再設定をリクエスト

入力されたメールアドレスからユーザーを見つける

再設定用トークンとそれに対応する暗号化された再設定用トークンを作る

暗号化された再設定用トークンはdbに保存して
メルアドにメルアドと再設定トークンが組み込まれたリンクを送信する

クリックされれば
リンクに組み込んだ再設定トークンとdbに保存した再設定トークンが同じか確認する

okならばパスワード変更画面に誘導

パスワード変更が完了すれば
ログインし、dbに保存された暗号化された再設定用トークンを空にする

写真のアップロードの仕方

uploaderのgem をダウンロードする

rails g uploader 〜でuploaderを作る
rails g migration ~でtableにに写真を保存する場所を示す
例 rails generate migration add_picture_to_microposts picture:string

rails db:migrateで写真を保存したいモデルのなかで写真を保存するためのカラムを作る

写真を保存したいモデルファイルで、保存したいカラムに対してuploaderが働きかけるようにする
詳しくはRuby on Rails チュートリアル

uploaderファイルの中には
アップする写真がどんな種類か見分ける、などの指示が書かれている

それを使ってviewのなかでoo種ならば写真を載せるとかにする

Ajaxとは

サーバーとの通信でデータを受け取り、ページを書き換える時に、
処理をするために別の場所に飛んで、処理後に再度今のページの中身を読み込んで戻ってくるのは処理が多くて遅くなる

Ajaxを使えば今のページのままで処理が行える(今のページの再読み込みをせずに処理できる)

Ajaxの例
.load→サーバーのHTMLを読み出す
.getや.post→送ったパラメータを使ってサーバーで処理をしてその結果を返してもらう。どちらも処理結果を得られるが、getの場合は処理結果を得るだけ、postは結果も得るがサーバー側のデータも書き換えも行う?

.getや.postの関数の中では処理してもらうサーバーファイルと送るパラメータと結果取得後の何をするかを書く

Ajaxの注意
Ajaxは非同期である。つまりその処理が完了する前に次の処理移る。


①Ajaxでサーバー側のAファイルを読み込む
②Aファイルの文字色を変える
単純にこの順番に命令を書くとファイルは読み込まれるが色は変わらない。

Ajax命令の後に、その中身に対する命令をしたいならばコールバック関数を使ってやる。

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

FactoryBotでassociationを持つモデルをbuildするもinvalidになる

(Rails Tutorialなんかで出てくる)Relationshipモデルのrspecのテストではまった。いや、テスト以前にFactoryBotで作ったRelationshipモデルを読み込むも、それがinvalidだという問題から抜けきれなかった。以下順々に何が起こったのかを記録。

今回のRelationshipモデル

カラムはid, follower_id, followed_id

app/modles/relationship.rb
class Relationship < ApplicationRecord
  belongs_to :follower, class_name: 'User'
  belongs_to :followed, class_name: 'User'
  validates :follower_id, presence: true, uniqueness: { scope: [:followed_id] }
  validates :followed_id, presence: true
end

Rspecでエラーが出るまで

Relationship has many Usersの関係があるため、Relationshipのテストには、以下の2つのFactoryBotを使う。

  • UserモデルのFactoryBot
  • RelationshipモデルのFactoryBot
spec/modles/user.rb
FactoryBot.define do
  factory :user do
    email { 'test@test.com' }
    account_id { 'testtest' }
    name { 'tester' }
    password { 'password123' }
  end
end

このFactoryから作られるUserモデルを用いてRealtionshipを作りだすFactoryを定義。

spec/factories/relationship.rb
FactoryBot.define do
  factory :relationship do
    association :follower, factory: :user
    # email, account_idは重複しないようにoverwrite
    association :followed, factory: :user, email: 'another@test.com', account_id: 'another'
  end
end

これをspecファイルから呼び出し、Realtionshipモデルを作る。まずは属性値のオーバーライトなしで作られるモデルがvalidであることの確認が必要。

spec/models/relationships_spec.rb
require 'rails_helper'

RSpec.describe Relationship, type: :model do
  it 'creates a valid relationship model' do
    r = build(:relationship)
    expect(r).to be_valid
  end
end

これを$ rspecで実行してみると...

実行結果
Failures:

  1) Relationship creates a valid relationship object 
     Failure/Error: expect(r).to be_valid
       expected #<Relationship id: nil, follower_id: nil, followed_id: nil, created_at: nil, updated_at: nil> to be valid, but got errors: Follower can't be blank, Followed can't be blank
     # ./spec/models/relationship_spec.rb:6:in `block (2 levels) in <main>'

打開策

テストファイルを以下のようにr = build(:relationship)r = create(:relationship)に書き換えたところ、エラーは出なかった。

これは、rを永続化していればrはvalidになるということを意味している。

spec/models/relationships_spec.rb
require 'rails_helper'

RSpec.describe Relationship, type: :model do
  it 'creates a valid relationship model' do
    r = create(:relationship)
    expect(r).to be_valid
  end
end

参考

StackOverflowによると、In Rails 5, associations defined as belongs_to are required by default. So when you are checking expect(build(:relationship)).to be_valid, the valid? call is returning false because you don't have a user set.(一部今回の状況に合うよう加筆)

とのこと。

つまり今回の問題はモデルの永続化に関係がありそう。

おまけ

Rails Consoleで遊んでいると以下の現象に気が付いた。要約すると...

  • 永続化されないUserモデルである u1, u2 を用いてRealtionshipモデル r を作ってもそれはsaveできない
  • u1, u2を永続化したとしても、先程のrはsaveできない
  • u1, u2の永続化の後、それらをrの属性に再代入することでrはsaveできるようになる
irb(main):077:0> u1 = User.new(email: 'test@test.com', account_id: 'testtest', name: 'user1', password: 'password')
=> #<User id: nil, email: "test@test.com", account_id: "testtest", name: "user1", is_male: nil, height: nil, weight: nil, comment: nil, created_at: nil, updated_at: nil>
irb(main):078:0> u2 = User.new(email: 'test2@test.com', account_id: 'testtest2', name: 'user2', password: 'password')
=> #<User id: nil, email: "test2@test.com", account_id: "testtest2", name: "user2", is_male: nil, height: nil, weight: nil, comment: nil, created_at: nil, updated_at: nil>
irb(main):079:0> r = Relationship.new(follower: u1, followed: u2)
=> #<Relationship id: nil, follower_id: nil, followed_id: nil, created_at: nil, updated_at: nil>
irb(main):080:0> r.save
=> false
irb(main):081:0> u1.save
=> true
irb(main):082:0> u2.save
=> true
irb(main):083:0> r.save
=> false
irb(main):084:0> r = Relationship.new(follower: u1, followed: u2)
=> #<Relationship id: nil, follower_id: 1, followed_id: 2, created_at: nil, updated_at: nil>
irb(main):085:0> r.save
=> true
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsでタブやナビゲーションをカレント表示する方法

Rails管理画面アプリのナビゲーションを作成するにあたって、
現在ページのカレント表示のやり方で簡単な方法が分かったので紹介します。

例)トップページの場合

まずはトップページを例とします。
トップページへのヘルパーメソッドはadmin_path(/admin)とします。

_navbar.html.erb
<ul class="nav">
  <li class="nav-link <%= 'active' if request.path == admin_path %>"><a href="<%= admin_path %>">トップページ</a></li> #ここの行に注目
  <li class="nav-link"><a href="#">リンク1</a></li>
  <li class="nav-link"><a href="#">リンク2</a></li>
</ul>

解説

request.pathで現在のパスがわかるので、これとadmin_pathのヘルパーメソッドを比較し、
trueだった場合はactiveのクラスを付与するようにしています。
(if request.path == admin_path の箇所)

例)トップページ以外の場合

次はトップページ以外を例とします。
前提としてroutes.rbにはadmin_usersresourcesとして設定していること。
トップページ以外へのヘルパーメソッドの例はadmin_users_path(/admin_users)とします。

routes.rb
Rails.application.routes.draw do
  resources :admin_users
end
_navbar.html.erb
<ul class="nav">
  <li class="nav-link <%= 'active' if request.path == admin_path %>"><a href="<%= admin_path %>">トップページ</a></li>
  <li class="nav-link <%= 'active' if request.path.starts_with?(admin_users_path) %>"><a href="<%= admin_users_path %>">ユーザー一覧</a></li> #ここの行に注目
  <li class="nav-link"><a href="#">リンク2</a></li>
</ul>

解説

request.pathで現在のパスがわかるので、これとadmin_users_pathのヘルパーメソッドをstarts_with?メソッドで先頭の文字列をチェックし、
trueだった場合はactiveのクラスを付与するようにしています。
(if request.path.starts_with?(admin_users_path) の箇所)

参考にさせていただいたURL

Rails4・Rails5 で現在のURLを取得する。

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

Rubyを使った簡単な自動計算bot

ruby 制作物

すごく簡単なものですがTECH::CHAMP基礎カリキュラム中にrubyのメソッドの使い方などをアウトプットしたいと思い。作ってみた自動で1日の消費カロリー消費の計算をし増量、減量、キープする際の適性摂取カロリーを計算をしてくれる物です。すごく簡単な物ですがいい練習になりました!変数名などはすごく適当にしてしまいました、、

def bmr(humans)
  sports = "一週間の運動量を教えてください\n[1]全く運動をしない。\n[2]二三日程度運動をする。\n[3]ほぼ毎日運動をする。"
  mind = "体重の目標推移を教えてください。\n[1]減量をしたい。\n[2]キープしたい。\n[3]増量したい。"
  puts "名前を教えてください"
  name = gets.chomp
  puts "性別を教えてください\n[1]男性[2]女性"
  sex = rollback(gets.to_i)
  puts "s身長(cm)を教えてください"
  height= gets.to_f
  puts "体重を教えてください"
  weight= gets.to_f
  puts "年齢を教えてください"
  age = gets.to_i
  puts sports
  mom = roll(gets.to_i)
  puts mind
  gem = back(gets.to_i)

  human = {name: name,sex: sex, height: height, weight: weight, age: age, ace: ace(sex, weight, age, height), mom: mom, gem: gem}

  humans << human

end

def back(back)
  sq = "体重の目標推移を教えてください。\n[1]減量をしたい。\n[2]キープしたい。\n[3]増量したい。"
  while back > 3 && back < 1 do
    puts "入力した値は無効な値です。再度入力をお願いします。#{sq}"
    back = gets.to_i
  end
  return back
end

def rollback(rollback)
  while  rollback > 2 do
    puts "入力した性別は無効な性別です。再度入力をお願いします\nあなたの性別を教えてください。\n[1]男性[2]女性"
    rollback = gets.to_i
  end
  return rollback
end

def roll(roll)
  sp = "一週間の運動量を教えてください\n[1]全く運動をしない。\n[2]二三日程度運動をする。\n[3]ほぼ毎日運動をする。"
  while  roll > 3 do
    puts "あなたが入力した運動量は無効な数値です。再度入力をお願いします\n#{sp}"
    roll = gets.to_i
  end
  return roll
end

def ace(sex, weight, age, height)
  if sex == 1
    ace = 10 * weight + 6.25 * height -5 * age + 5
  elsif sex == 2
    ace = 10 * weight + 6.25 * height -5 * age- 161
  end
end

def b(humans)

  humans.each_with_index do |human, index|
    puts "#{index + 1} #{human[:name]}"
  end
  puts "見たい人の番号を入力してください。"
  input = gets.to_i
  human = humans[input - 1]
  if human[:mom] == 1
    kr = human[:ace] * 1.2
    puts "一日の消費カロリーは#{kr.round(1)}キロカロリーです"
  elsif human[:mom] == 2
    kr = human[:ace] * 1.55
    puts "一日の消費カロリーは#{kr.round(1)}キロカロリーです"
  elsif human[:mom] == 3
    kr = human[:ace] * 1.725
    puts "一日の消費カロリーは#{kr.round(1)}キロカロリーです"
  end
  if human[:gem] == 1
    krc = kr * 0.8
    puts "運動量を変えずに減量するには#{krc.round(1)}キロカロリー以上1日に食べてはいけません。"
  elsif human[:gem] == 2
    krc = kr * 1
    puts "運動量を変えずに体重をキープするには#{krc.round(1)}キロカロリー1日に食べてください。"
  elsif human[:gem] == 3
    krc = kr * 1.2
    puts "運動量を減らす。もしくは#{krc.round(1)}キロカロリー以上1日に食べてください。"
  end

end

humans = []

while true
  puts '選択してください'
  puts '[0]登録する'
  puts '[1]データを確認する'
  puts '[2]終了する'
  input = gets.to_i

  if input == 0
    bmr(humans)
  elsif input == 1
    b(humans)
  elsif input == 2
    exit
  else
    puts '無効な値です'
  end
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

『Ruby』簡単な適性摂取カロリー自動計算bot

はじめに

すごく簡単なものですがTECH::CHAMP基礎カリキュラム中でrubyのメソッドの使い方などをアウトプットしたいと思い。作ってみた自動で1日の消費カロリー消費の計算をし増量減量キープする際の適性摂取カロリーを計算をしてくれる物です。すごく簡単な物ですがいい練習になりました!変数名などはすごく適当にしてしまいました、、

環境

  • macOS Catalina  バージョン10.15.4
  • Ruby バージョン2.5.1

制作物

def bmr(humans)
  sports = "一週間の運動量を教えてください\n[1]全く運動をしない。\n[2]二三日程度運動をする。\n[3]ほぼ毎日運動をする。"
  mind = "体重の目標推移を教えてください。\n[1]減量をしたい。\n[2]キープしたい。\n[3]増量したい。"
  puts "名前を教えてください"
  name = gets.chomp
  puts "性別を教えてください\n[1]男性[2]女性"
  sex = rollback(gets.to_i)
  puts "s身長(cm)を教えてください"
  height= gets.to_f
  puts "体重を教えてください"
  weight= gets.to_f
  puts "年齢を教えてください"
  age = gets.to_i
  puts sports
  mom = roll(gets.to_i)
  puts mind
  gem = back(gets.to_i)

  human = {name: name,sex: sex, height: height, weight: weight, age: age, ace: ace(sex, weight, age, height), mom: mom, gem: gem}

  humans << human

end

def back(back)
  sq = "体重の目標推移を教えてください。\n[1]減量をしたい。\n[2]キープしたい。\n[3]増量したい。"
  while back > 3 && back < 1 do
    puts "入力した値は無効な値です。再度入力をお願いします。#{sq}"
    back = gets.to_i
  end
  return back
end

def rollback(rollback)
  while  rollback > 2 do
    puts "入力した性別は無効な性別です。再度入力をお願いします\nあなたの性別を教えてください。\n[1]男性[2]女性"
    rollback = gets.to_i
  end
  return rollback
end

def roll(roll)
  sp = "一週間の運動量を教えてください\n[1]全く運動をしない。\n[2]二三日程度運動をする。\n[3]ほぼ毎日運動をする。"
  while  roll > 3 do
    puts "あなたが入力した運動量は無効な数値です。再度入力をお願いします\n#{sp}"
    roll = gets.to_i
  end
  return roll
end

def ace(sex, weight, age, height)
  if sex == 1
    ace = 10 * weight + 6.25 * height -5 * age + 5
  elsif sex == 2
    ace = 10 * weight + 6.25 * height -5 * age- 161
  end
end

def b(humans)

  humans.each_with_index do |human, index|
    puts "#{index + 1} #{human[:name]}"
  end
  puts "見たい人の番号を入力してください。"
  input = gets.to_i
  human = humans[input - 1]
  if human[:mom] == 1
    kr = human[:ace] * 1.2
    puts "一日の消費カロリーは#{kr.round(1)}キロカロリーです"
  elsif human[:mom] == 2
    kr = human[:ace] * 1.55
    puts "一日の消費カロリーは#{kr.round(1)}キロカロリーです"
  elsif human[:mom] == 3
    kr = human[:ace] * 1.725
    puts "一日の消費カロリーは#{kr.round(1)}キロカロリーです"
  end
  if human[:gem] == 1
    krc = kr * 0.8
    puts "運動量を変えずに減量するには#{krc.round(1)}キロカロリー以上1日に食べてはいけません。"
  elsif human[:gem] == 2
    krc = kr * 1
    puts "運動量を変えずに体重をキープするには#{krc.round(1)}キロカロリー1日に食べてください。"
  elsif human[:gem] == 3
    krc = kr * 1.2
    puts "運動量を減らす。もしくは#{krc.round(1)}キロカロリー以上1日に食べてください。"
  end

end

humans = []

while true
  puts '選択してください'
  puts '[0]登録する'
  puts '[1]データを確認する'
  puts '[2]終了する'
  input = gets.to_i

  if input == 0
    bmr(humans)
  elsif input == 1
    b(humans)
  elsif input == 2
    exit
  else
    puts '無効な値です'
  end
end

最後に

とても簡単な物ですが自分で考えて関数を作り組み合わせて一つのシステムを作るのはとても楽しいですね:relaxed:

これからも色々な開発を続けてQiitaにてアウトプットしていきたいです:raised_hand_tone1:

最後までご閲覧いただきありがとうございました!!

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