20190804のRubyに関する記事は14件です。

RubyのRailsをMySQLでHerokuにあげてみた

今までの麻雀アプリは一人でずっとやるだけだったので、
もう少しデータ的なのを集められるようになりたいなーと思って
ちょっと改良しました。

https://rubymahjong.herokuapp.com/

↓こんなの
スクリーンショット 2019-07-16 2.51.18.png

みんなのあがり回数とあがりまでの平均ツモ数を表示できるようにしました!

◇開発言語
 ruby 2.6.3
◇サーバーサイドフレームワーク
 ruby on rails 5.2.3
◇フロントエンドフレームワーク
 Vue.js
◇データベース
 MySQL
◇開発OS
 mac
◇IDE
 vscode
◇ソース管理
 GitHub
◇アプリケーションプラットフォーム
 Heroku

忘れないうちにRuby On Railsのインストール手順とかまとめておきます。

Ruby On Railsのインストール

まぁ、Railsのインストール手順とかは色々記事があるのでそれを見ればできます。
自分はRails Girls ガイドを見ながら環境を作りました。(Girlじゃないけど)

基本的にはRails Girls ガイドの通りに作業を進めればいいんですが、
Homebrewのインストールがうまく行きませんでした。
brew doctor を実行してエラーがないか確認したところ

11:05:46 Users $ brew doctor
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: "config" scripts exist outside your system or Homebrew directories.
`./configure` scripts often look for *-config scripts to determine if
software packages are installed, and which additional flags to use when
compiling and linking.

Having additional scripts in your path can confuse software installed via
Homebrew if the config script overrides a system or Homebrew-provided
script of the same name. We found the following "config" scripts:
  /Library/Frameworks/Python.framework/Versions/3.7/bin/python3.7-config
  /Library/Frameworks/Python.framework/Versions/3.7/bin/python3.7m-config
  /Library/Frameworks/Python.framework/Versions/3.7/bin/python3-config
11:05:52 Users $ 

と大量のWarningが…。
原因ですが、「-config」ファイルにPathが通っているとWarningが発生するみたいです。
envコマンドで環境設定確認すると、確かにPythonのPathが通ってますね。

11:12:40 Users $ env | grep PATH
PATH=/Users/itoutoshiya/.rbenv/shims:/Library/Frameworks/Python.framework/Versions/3.7/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

以下のサイトを参考に、
PathからPythonを除外してbrewコマンドを実行するエイリアスを作成しました。
参考:https://www.task-notes.com/entry/20141223/1419324649

alias brew="env PATH=${PATH/\/Library\/Frameworks\/Python.framework\/Versions\/3.7\/bin:/} brew"

コンソールを再起動してbrew doctorを再実行。

11:22:47 ~ $ brew doctor
Your system is ready to brew.

これでHomebrewのインストールはうまくできました!

残りのソフトは、Rails Girls ガイドの通りに実装できました。

MySQLのインストール

MySQLのインストール手順も参考になる記事はたくさんありますね。
自分は以下のサイトが分かりやすかったので参考にさせてもらいました。
https://qiita.com/fuku_tech/items/a380ebb1fd156c14c25b

brew install mysql

railsプロジェクト作成

必要なものは全部インストールできたので、早速
mysqlを利用するRailsプロジェクトを作成します。
といっても、さすがRails。コマンド一つだけですぐにできます。

rails new ./ -d mysql

適当なフォルダにて上記コマンドを実行すればOKです。
VScodeにてコンソールを表示し、上記コマンドを実行すれば必要なファイルが勝手に作成されます。

スクリーンショット 2019-08-01 14.48.40.png

config/database.ymlを確認すると、ちゃんとMySQLを使う設定になってますね!

んで、早速Railsの起動コマンド「rails server」を実行。
デフォルトだと地球儀の絵がTOPページに表示されるはず。
スクリーンショット 2019-08-01 14.37.07.png
うーん失敗。

ただ、以下のメッセージからするに、mysqlに接続できていない感じ。

Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

というか、そもそもsqlサーバーを起動していないので、そりゃDB接続できないよってエラー出ますよね。
ということで、以下コマンドを実行してsqlサーバーを起動。

mysql.server start

スクリーンショット 2019-08-01 14.42.44.png

うん。sqlサーバーは起動できたみたいです。
じゃぁもう一度Railsを起動し画面を確認!
スクリーンショット 2019-08-01 14.51.31.png
まぁ、エラーになるよね。今回のエラー原因は以下の通り。

Unknown database 'project_development'

project_developmentってデータベースがないよーってい言ってますね。
project_developmentは、config/database.ymlで設定している
データベースですね。
mySqlにログインしようとしてもproject_developmentはないからエラーになりますね。
まぁ、project_developmentを作ってないので当たり前ですね。

スクリーンショット 2019-08-01 14.56.18.png

なので、project_developmentを作ります。
ただ、これもRailsを利用して作成することができます。
以下コマンドを実行するだけ!

rails db:create

スクリーンショット 2019-08-01 14.59.33.png

はい!できましたー。
じゃぁもう一度Railsを起動し画面を確認!

スクリーンショット 2019-08-01 15.01.42.png

地球の絵!
見慣れた画像が表示されました!
とりあえず、これで環境面は一通りできました!

テーブル作成

今回は、上がりまでにかかった自摸の回数をテーブルに記録させていきたいと思います。
Railsのコマンドを実行すると、テーブルやそのテーブルにアクセスするための機能(プログラムファイル)
も自動でできます。

rails generate scaffold WonCount name:string wonCount:integer

スクリーンショット 2019-08-01 15.16.49.png

ですが、上記コマンドだけだと肝心のテーブル自身は作成されません。
スクリーンショット 2019-08-01 15.24.24.png

マイグレーションを実行する必要があります。
と言っても難しいことは何もしません。
以下コマンドを実行するだけです。

rails db:migrate

スクリーンショット 2019-08-01 15.21.15.png

スクリーンショット 2019-08-01 15.34.24.png

参考:https://www.sejuku.net/blog/14229

ここまでくれば、後はあがりまでの自摸数をDBに登録するAPIを実装するだけです。

Herokuへのデプロイ

ローカル環境ではうまく出来たので、早速インターネットに公開したいと思います。
サーバーは、またHerokuを使います。便利ですね、PaaS。
参考:http://arfyasu.hatenablog.com/entry/2016/01/11/035101
   https://devcenter.heroku.com/articles/rails4#logging-and-assets

rails_12factor

rails_12factorというのをHeroku上で利用できるように設定します。
rails_12factorは、Herokuでのログを見れるようにするgem(Rubyのライブラリ)です。
Gemfileに以下記述を追加するだけでOKです。

group :production do
  gem 'rails_12factor'
end

Procfile作成

Procfileを作成し、Heroku上での起動コマンドを記述します。
以下記述だけでOK。

web: bundle exec rails server -p $PORT

スクリーンショット 2019-08-04 21.11.10.png

Herokuにアップ

はい。ここまで出来たらHerokuにアップします。
HerokuGitにアップする方法もありますが、
自身のGitHubにアップしたプロジェクトを利用します。

んで、プロジェクトアップロード後にWebサイトを確認。

スクリーンショット 2019-08-04 21.32.05.png

はい。失敗〜。
Herokuのログを見ます。コマンドプロンプトから以下コマンドを実行〜。

heroku logs --tail --app rubymahjong

※「rubymahjong」は、Herokuにアップしたプロジェクト名です。
スクリーンショット 2019-08-04 21.32.11.png

Mysql2::Error::ConnectionError (Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)):

MySQLに接続出来なくてエラーになってますね。

HerokuにMySQLのDB作成

MySQLを利用するにはHerokuにクレジットカードの情報を登録する必要があります。
クレジットカードの登録だけなら無料です。(2019/08/04現在)

クレジットカード登録後、コマンドプロンプトから以下コマンドを実行しMySQLが利用できるようにcleardbアドオンをインストールします。
参考:https://www.yuta-u.com/programing/rails/heroku-mysql-2

heroku addons:create cleardb:ignite --app rubymahjong

スクリーンショット 2019-08-04 22.20.04.png

Heroku上の「Overview」を見ると、MySQLがアドオンされたことが分かりますね。
スクリーンショット 2019-08-04 22.10.24.png

以下コマンドを実行してコンフィグを確認しても、MySQLが追加されたことが分かります。

heroku config --app rubymahjong

【変更前】
スクリーンショット 2019-08-04 22.24.38.png
【変更後】
スクリーンショット 2019-08-04 22.23.52.png

CLEARDB_DATABASE_URLに、デプロイ用のDB接続情報が記載されています。

CLEARDB_DATABASE_URL:     mysql://bfc76098d1b006:90049602@us-cdbr-iron-east-02.cleardb.net/heroku_c287fee3253ccb2?reconnect=true

この情報をDATABASE_URLとして設定します。
ただし、Railsのgemでインストールしているのがmysql2のため、
mysqlではなくmysql2に変更して設定します。

heroku config:set DATABASE_URL=mysql2://bfc76098d1b006:90049602@us-cdbr-iron-east-02.cleardb.net/heroku_c287fee3253ccb2?reconnect=true --app rubymahjong

スクリーンショット 2019-08-04 22.56.06.png

変更後、またコンフィグを確認してみます。
【変更後】
heroku config --app rubymahjong
スクリーンショット 2019-08-04 23.10.33.png
DATABASE_URLが追加されてますね!

この状態でブラウザから画面を確認すると…。
スクリーンショット 2019-08-04 21.32.05.png

エラー。でも、ログの内容は変わってます。
スクリーンショット 2019-08-04 23.16.17.png

ActiveRecord::StatementInvalid (Mysql2::Error: Table 'heroku_c287fee3253ccb2.won_counts' doesn't exist: SHOW FULL FIELDS FROM `won_counts`):

won_countsテーブルがなくてエラーになってますね。

テーブル作成はマイグレーションですね。以下コマンドを実行!

heroku run rails db:migrate --app rubymahjong

スクリーンショット 2019-08-04 23.22.31.png

なんか出来てる感じですね!
早速ブラウザから画面を確認してみます。

スクリーンショット 2019-08-04 23.24.49.png
できました!
きちんとあがり回数をDBに登録し、その結果を出力出来てます!

Herokuって便利ですねー。
Rails+MySQLってかなりのWebサービスで利用されてそうで、
その環境が簡単に作れると色々なことが出来て夢が広がりますね!


今回のプログラムは以下GitHubにあげてます。
https://github.com/kph7m/rubymahjong

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

未経験が現場iOSアプリ開発で出会うRuby関連

どうもみなさんこんにちはiOS青二才です。

未経験でiOS開発現場に入ると、思いの外今まで頑張って技術をあげてきたSwift以外にも様々なものに出会い自分の知見・技術レンジが狭いことに気付きます。
現場に入る前も幅広く開発をしてる人は出会うことがあったり使用したりの経験があると思いますが、私はそんなことはなかったので、「あれ、rubyさん介入してるやんなんやこれ」ってなった物のメモをおきます。

Ruby

  • 日本産のスクリプト言語
  • Webサイト制作に使用
  • Webアプリ制作に使用
  • スマホアプリ開発に使用
  • サーバーサイド開発に使用

まずiOSアプリ開発とRubyとの関係性と知る

色々と掘り下げる前に、iOSアプリ開発に置いてのRubyとの関係性を知るべきだと思いました。
Rubyという言語の一部の特徴は上にあげたものたちですが、サーバーサイド側の処理を担うことが多々あります。
ここでまず一つ、「開発に置いてサーバー連携はrubyで、、、」という繋がり1が生まれます。
そしてMacにはデフォルトでRubyが導入されているのですが、サーバー側処理とか個人開発で使わなきゃ出会いないよね、と思っていたのですがところがどっこい。実は触れてました。

以下で説明するgemですが、実はCocoapodsをインストールする際に使用していたんですね。最近は既存のプロジェクトを改修したりすることばかりで、新規でインストールする機会を逃していたので完全に忘れていました。
よくよく調べてみるとCocoapodsRubyで実装されているらしく、インストールはRuby経由ということになります。

ライブラリ / パッケージ

プロジェクトのreadmeをみるとgem installとかbundle install とかそういうのを見かけることがあります。
調べてみると、gemとはRubyGemsが公開しているRubyのパッケージ管理ツール。とかいろんなところで説明されています。正直、意味がすんなり入ってこなかったので調べました。

まずここで一つはっきりさせておきたいのが
ライブラリ = パッケージ
ということです。
初歩的なことかとは思いますが、新しいものを理解するときに事前に脳内にある知識と説明を照らし合わせたときに少しでも差異があると混乱を招きますので、この際にはっきりさせました。

iOS開発で使用するCocoapods Carthageライブラリ管理ツールと認識していたので、パッケージ管理?また違うもの?っとなってしまったのでここで認識を共通化させたかった次第です。
以下の説明では、同等のものと認識してください。
なおここではライブラリという言葉で統一化します。

Gem

  • RubyGemsが提供するRuby用のライブラリ管理ツール
  • Rubyにおいてgemとはライブラリのこと(太郎さん、花子さんを人間と呼ぶ感じ)
  • ターミナルにてgemコマンドで使用
  • gemコマンドにてビルド、アップロード、ダウンロード、インストールを行う
  • gemfile gemfile.lockというのが作成されるので、gemfile内にライブラリを記載して使用

まずRubyGemsですが、これはそもそものgemを使用できる環境、または管理するシステムです。これを
gemを使用するにはまずそれ自体のインストールから始めます。丁寧なreadmeの場合はだいたいプロジェクトをビルドするまでのフローが書いてあると思いますので、それに従ってください。

こいつがSwiftでいうCocoapodsなどの管理ツールに該当するのではと思います。

参考
https://ja.wikipedia.org/wiki/RubyGems
https://qiita.com/sumyapp/items/5ec58bf3567e557c24d7

bundler

gemの依存関係とバージョンを管理するためのツール。との説明が多いですがこの表現も紐解くと

  • bundlergemの一つ
  • 複数のgemの使用の間で生まれるgemA version1 と gemB version1が上手く動作しない、というのを管理して解消してくれる。
  • gemfile gemfile.lockに準拠して管理
  • gemの管理をする gem、それがbundler

ということになります。bundlerを入れましたら、基本的にはbundle installなどbundlerを介してgem達のインストールを行うのが良いとされているようです。

参考
https://qiita.com/oshou/items/6283c2315dc7dd244aef
https://techacademy.jp/magazine/19840

rbenv

rbenvは、複数のRubyのバージョンを管理してくれて、かつプロジェクトごとのRubyのバージョンを指定して使うことができるツールです。Rubygemsがライブラリ管理ツールだとしたら、こちらはRuby管理ツールとでもいうんですかね。Homebrewなどでインストールして使います。

rbenvRubyのバージョン操作等を行うことがあるかどうかわわかりませんが、だいたいgem bundlerとセットで使用されていることが多いはずです。
ちなみアールベンブとかアールビーエンブという呼び方をするそうです。

まとめ

登場したのは以下のもの達

  • rbenv - Rubyのバージョンを管理
  • gem(RubyGems) - Rubyのライブラリ管理ツール
  • bundler - gem(ライブラリ)の一つで、gemの相互性などの管理をする

iOSアプリ開発でRubyを扱っていた場合ほぼほぼこれらを導入しているケースが多いのかなと思います。
Rubyも完璧にする!というのもまた先が長い話になるので、チーム開発規模のプロジェクトに介入する際は最低限入れておくべき部分かなと感じました。

という訳で、知見を広げるいい経験でした。ビルドの際、何かライブラリ系のエラーにエンカウントした場合はこの辺にも何か原因があるのでは、という発想をもてるようにもなったかと思うのでとてもいい機会だったと思います。

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

『レストラン検索アプリ』の制作過程

はじめに

今回自作アプリを作るのでその過程を残しておきます。(備忘録)
現在制作中なので随時更新されていきます。

目次

※別記事をアップしたら随時更新していきます

アプリ概要

●使用する技術
今回はRails+mysql+heroku+bootstrapでアプリを作っていきます。
AWSと迷いましたが、チーム開発でAWSを触っていたので省略してherokuを使います。
もし時間があれば、AWSに移すかもしれません。

●解決したい事とアプリへの想い
アプリを作ったキッカケは、ミシュランや食べログなど様々な観点の評価軸をもつサイトがあるが、200店舗程実際に食べてみて、どれも当てにならないと思っていました。(勿論個人の好みもあります)
いつもレストランに行ってトライアンドエラーを繰り返す中で、一番信用出来る情報源は、食通や料理人が美味しいと言うお店だと思いました。
なので私が知っている限りですが、それを紹介できるアプリを作ろうと思ったのがきっかけです。
しかし問題として、私自身美味しいお店を広めたくありません!過去好きなお店が突然点数アルゴリズムが変わったとか
なんとかで、予約が取れなくなる苦い経験を何度かしています。(お店側も結構似た想い持ってるところが多いです、、、)
なので、今回は質問に答えて、それに当てはまる1店舗だけを紹介するという形にしました。拘りも出せて一石二鳥です。
●実装内容
内容としては
・DBにレストラン情報と別テーブルでカテゴリーidを保存しておく。
・質問に答えて貰って、該当のカテゴリーidを持つレストランを表示する。

の二点が最低機能で追加機能を入れるなら、
・ユーザー登録機能の実装
・ユーザーが1店舗だけオススメのレストランを登録できる。
・レストラン検索機能
です。
レストランをカテゴリー分けして、表示しようかなと思いました。
別テーブルに保存する事で、カラムを増やせばカテゴリーを増やせるので、後々質問が多様化してカテゴリーの種類が増えた時に困らないかなと思ったのでこの様な仕様にしました。
ユーザー投稿を導入すると、どうしても検索されるレストランの質が落ちてしまう問題があるので、1ユーザー1店舗に
する事で質を保とうとしました。
またユーザーが投稿出来る様になる事で、私の秘蔵情報を公開する必要がなくなる為、レストラン検索機能を追加したいと思います。

まとめ

現状最低機能までを3日で考えています。
またアプリが完成した段階でまとめを書いていきたいと思います

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

Docker for Windowsでrubyファイルを実行する

docker run -it --rm --name ruby -v D:/ユーザー名/workspace/foo_dir:/myapp -w /myapp ruby:2.5 bash

エディタでの編集内容は自動的に反映されるので、コンテナのbashからrubyファイルを実行

各オプションとか

-it bash コンテナのbashに入って操作
--rm 終了時にコンテナを削除(終了したコンテナが溜まっていくので)
--name コンテナの名前を指定
-v ボリュームをマウント(各々のPCのディレクトリ構成に合わせる)
-w Docker内のワーキングディレクトリを指定

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

seedsファイルで西暦テーブルを作りたい

前記事で下の画像のミニアプリを実装しようとした際、optionタグ用に1900年から2019年までのレコードを作ろうとして七転八倒したので共有します。 
qiitad.mov.gif

seeds.rbっていうぐらいだからruby式が使えます

qiita seedデータの投入方法
【Rails入門】seedの使い方まとめ | 侍エンジニア塾ブログ(Samurai Blog)
seedsファイルのデータ投入方法について検索すると出てくる上記のリンクでは下記のようなコードを紹介しています。

(例)seeds.rb
2019.times do |number|
  Year.create(year: number)
end

yearsテーブルのyearカラムに0~2019年までのデータを入れるというコードです。
しかし、このコードだと0年からレコードが作られてしまいます。
僕は、ずっとこの式じゃないとデータ投入ができないという固定観念があったので、これでどうやって1900年からだけ入れればいいんだと悩みました。
しかし、seeds.rbでは普通のruby式が使えるので以下のコードでいけます

(正解)seeds.rb
num = 1900
while num < 2020
  Year.create(year: num)
  num += 1
end

これでもいけます

(正解)seeds.rb
2019.times do |number|
  Year.create(year: number) if number >= 1900 
end

干支も一緒に登録する

話はミニアプリに戻りますが、当初は以下のコードでユーザーの選んだ年に対してリアクションを返そうとしていました。

js
$(function(){
  $(".daigo-main__year__select").on("change", function(){ //optionタグを選択すると発火
    var ment = $(this).val();//値を入手
    if (ment % 12 == 0) {
      $(".demon").text("あなたは申年ですね。これが").fadeIn(4000, function(){
        $(".demon2").text("メンタリ○ムです").fadeIn(2000);//値 ÷ 12のあまりが0なら申年
      });
    }
    else if (ment % 12 == 1) {
      $(".demon").text("あなたは酉年ですね。これが").fadeIn(4000, function(){
        $(".demon2").text("メンタリ○ムです").fadeIn(2000);//値 ÷ 12のあまりが1なら酉年
      });
    }
    else if (ment % 12 == 2) {
      $(".demon").text("あなたは戌年ですね。これが").fadeIn(4000, function(){
        $(".demon2").text("メンタリ○ムです").fadeIn(2000);//値 ÷ 12のあまりが2なら戌年
      });
    }
  });
});
.
.
.
.

書くのがだる過ぎて干支をテーブルに登録できないか考えました。
テーブルに保存していれば下記のコードを全ての干支で使いまわせますからね。

(正解)js
$(function(){
  $(".daigo-main__year__select").on("change", function(){
    var ment = $(this).val();
    $(".demon").text("あなたは"+ ment +"年ですね。これが").fadeIn(4000, function(){
      $(".demon2").text("メンタリ○ムです").fadeIn(2000);
    });   
  });
});

それを可能にしたのが以下のコードです。

seeds.rb
num = 1900
zyuunishi = ["申", "酉", "戌", "亥", "子", "丑", "寅", "卯", "辰", "巳", "午", "未"]
while num <  2020
  Year.create(year: "#{num}", eto: "#{zyuunishi[num % 12]}")
  num += 1
end

配列の中の要素は配列名[番号]で入手することができます。それを利用してjQuery側で行なっていた干支の仕分けを自動でしてくれるというわけです。

完成!

スクリーンショット 2019-08-04 18.32.31.png

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

rails config/routes.rbの基本

1. root

あるドメイン名(例えばlocalhost:3000)でアクセスしたら、指定したcontroller, action, viewに従いブラウザに表示する。
ひとつのドメインに対して一つのrootのみ

config/routes.rb
Rails.application.routes.draw do
  root 'users#index'
end

view : users/index.html.erb
controller : Users
action : index
url欄の表示 : localhost:3000
root_path = 'localhost:3000'
(root_pathは変数として使える)

urlを打ち込みブラウザに表示するまでの流れ
1 「localhost:3000」をurlで検索する
2 config/routes.rbから該当するcontroller, action, viewを読み込む
3 読み込んだcontroller(Users), action(index)で「@name='hoge'」が入る
4 読み込んだviewでcontroller, actionで設定した「@name」をブラウザ上で表示させる

1 「localhost:3000」

2      __________________
      |                  |     controller : Users
      |root 'users#index'|  →  action     : index
      |                  |     view       : users/index.html.erb
      |__________________|
       config/routes.rb

3      _____________         
      |             |       
      |def index    |          
      | @name='hoge'|       → @name = 'hoge'
      |end          |        
      |             |        
      |_____________|         
app/controllers/users_controller.rb

4      ____________
      |<%= @name %>|
      |            |
      |            |
      |            |
      |            |
      |____________|
app/views/users/index.html.erb
       ____________
      | hoge       | 
      |            |
      |            |
      |            |
      |            |
      |____________|
     ブラウザ上の表示結果

2. get

指定したview,controller,actionに従いブラウザに表示する。
rootと違い、urlの表示が「ドメイン名/???」となり、???を変えれば複数の設定が可能

config/routes.rb
Rails.application.routes.draw do
  get '/index', to: 'users#index'
end

view : users/index.html.erb
controller : Users
action : index
url欄の表示 : localhost:3000/index
index_path = 'localhost:3000/index'
(index_pathは変数として使える)

urlを打ち込みブラウザに表示するまでの流れ(ドメインの後ろに「/???」がつく所などがrootと異なる)
1 「localhost:3000/index」をurlで検索する
2 config/routes.rbから該当するcontroller, action, viewを読み込む
3 読み込んだcontroller(Users), action(index)で「@name='hoge'」が入る
4 読み込んだviewでcontroller, actionで設定した「@name」をブラウザ上で表示させる

1 「localhost:3000/index」

2      _______________________________
      |                               |     controller : Users
      |get '/index', to: 'users#index'|  →  action     : index
      |                               |     view       : users/index.html.erb
      |_______________________________|
             config/routes.rb

3      _____________         
      |             |       
      |def index    |          
      | @name='hoge'|       → @name = 'hoge'
      |end          |        
      |             |        
      |_____________|         
app/controllers/users_controller.rb

4      ____________
      |<%= @name %>|
      |            |
      |            |
      |            |
      |            |
      |____________|
app/views/users/index.html.erb
       ____________
      | hoge       | 
      |            |
      |            |
      |            |
      |            |
      |____________|
     ブラウザ上の表示結果

3. post

「form_for」などでdbに新規データを保存する時に使う。(違う事を言っているかもしれません)

config/routes.rb
Rails.application.routes.draw do
  get '/users/new', to: 'users#new'
  post '/users', to: 'users#create'
end
app/controllers/users_controller.rb
class UsersController < ApplicationController
  def new
    @user = User.new
  end
  def create
    user = User.new(user_params)
    #dbはUserテーブルでカラムがname(string), age(integer)を用意しておく
    user.save
    #本当はdbに保存する前に色々と値が正しいのかチェックしたいが今回は省略する
  end

  private

    def user_params
      params.require(:user).permit(:name, :age)
    end
  end
end
app/views/users/new.html.erb
<%= form_for @user do |f| %>
  <%= f.label :名前 %>
  <%= f.text_field :name %>
  <%= f.label :年齢 %>
  <%= f.number_field :age %>
  <%= f.submit "新規作成" %>
<% end %>
form_forなどでdbに新規データを保存するまでの流れ
1 「localhost:3000/users/new」に移動
2 config/routes.rbから該当するgetのcontroller, action, viewを読み込む
3 getなどでform入力画面に移動(newメソッドで「@user」を作成、viewで使用する)
4 「form_for」などでフォームにデータを入力しsubmitボタンを押す(「@user」にデータを入れて投げる)
5 config/routes.rbから該当するpostのcontroller, action, (view)を読み込む
6 読み込んだcontroller(Users), action(create)に従い、投げられた「@user」データをdbに保存する

1 「localhost:3000/users/new」

2      _________________________________
      |                                 |     controller : Users
      |get '/users/new', to: 'users#new'|  →  action     : new
      |                                 |     view       : users/new.html.erb
      |_________________________________|
             config/routes.rb

3      _______________         
      |               |       
      |def new        |          
      | @user=User.new|       → @user = User.new
      |end            |        
      |               |        
      |_______________|         
app/controllers/users_controller.rb

       __________________
      |form_for          |
      |上を参照           |       ← @user = User.new
      |name:             |
      |age:              |   
      |                  |
      |__________________|
   app/views/users/new.html.erb

4      __________________
      |form_for          |
      |上を参照           |
      |name:'yamada taro'|
      |age:105           |       → @user.name = 'yamada taro'    
      |                  |     @user.age = 105
      |__________________|
   app/views/users/new.html.erb

理解していないのだが、form_forで飛ぶurlはデフォルトだと'localhos:3000/users'になるのかな
一応form_forのオプションでurlを指定も出来る。
今回は理解が出来ていないが、app/views/users/new.html.erbのform_forで飛ぶ先は'localhost:3000/users'という事で進める。

5      _________________________________
      |                                 |     controller : Users
      |post '/users', to: 'users#create'|  →  action     : create
      |                                 |     view       : users/new.html.erb
      |_________________________________|
             config/routes.rb

6      _______________         
      |               |       
      |def create     |          
      |  上を参照      |       ← @user.name = 'yamada taro'
      |end            |         @user.age = 105
      |               |        
      |_______________|         
app/controllers/users_controller.rb
           ↓
       @user.name = 'yamada taro'
       @user.age = 105
       ____↓_____
      | / / / / /|
      |/ / / / / |
      | / / / / /|
      |/ / / / / |  
      |_/_/_/_/_/|
           db

4. patch

dbにあるデータを変更し保存する

5. delete

dbにあるデータを削除する

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

Railsのビューテンプレートで使うcontent_forとyieldっぽいものを、Ruby標準のERBだけを使って自作する

まえおき

完全に自分用メモ。
80%くらい同じだけど20%くらい中身が異なるDockerfileを量産したかったので、

Dockerfile.base.erb
FROM <%= yield(:base_image) || 'debian:buster' %>

RUN apt-get update && apt-get -y install ...
RUN ...
RUN ...

<%= yield(:additional_install) %>

USER user
RUN git clone ...
RUN ...
ENV ...

<%= yield(:additional_install_for_user) %>

RUN ...
RUN ...

CMD ["/bin/bash", "start_server.sh"]
ruby2.6/Dockerfile.binding.erb
<% content_for(:base_image, 'ruby:2.6-buster') %>

<% content_for(:additional_install) do %>
RUN apt-get install libxslt-dev libsqlite-dev
<% end %>

みたいな感じのことをやりたかった。

content_forとyieldでテンプレート

ただ、Railsを入れるほどではないので、Rails非依存で(Ruby標準のERBだけで)サクッと自作できないかなと考えた話。

※ 結果だけを知りたい方は「まとめ」のところに一気にどうぞw

Railsの実装を参考にしてみる

content_forはどういう定義になっているかをちらっと見ると、

/actionview/lib/action_view/helpers/capture_helper.rb
      def content_for(name, content = nil, options = {}, &block)
        if content || block_given?
          if block_given?
            options = content if content
            content = capture(&block)
          end
          if content
            options[:flush] ? @view_flow.set(name, content) : @view_flow.append(name, content)
          end
          nil
        else
          @view_flow.get(name).presence
        end
      end

         (中略)

      def content_for?(name)
        @view_flow.get(name).present?
      end

テンプレートのバインディングの方で使われる content_for(:key) は、単純に @view_flow[:key] 的な場所に値を入れているだけだ。

app/views/layouts/application.html.erb などテンプレート側は yield を使うだけなので、ブロックを何らかの形で渡してるんだろう。
https://medium.com/rubyinside/disassembling-rails-template-rendering-2-a99214c6fde8
あたりに詳しく説明があるが、 template.render {|*name| ... } みたいな感じでブロックを渡しているらしい。

複雑なことをしない、自分だけの yield, content_for の要件

今回の自分の用途では

  • yieldは必ず1つのキーを指定される
  • content_forは必ず1つのキーを指定され、valueもしくはブロックで値が指定される
  • content_forを書くファイルには、content_for以外の内容は書かない

という、仕様を削ぎ落とした版のyield/content_forがあればよい。

この程度であれば、Ruby標準のERBでできそうだ。

実コードでいうと

冒頭で書いた Dockerfile.base.erb ruby2.6/Dockerfile.binding.erb を読み込んで、以下のようなRubyスクリプトでいい感じに ruby2.6/Dockerfile ができればいい。

generate_dockerfile.rb
require 'erb'

def apply_template(template_erb, binding_erb)
  # どう書く?
end

template_erb = ERB.new(File.read("Dockerfile.base.erb")) # yield指定がある
binding_erb = ERB.new(File.read("ruby2.6/Dockerfile.binding.erb")) # content_for指定のみがある
dockerfile = apply_template(template_erb, binding_erb)
File.write("ruby2.6/Dockerfile", dockerfile)

さて、apply_templateをどうすればいいんだ?というのがこの記事の本題。

実装するぞ

binding_erbにあるcontent_forの内容をどこかの変数に一時的に持っておく

Railsだとcapture_helper.rbで @view_flow に保持していた。

https://magazine.rubyist.net/articles/0017/0017-BundledLibraries.html をみるとなんとなく想像がつくが、ERBのバインディングはresultメソッドを叩いたその瞬間の評価コンテキストで行われる。(内部でevalをしているだけ)
なので、 binding_erb.result を呼ぶ時には、そこから見える場所に content_for メソッドが定義されている必要がある。

すっっごい雑にやるなら、

generate_dockerfile.rb
def content_for(key, value = nil)
  @binding_values[key] = block_given? ? yield : value
end

def apply_template(template_erb, binding_erb)
  @binding_values = {}
  binding.erb.result(binding)

  puts @binding_values # => { "base_image" => "ruby:2.6-buster", "additional_install" => "..." }
end

こんな感じで、メソッドをもう1つ生やしてみるとよい。中身は、一時的なインスタンス変数にcontent_forで指定されたものをつっこむだけ。
(よいこのみんなはちゃんとクラス化して、プライベートメソッドで content_for を定義しましょう :sweat_smile:

template_erbのyield呼び出し時に、保持していた値を入れ込む

template_erb側で

<%= yield(:hoge) %>

のような指定があった際に、 @binding_values[:hoge] を入れ込むようにする必要がある。

そもそもyieldってなんだっけ?というところがキモなのだが、雑に言うと「ブロックを評価せよ」という命令だ。

yield
def aaa(x)
  puts x, yield(:hoge)
end

data={hoge: 3, fuga: 4}
aaa(1) do |key|
  data[key]
end
# => 1, 3

 

さて、今回は何にブロックを渡せばいいんだっけ?ということになるが、

template_erb.result(binding) do |key|
  @binding_values[key]
end

これでいけるかな?と最初思ってやってみたんだけど、これではうまくいかない。
先にも書いたとおり、 ERB#result は内部的には単なるevalなので、resultを叩いた時点でブロックが見える必要がある、つまり極端に書くと

yield(:hoge)
#template_erb.result(binding)

このyield指定でも正しく動かないといけない。

そう、正解は

generate_dockerfile.rb
def content_for(key, value = nil)
  @binding_values[key] = block_given? ? yield : value
end

def bind_to_template(template_erb)
  # templateの中でyieldされると、bind_to_templateに渡されたブロックが評価される
  template_erb.result(binding)
end

def apply_template(template_erb, binding_erb)
  @binding_values = {}
  binding.erb.result(binding)

  bind_to_template(template_erb) do |key|
    @binding_values[key]
  end
end

だ。

まとめ

ここまでの内容だとまとまらないので、一応クラス化しとこうと思う。

template_binder.rb
require 'erb'

class TemplateBinder
  def initialize(template_erb_string:, binding_erb_string:)
    template_erb = ERB.new(template_erb_string)
    binding_erb = ERB.new(binding_erb_string)
    evaluate_binding(binding_erb)
    @result = evaluate_template(template_erb) do |key|
      @binding_values[key]
    end
  end

  attr_reader :result

  private

  def content_for(key, value = nil)
    @binding_values[key] = block_given? ? yield.strip : value
  end

  def evaluate_binding(binding_erb)
    @binding_values = {}
    # binding_erbの中でcontent_forされたものが @binding_values に保持される
    binding_erb.result(binding)
  end

  def evaluate_template(template_erb)
    # template_erb の中でyieldされると、evaluate_templateに渡されたブロックが評価される。
    template_erb.result(binding)
  end
end

こんなクラスを1つ用意しておけば、

template = 'var1=[<%= yield(:var1) %>], var2=[<%= yield(:var2)%>]'

binding1 = <<~ERB
<% content_for(:var1, 3) %>
ERB

binding2 = <<~ERB
<% content_for(:var1) do %>
    hoge
<% end %>

<% content_for(:var2, :fuga) %>
ERB

TemplateBinder.new(
  template_erb_string: template,
  binding_erb_string: binding1
).result
# => var1=[3], var2=[]

TemplateBinder.new(
  template_erb_string: template,
  binding_erb_string: binding2
).result
# => var1=[hoge], var2=[fuga]

こんな感じで超簡易版 yield / content_for ができる。

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

本番環境でCarrierWaveでS3にアップロードした画像が表示されない時の対処

簡単なチャットアプリケーションを開発する学習で
Rails、Heroku、CarriaWave 、S3を使用して画像をアップロードした際に
以下のようになり、画像が正しく表示されませんでした

image.png
対処した時のことを忘れないように、記事を投稿したいと思います。

原因を探ってみる

まずは、そもそも画像がAmazon S3の管理画面にアップロードできているのかを確認
image.png

問題なくアップロードされていました。

ファイルの記述方法は間違っていないかを確認

carrierwave.rb
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
  config.storage = :fog
  config.fog_provider = 'fog/aws'
  config.fog_credentials = {
    provider: 'AWS',
    aws_access_key_id: Rails.application.secrets.aws_access_key_id,
    aws_secret_access_key: Rails.application.secrets.aws_secret_access_key,
    region: 'ap-northeast-1' 
  }

  config.fog_directory  = 'バケット名'
  config.asset_host = 'https://s3-ap-northeast1.amazonaws.com/バケット名'
end

んー、カリキュラムの指示通りかけてるな

どこが悪いのかさっぱり!

解決方法

キーワードを変えながら検索をしていると同じような問題を書いてあるページを発見しました。
読んでみると、
「原因はconfig/initializers/carrierwave.rb内の、urlの指定が間違っていたからでした。以下のように asset_hostのurlの指定を修正すると、無事にストレージから画像を取得できました。」
(https://remonote.jp/rails-production-carrierwave-s3-error より引用)

carrierwave.rbの書き方ミスとのこと
カリキュラムの書き方を信じるのもよくないですな
以下のようにコードを修正しました

carrierwave.rb
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
  config.storage = :fog
  config.fog_provider = 'fog/aws'
  config.fog_credentials = {
    provider: 'AWS',
    aws_access_key_id: Rails.application.secrets.aws_access_key_id,
    aws_secret_access_key: Rails.application.secrets.aws_secret_access_key,
    region: 'ap-northeast-1' 
  }

  config.fog_directory  = 'バケット名'
  config.asset_host = 'https://s3-ap-northeast1.amazonaws.com/バケット名' #url間違い
  config.asset_host = 'https://バケット名.s3.amazonaws.com' #このように修正

すると、画像を投稿した際に表示されるようになりました。
image.png

ふぅ・・なんとかなりました

最後に

いかがでしたでしょうか?
初投稿なので読みづらかったり分かりづらい点もあるかと思います。
コードの書き方は変わっていくので常に追っていかないといけないなと改めて思いました
同じエラーで悩んでいる人の助けになれたらいいなと思います

参考元

「本番環境でCarrierWaveでS3にアップロードした画像が表示されない問題」の対処
https://remonote.jp/rails-production-carrierwave-s3-error

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

Rspecメモ

Rspecとは

RubyでBDD(振舞駆動開発)を実施するためのテストフレームワーク。

そもそもBDD(振舞駆動開発)とは

  • 振舞とは?
    ユーザーの操作によって実行されるソフトウェアの処理であり機能。
    つまり、対象における「外部から見える変化」「入力・出力」「オブジェクトのメッセージ」などの「対象における何らかのイベントにひも付く外部から見える変化」であると言える。

  • 振る舞いをテストしている」とは何か
    上記のような、「対象オブジェクトにおけるメソッドの組み合わせによって外部から見える変化を記述している」、「対象がどのように何をするかを記述している」、「コミュニケーションパターンを記述している」など

例で言い換えると「ある人物について個々の動作を独立に説明しているけれど、その人物を特徴付ける一連の行動を説明していない」と言い換えることができる。

RSpecとMiniTestの違い

Rspecの特徴

  • DSLで記述→ロジックの自由度が低い
  • 学習コストが高い
  • 採用している企業が多い
  • 情報が豊富
  • 最初からさまざまな機能が入っていて便利

MiniTestの特徴

  • 純粋なRubyで記述→言語機能が使えるため自由度が高い
  • 学習コストが低い
  • Rails標準のテストフレームワーク
  • 採用している企業が少ない
  • 実行速度が早い
  • 複雑なテストを行う場合、多くのプラグインが必要となる

主なテストの種類

Modelテスト

  • モデルの状態が有効になっているか。
  • バリデーションが効いているか。
  • クラスメソッドとインスタンスメソッドの動作。

System テスト

  • Rails 5.1から使用可能となった統合テスト。
  • Feature テストと役割は同じだがテスト失敗時スクショを撮影するgemのインストールが不要。
  • driven_byを使って、specごとにブラウザを簡単に切り替えることができる。
  • テスト終了時にDBが自動的にロールバックされる

Request(結合) テスト

  • ルーティングを含めたコントローラー、モデル、ビューを通したテストを行う。また、リクエストに対して正しいレスポンスが返されることを確認する。

その他のテストは利用頻度が少なかったり上記のテストに置き換えが推薦されていたりするので割愛。

コードの基本形

describe [仕様を記述する対象(テスト対象)], type: [Specの種類] do

  context [ある状況・状態] do
    before do
      [事前準備]
    end

    it [仕様の内容(期待の概要)] do
      [期待する動作]
    end
  end
end
  • テストを整理・分類する・・describe,context
  • テストコードを実行する・・before、it

  •  before

    • 何を記述しようとしているのかを記述
  • context

    • テストの内容を「状況・状態」のバリエーションごとに分類する
  • it

    • 期待する動作を文章と、ブロック内のコードで記述

(参考)
https://www.atmarkit.co.jp/ait/articles/1404/30/news022.html

https://qiita.com/umeziro_v2/items/edd7df47a5aa378af721#_reference-e2a604932337f846bc8e

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

if文をunlessを用いて書き換える

「if」

if a + b > 0
  puts "計算結果は0より大きいです"
end

「unless」

unless a + b <= 0
  puts "計算結果は0より大きいです"
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails generate react:install実行時のrun() in thread failed: inotify event queue has overflowed対応

現象

rails webpacker:installを実行するとrun() in thread failed: inotify event queue has overflowedと表示される。
app/assets/javascripts/application.jsが作成されない。

環境

docker-composeでruby:2.6.3をベースに構築。

対応

方法その1.Dockerの設定を変更する。

 環境設定→AdvancedのCPUs,Memory,Swapの値を増加する。

方法その2.コンテナ内のファイル以下の記述を追加しsysctl設定にロードする。

/etc/sysctl.conf
fs.inotify.max_user_watches = 999999
fs.inotify.max_queued_events = 999999
fs.inotify.max_user_instances = 999999

以下のコマンドを実行

sudo sysctl -p

補足:以下のエラーが表示される場合、privilegedでコンテナを起動する必要がある。

sysctl: setting key "fs.inotify.max_user_watches": Read-only file system

privilegedを以下の通り記載してコンテナを起動し、再度コンテナ内でsudo sysctl -pを実行する。

docker-compose.yml
version: '3'
services:
  web:
    privileged: true

結果

rails generate react:installでエラーが出ず、正しくapp/assets/javascripts/application.jsが作成される!

参考にさせていただいたサイト
https://github.com/guard/listen/wiki/Increasing-the-amount-of-inotify-watchers
https://github.com/guard/rb-inotify/issues/61
https://qiita.com/osamunmun/items/1786aac5904439522d72

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

rails bootstrap Paginationの基本

■ 環境

  • windows 8.1
  • Rails 5.1.6
  • ruby 2.3.3p222 (2016-11-21 revision 56859) [i386-mingw32]
  • Bundler version 1.15.3

Gemfileに以下を追加

Gemfile
gem 'will_paginate',           '3.1.6'
gem 'bootstrap-will_paginate', '1.0.0'
$ bundle update
$ bundle install
app/controllers/Users_controller.rb
class UsersController < ApplicationController
  def index
    @users = User..paginate(page: params[:page], per_page: 5)
    #per_pageで1ページに表示可能な個数を指定できる
  end
end
app/views/users/index.html.erb
<!-- 上で設定した@usersを使い表示させる -->

<% @users.each do |user| %>
  <p><%= link_to user.name, user %></p>
<% end %>
<%= will_paginate %>

<!-- ↓ will_paginateを少しいじる。詳しくは参照2に行くと良い-->
<% @users.each do |user| %>
  <p><%= link_to user.name, user %></p>
<% end %>
<%= will_paginate @users, previous_label: '&lt 前へ', next_label: '次へ &gt' %>

参照

  1. ruby on rails tutorial
  2. https://qiita.com/Nukioman/items/5e35ded48dfcab389c75
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Sinatra】サーバを再起動せずにコードの更新を行う

sinatraで、コードを変更した際にサーバを再起動しないとコードの変更が反映されません。面倒くさいさいですよね。

ということで、自動でコードの変更がが反映されるようにしましょう!

※参考
https://codingcast.techdrive.top/sinatra/bundler/
https://qiita.com/k-ta-yamada/items/9e35c5f8b31862267e01

*windows10環境を使用しています。

Gemファイルの作成

アプリを作成しているディレクトリまで移動してください。
そこでGemファイルの作成を行います。

$ bundle init

でGemファイルが作成されます。

windows環境ではGemファイルは隠しファイルになってるので、隠しファイルの表示を行いましょう。
フォルダのエクスプローラの「表示」オプションから隠しフォルダの設定の変更を行うことが出来ます。

オプションを選択します
スクリーンショット (53)_LI.jpg

表示オプションを選択後、「隠しファイル、隠しフォルダー、および隠しドライブを表示する」を選択後、OKを押します。
スクリーンショット (54)_LI.jpg

Gemファイルの編集

次にGemファイルの編集を行います。

Gemfile.
source 'http://rubygems.org'

gem 'sinatra'
gem 'sinatra-reloader'

sinatraとsinatraリローダーを表記しています。

アプリのファイルの編集

myapp.rb
require 'rubygems'
require 'bundler'

Bundler.require

こちらの表記をアプリに対して行います。

こう記述することによって、Gemファイルに記述されている内容を持ってくることができ、require~を書かなくて済むようになります。

もう一度bundle installを実施します。

これでコードの編集時にサーバを再起動しなくても、コードの変更が自動で反映されます。

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

Rails ルーティングの基礎とRESTful

はじめに

Railsのルーティングについて調べましたので、まとめようと思います。
Railsのルーティングについて一気にまとめてしまうと長くなってしまいますので、
今回は

  • Railsのルーティングの基礎
  • RESTful

に絞りました。

ルーティングの基礎

ルーティングとは

リクエストのURLに応じて、どの処理を実行するかを決定するしくみを指します。
Railsの場合、次の手順で実行するコントローラとアクションを決定します。

  1. クライアントがリクエストを送る
  2. パスを解析し、ルート定義を検索する
  3. 検索されたルート定義に基づいて対応するコントローラ、アクションを呼び出す

ルーティングの設定

ルーティングの設定は/config/routes.rbに定義します。

routes.rb
Rails.application.routes.draw do
  get 'members' => 'members#index'
end

これは
リクエストのURLの末尾がmembersだった場合 =>
membersコントローラのindexアクションを呼び出す

と定義しています。

ルーティングとコントローラの設定例

例えば、次のコントローラとアクションを定義して

members_controller.rb
class MembersController < ApplicationController
  def index
  end
end

次のルーティングを定義して

routes.rb
Rails.application.routes.draw do
  get 'members' => 'members#index'
end

次のリクエストを送信すると
※ http://localhost:3000/の部分はホスト名で、Railsのデフォルトポートは3000です。

http://localhost:3000/members

Membersコントローラのindexアクションが呼ばれます。

RESTful

Railsのルート設計

RESTの性質を持つルート設計のことをRESTfulと言います。
Railsのルート設計はRESTfulです。
※ RESTfulでないルート設計も可能です。しかしRailsにはRESTfulなルート設計が前提の機能も存在するため、注意が必要です。

RESTとは

以下の原則に沿った Webサービスの設計モデルを指します。

  1. セッションなどの状態管理を行わない
  2. 情報を操作する命令が体系化されて定義・共有される
  3. 情報に対して汎用的な構文で一意に識別される
  4. 情報に、別の情報や別の状態へのリンクを含めることができる

一つ一つ具体的にまとめてみます。

セッションなどの状態管理を行わない

クライアントの送信する情報には、全てのやりとりが含まれています。
サーバはクライアントの状態を保持しません。
このようなクライアントとサーバのやりとりはステートレスと言われます。
逆に状態を保持する場合はステートフルと言われます。

例としてECサイトで買い物する場合

ステートフルの場合
1. 商品Aをカートに入れる
2. 商品Bをカートに入れる
3. カート内の商品を購入

ステートレスの場合
1. 商品Aをカートに入れる
2. 商品Aと商品Bをカートに入れる
3. カート内の商品を購入

ステートフルの場合、サーバ側でカートに入れた商品の状態を保持しているため、クライアントは追加する商品の情報のみ送信します。
ステートレスの場合、サーバ側でカートの状態を保持していないため、クライアントは送信する情報にすべてのやりとりを含める必要があります。

情報を操作する命令が体系化されて定義・共有される

なに(リソース)に対してどうするか(HTTPメソッド)でルート定義を設定すること
HTTPメソッドとはクライアントがサーバに対して出す依頼のことで、主に次のようなものがあります。

  • GET:取得
  • POST:作成
  • PUT:更新
  • PATCH:部分更新
  • DELETE:削除

リソースとはユーザ情報や画像データなど、情報全般のことを指します。

例えば以下のルーティングの場合

routes.rb
Rails.application.routes.draw do
  get 'members' => 'members#index'
end

Members(リソース)をGET(取得)するとルート設計しています。

情報に対して汎用的な構文で一意に識別される

すべてのリソースはURIで識別されるということです。

情報に、別の情報や別の状態へのリンクを含めることができる

ハイパーテキスト(他の文書への参照を埋め込める)を拡張したハイパーメディア(文字情報に加え、画像や音声などの情報を扱えるようにし、対応づけたもの)を使おうということです。
ハイパーメディアを用いることで、現在のアプリケーションの状態や、違う情報へのリンクなどを表現します。

メリット

  • ステートレスなため、サーバ側の負荷が少ない
  • HTTP標準のメソッドを使用することで、一貫性のあるルートを設計できる
  • URIに規則が生まれるため、アプリ開発者はリソースを管理しやすい

おわりに

RailsのルーティングとRESTfulについてまとめました。
間違っているところなどがありましたら、教えていただけるとありがたいです。

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