- 投稿日:2020-02-16T23:07:25+09:00
Rails ビュー
ビューはレスポンスとして見た目を返すものになります。
コントローラーの次にビューが実行される。
app/views/コントローラー名ディレクトリにアクション名.html.erbというファイル名で作成される。
コントローラにインスタンス変数を定義
#app/controllers/posts_controller.rbに定義する場合 class PostsController < ApplicationController def index @post = "これはコントローラーで定義したインスタンス変数を確認するための文字列です" end end#ビューファイル(app/views/posts/index.html.erb)にインスタンス変数を定義 <h1>トップページ</h1> <%= @post %>なぜできる?
- 投稿日:2020-02-16T22:52:02+09:00
Rails コントローラーついて
ルーティングを設定したらコントローラーを設定します。
コントローラーはルーティングで振り分けられたリクエストを実際に処理する役割を持っています。
コントローラーの作成
$ rails g controller コントローラー名
postsコントローラーを作成する場合
$ rails g controller posts #app/controllers/posts_controller.rbが作成されているか確認コントローラー内にアクションを記載する
class PostsController < ApplicationController end #作ったばっかりでは何も記載はないindexアクションを定義する場合↓
class PostsController < ApplicationController def index # indexアクションを定義した end endこれでコントローラーの大まかな作業は完了です。続きはビュー編でお伝えします。
- 投稿日:2020-02-16T22:25:32+09:00
Rails ルーティング設定について
ルーティングとはどの要求を受けたら、どのコントローラを呼び出すかを決めている場所。
ルーティングの記載
【例】config/routes.rbに記載
以下はHTTPメソッドとリクエスト、そして行き先のコントローラーとアクションが明示されている形です。
HTTPメソッド
クライアントから送られたリクエスト(GET[ページを表示する操作]、POST[データを登録する操作]、PUT[データを変更する操作]、DELETE[データを削除する操作])のこと。URIパターン
URLのようなもの。例えば、http://localhost:3000/posts
にアクセスする際はpostsのみを記載。コントローラー
ルーティングの次にやってくる処理のこと。
アクション
コントローラー内における、処理のカテゴリの事。
ルーティングは「どのようなリクエスト」=>「どのようなコントローラー・アクション」をイメージ。Rails.application.routes.draw do [HTTPメソッド] '[URIパターン]', to: '[コントローラー名]#[アクション名]' end #例として以下のように記載 Rails.application.routes.draw do root to: 'posts#index' get 'posts', to: 'posts#index' get 'posts/new', to: 'posts#new' post 'posts', to: 'posts#create' end #get 'posts', to: 'posts#index'を例にとる。 #リクエスト: GETのHTTPメソッド、URLはhttp://localhost:3000/posts #行き先: postsコントローラーという名前のコントローラー、indexアクションという名前のアクションresources メソッドを使用したバージョン
resourcesを使用すると7つのアクション(index[一覧表示ページを表示]、new[新規投稿ページを表示]、create[データの投稿を行う]、show[個別詳細ページを表示]、edit[投稿編集ページを表示]、update[データの編集を行う]、destroy[データの削除])全てを実装したことになる。
onlyオプション
指定したアクションのルーティングのみを設定できる。
Rails.application.routes.draw do root to: 'posts#index' resources :posts, only: [:index, :new, :create] endrails routesコマンド
Prefixとは
Prefixを指定した場合はパスの書き方が変わります。詳しくはビューファイル設定の際に説明します。
- 投稿日:2020-02-16T21:50:10+09:00
Rails アプリ作成に向けての準備
実際にアプリケーションを作成するにあたっての説明です。
rails new コマンド
Railsで新規アプリケションを作成する際に使用します。
$ rails new アプリケーション名 -オプション名 # オプションを付けてアプリケーションを作成例:sample_appleを作成する場合
# Railsのバージョン5.2.3を用いて、「sample_apple」を「-d」オプションでMySQLを指定して作成。 $ rails _5.2.3_ new sample_apple -d mysql # 「sample_apple」ディレクトリに移動 $ cd sample_apple # 現在のディレクトリのパスを表示 $ pwdデータベースを作成
rails db:create
を実行して新しくデータベースを作成します。$ rails db:create # データベースの作成 Created database 'sample_apple_development' Created database 'sample_apple_test'これで開発環境とテスト環境用のデータベースが作成完了。
確認はdatabase.ymlで確認できます。データベースはSequel Proで管理する前提で説明します。
以下の設定でデータベース接続。rails s
開発者のみがローカルでサーバーを立ち上げるためのコマンドです。
control + cでサーバーを切ることができる。
- 投稿日:2020-02-16T21:16:09+09:00
rubocopをbundlerでインストールするときにrequire: falseにする理由
本記事の対象者
「rubocopを導入するときにrequire: falseにしてたけど、理由がよく分からない」
そんな方に向けてこの記事を書いています。
rubocopの導入方法
rubocopの公式ドキュメントでは、以下のコマンドを実行する
$ gem install rubocop`もしくは、Gemfileに以下を記載して、bundlerで導入してくださいと書いてあります。
$ gem 'rubocop', require: false`この記事では、後者について記載していきます。
bundlerの特徴
rubocopを導入するうえで、覚えておきたいbundlerの特徴は、
「bundlerでは、Gemfileに書いたgemをまとめて自動でrequireする仕組みになっている」ということです。rubocopはどこで使うの?
rubocopは、ソースコードが規約に沿っているか確認するために、ターミナル等でコマンドを実行します。
結論
rubocopは、ターミナル等で使用するため、bundlerによってアプリ側に自動で読み込む必要がない。よって、
require: false
にする。参考
主に以下を参考にさせていただきました。ありがとうございます!
- 【Rails】RuboCopの基本的な使用方法と出力の見方 https://qiita.com/terufumi1122/items/ad55bf8713c0df053f58
- Home - RuboCop: The Ruby Linter that Serves and Protects https://rubocop.readthedocs.io/en/latest/
- 投稿日:2020-02-16T20:27:33+09:00
Gemfileでインストールするgemを間違えた時の対処法
本記事の対象者
「インストールしようと思っていたgemを間違えてしまった」
「Gemfileでインストールしたgemを削除したい」
そんな方に向けてこの記事を書いています。ステップ1:Gemfileから削除する
はじめに、Gemfileから間違ってインストールしたgemの記載を削除します。
ステップ2:Gemfile.lockから削除する
次に、Gemfile.lockの記載を更新します。Gemfile.lockは手動で修正せずに、以下のコマンドを実行して、自動で修正するようにしてください。
$ bundle installもしくは
$ bundle install --path vendor/bundleまとめ
Gemfileでインストールするgemを間違えた際には、以上のたった2ステップを実行することで対処できます。
- 投稿日:2020-02-16T20:27:33+09:00
Gemfileでインストールするgemを間違えた時の取り消し方
本記事の対象者
「インストールしようと思っていたgemを間違えてしまった」
「Gemfileでインストールしたgemを削除したい」
そんな方に向けてこの記事を書いています。ステップ1:間違ってインストールしたgemを削除する
まずは、以下のコマンドを実行して、間違ってインストールしたgemを削除しましょう。このとき削除するgemによっては、他のgemやコードに影響を及ぼす可能性があるので、注意してください。
$ bundle exec gem uninstall <gem名>ステップ2:Gemfileから削除する
続いて、Gemfileから間違ってインストールしたgemの記載を削除します。
ステップ3:Gemfile.lockから削除する
最後に、Gemfile.lockの記載を更新します。Gemfile.lockは手動で修正せずに、以下のコマンドを実行して、自動で修正するようにしてください。
$ bundle installもしくは
$ bundle install --path vendor/bundleまとめ
間違ってインストールしたgemは、①gemのアンインストール、②Gemfileの書き換え、③Gemfile.lockの書き換えの3ステップで行えました。
ただし、gemをアンインストールする前に、他のgemやコードへの影響がないか確認をしてから行うようにしましょう!
- 投稿日:2020-02-16T20:16:10+09:00
DXRuby:「当たり判定」を自分で作ってみよう A. 四角形の四隅の座標で判定する
概要
この記事は中学高校生向けプログラミング教室の教材として作ったものを一部改変したものです。
今回の記事は、
・DXRuby:「当たり判定」を自分で作ってみよう - Qiita● 当たり(衝突)判定の方法
A. 四角形の四隅の座標で判定する
B. 円の中心からの距離で判定する
C. 色で判定するの内の
A. 四角形の四隅の座標で判定する
になります。次の記事
・DXRuby:「当たり判定」を自分で作ってみよう B. 円の中心からの距離で判定する - Qiita技術解説
- 使用ライブラリ
- 参考サイト については、上記記事を参照してください。
ライセンス
ソースコード、本解説ともにパブリックドメイン
プログラム解説
A. 四角形の四隅の座標で判定する
→ 「ブロック崩し」追加課題 1a);衝突判定の自作(四角) - noanoa 日々の日記
http://blog.livedoor.jp/noanoa07/archives/2046179.htmlA-1a.
===
を使った準備:判定相手が単独(atari_1.rb)DXRubyのスプライトでは、
===
を使うと、衝突の有/無でtrue
/fasle
を返します。
ball
(小さい正方形)が、block
(大きい長方形)と衝突しているかを===
で判定します。
衝突/非衝突 の結果をターミナル(コマンドプロンプト)にtrue
/false
で出力しつつ、block
の色も赤
/白
にします。
また、ウィンドウに衝突時はhit!
の文字列を表示します。atari_1.rbrequire 'dxruby' image0 = Image.new( 50, 50, C_WHITE) image1 = Image.new(200, 100, C_WHITE) image2 = Image.new(200, 100, C_RED) ball = Sprite.new(300, 400, image0) block = Sprite.new(200, 200, image1) font = Font.new(32) Window.loop do ball.x = Input.mouse_pos_x ball.y = Input.mouse_pos_y ball.draw result = (ball === block) p result if result Window.draw_font(0, 0, "hit!", font) block.image = image2 else block.image = image1 end block.draw endA-1b.
atari?
を自作:判定相手が単独(atari_2.rb)
atari?(jibun, aite)
を作って、 衝突の有/無でtrue
/fasle
を返すようにします。判定方法は、互いの四角形の四隅の座標を比較することにします。
自分
jibun
のx座標
はx0
〜xx0
、y座標はy0
〜yy0
相手
aite
のx座標
はx
〜xx
、y座標はy
〜yy
2つが重なっている条件は;
aite
のx座標
の範囲x
〜xx
の中に、jibun
のx0
またはxx0
があることかつ
aite
のy座標
の範囲y
〜yy
の中に、jibun
のy0
またはyy0
があることこれをコーディングすると以下のようになります。
(
&&
はかつ
、||
はまたは
の意味)(x <= x0 && x0 <= xx || x <= xx0 && xx0 <= xx) && (y <= y0 && y0 <= yy || y <= yy0 && yy0 <= yy)また、
スプライト
の画像の幅
と高さ
を求めるには、
幅
;スプライト.image.width
高さ
;スプライト.image.height
を使います。
→ DXRubyリファレンス:API INDEX;Sprite;image
http://mirichi.github.io/dxruby-doc/api/Sprite_23image.html→ DXRubyリファレンス:API INDEX;Image;width,height
http://mirichi.github.io/dxruby-doc/api/Image.htmlそれでは、自作した
atari?
を使って、===
を使ったコードを書き換えてみます。atari_2.rbrequire 'dxruby' def atari?(jibun, aite) x0 = jibun.x xx0 = x0 + jibun.image.width y0 = jibun.y yy0 = y0 + jibun.image.height x = aite.x xx = x + aite.image.width y = aite.y yy = y + aite.image.height (x <= x0 && x0 <= xx || x <= xx0 && xx0 <= xx) && (y <= y0 && y0 <= yy || y <= yy0 && yy0 <= yy) end image0 = Image.new( 50, 50, C_WHITE) image1 = Image.new(200, 100, C_WHITE) image2 = Image.new(200, 100, C_RED) ball = Sprite.new(300, 400, image0) block = Sprite.new(200, 200, image1) font = Font.new(32) Window.loop do ball.x = Input.mouse_pos_x ball.y = Input.mouse_pos_y ball.draw result = atari?(ball, block) p result if result Window.draw_font(0, 0, "hit!", font) block.image = image2 else block.image = image1 end block.draw endA-2a.
===
を使った準備:判定相手が配列(atari_3.rb)DXRubyのスプライトでは、
===
は、相手がスプライトの配列でも、衝突の有/無でtrue
/fasle
を返します。
ball
が、スプライトの配列blocks
と衝突しているかを===
で判定します。
blocks
のいずれかと衝突していたら、ターミナル(コマンドプロンプト)にtrue
で出力し、それ以外はfalse
を出力します。
また、ウィンドウに衝突時はhit!
の文字列を表示します。atari_3.rbrequire 'dxruby' image0 = Image.new( 50, 50, C_WHITE) image1 = Image.new(200, 100, C_WHITE) image2 = Image.new(200, 100, C_RED) ball = Sprite.new(300, 400, image0) block1 = Sprite.new( 10, 200, image1) block2 = Sprite.new(250, 200, image1) blocks = [block1, block2] font = Font.new(32) Window.loop do ball.x = Input.mouse_pos_x ball.y = Input.mouse_pos_y ball.draw result = (ball === blocks) p result if result Window.draw_font(0, 0, "hit!", font) end Sprite.draw(blocks) endA-2b.
atari_array?
を自作:判定相手が配列(atari_4.rb)
===
の代わりに、atari_array?(jibun, array)
を自作します。
判定相手の配列の要素を一つずつatari?
で判定していきます。自作した
atari_array?
を使って、コードを書き換えます。atari_4.rbrequire 'dxruby' def atari?(jibun, aite) x0 = jibun.x xx0 = x0 + jibun.image.width y0 = jibun.y yy0 = y0 + jibun.image.height x = aite.x xx = x + aite.image.width y = aite.y yy = y + aite.image.height (x <= x0 && x0 <= xx || x <= xx0 && xx0 <= xx) && (y <= y0 && y0 <= yy || y <= yy0 && yy0 <= yy) end def atari_array?(jibun, array) array.each do |a| if atari?(jibun, a) return true end end false end image0 = Image.new( 50, 50, C_WHITE) image1 = Image.new(200, 100, C_WHITE) image2 = Image.new(200, 100, C_RED) ball = Sprite.new(300, 400, image0) block1 = Sprite.new( 10, 200, image1) block2 = Sprite.new(250, 200, image1) blocks = [block1, block2] font = Font.new(32) Window.loop do ball.x = Input.mouse_pos_x ball.y = Input.mouse_pos_y ball.draw result = atari_array?(ball, blocks) p result if result Window.draw_font(0, 0, "hit!", font) end Sprite.draw(blocks) endA-3a.
check
を使った準備(atari_5.rb)DXRubyの
===
や、自作したatari_array?
では、どの相手に衝突したかは分かりませんでした。一方、DXRubyのスプライトでは
check
を使うと、衝突している相手すべてを配列に入れて返します。(衝突していない時は、何も入ってない配列を返す)この配列を
array
とすると、0番目のarray.first
(array[0]
でも同じ)が最初に衝突した相手です。また、array.first
に何か入っていれば衝突している、空(nil)
ならば衝突していないという、当たり判定にも使えます。→ DXRubyリファレンス:Spriteを使うためのチュートリアル;衝突したオブジェクトを取得する
http://mirichi.github.io/dxruby-doc/tutorial/sprite.html→ DXRubyリファレンス:API INDEX;Sprite;check
http://mirichi.github.io/dxruby-doc/api/Sprite_23check.htmlプログラムでは、
ball
がblocks
のどれに最初に衝突しているかをcheck.first
で判定します。
最初に衝突しているブロックをターミナル(コマンドプロンプト)に出力し、そのブロックを赤色にします。それ以外はnil
を出力します。
また、ウィンドウに衝突時はhit!
の文字列を表示します。atari_5.rbrequire 'dxruby' image0 = Image.new( 50, 50, C_WHITE) image1 = Image.new(200, 100, C_WHITE) image2 = Image.new(200, 100, C_RED) ball = Sprite.new(300, 400, image0) block1 = Sprite.new( 10, 200, image1) block2 = Sprite.new(250, 200, image1) blocks = [block1, block2] font = Font.new(32) Window.loop do ball.x = Input.mouse_pos_x ball.y = Input.mouse_pos_y ball.draw col = ball.check(blocks).first p col if col Window.draw_font(0, 0, "hit!", font) col.image = image2 Sprite.draw(blocks) col.image = image1 else Sprite.draw(blocks) end endA-3b.
atari_array
を自作(atari_6.rb)ぶつかった相手は最初のものだけ分かればよいので、DXRubyの
check.first
相当のatari_array
を自作します。つまり、
atari_array
は、衝突していないとnil
を返し、衝突すると "ぶつかった最初のもの
" を返します。方法は、判定相手の配列の要素を一つずつ
atari?
で判定していき、最初に衝突している要素を返します。自作した
atari_array
を使って、コードを書き換えます。atari_6.rbrequire 'dxruby' def atari?(jibun, aite) x0 = jibun.x xx0 = x0 + jibun.image.width y0 = jibun.y yy0 = y0 + jibun.image.height x = aite.x xx = x + aite.image.width y = aite.y yy = y + aite.image.height (x <= x0 && x0 <= xx || x <= xx0 && xx0 <= xx) && (y <= y0 && y0 <= yy || y <= yy0 && yy0 <= yy) end def atari_array(jibun, array) array.each do |a| if atari?(jibun, a) return a end end nil end image0 = Image.new( 50, 50, C_WHITE) image1 = Image.new(200, 100, C_WHITE) image2 = Image.new(200, 100, C_RED) ball = Sprite.new(300, 400, image0) block1 = Sprite.new( 10, 200, image1) block2 = Sprite.new(250, 200, image1) blocks = [block1, block2] font = Font.new(32) Window.loop do ball.x = Input.mouse_pos_x ball.y = Input.mouse_pos_y ball.draw col = atari_array(ball, blocks) p col if col Window.draw_font(0, 0, "hit!", font) col.image = image2 Sprite.draw(blocks) col.image = image1 else Sprite.draw(blocks) end endA-4. 自作の当たり判定(四角)を
Spriteクラスのメソッド
にする(atari_7.rb)元の
===
とcheck
は、Sprite
クラスのメソッド(命令)なので、書き方としては、ball.check(blocks)
のようになります。自作の
atari_array
も同じような書き方になるように、Sprite
クラスのメソッドにしてみます。
クラス
やメソッド
についての説明はここでは説明を省きますので、詳しくはRubyのテキストを見てください。クラスメソッドを追加する方法は簡単で、以下のようにします。
class Sprite def 追加したいメソッド #追加したいメソッドの内容 end end
Sprite
クラスにatari?
とatari_array
追加します。ちなみに、
jibun
(自分)に相当するものは、self
と書きます。class Sprite def atari?(aite) x0 = self.x xx0 = x0 + self.image.width y0 = self.y yy0 = y0 + self.image.height x = aite.x xx = x + aite.image.width y = aite.y yy = y + aite.image.height (x <= x0 && x0 <= xx || x <= xx0 && xx0 <= xx) && (y <= y0 && y0 <= yy || y <= yy0 && yy0 <= yy) end def atari_array(array) array.each do |a| if self.atari?(a) return a end end nil end endこれで、クラスメソッドになったので、今までの
atari_array(ball, blocks)
という書き方ではなく、ball.atari_array(blocks)
というように書くことができるようになりました。atari_7.rbrequire 'dxruby' class Sprite def atari?(aite) x0 = self.x xx0 = x0 + self.image.width y0 = self.y yy0 = y0 + self.image.height x = aite.x xx = x + aite.image.width y = aite.y yy = y + aite.image.height (x <= x0 && x0 <= xx || x <= xx0 && xx0 <= xx) && (y <= y0 && y0 <= yy || y <= yy0 && yy0 <= yy) end def atari_array(array) array.each do |a| if self.atari?(a) return a end end nil end end image0 = Image.new( 50, 50, C_WHITE) image1 = Image.new(200, 100, C_WHITE) image2 = Image.new(200, 100, C_RED) ball = Sprite.new(300, 400, image0) block1 = Sprite.new( 10, 200, image1) block2 = Sprite.new(250, 200, image1) blocks = [block1, block2] font = Font.new(32) Window.loop do ball.x = Input.mouse_pos_x ball.y = Input.mouse_pos_y ball.draw col = ball.atari_array(blocks) p col if col Window.draw_font(0, 0, "hit!", font) col.image = image2 Sprite.draw(blocks) col.image = image1 else Sprite.draw(blocks) end endA-5. 自作の当たり判定(四角)を使ったブロック崩し(atari_8.rb)
「ブロック崩し」のプログラム
block28.rb
を、自作のatari_array
に書き換えてみましょう。元の
===
とcheck.first
を同じ動きをしているのがわかると思います。atari_8.rbrequire 'dxruby' class Sprite def atari?(aite) x0 = self.x xx0 = x0 + self.image.width y0 = self.y yy0 = y0 + self.image.height x = aite.x xx = x + aite.image.width y = aite.y yy = y + aite.image.height (x <= x0 && x0 <= xx || x <= xx0 && xx0 <= xx) && (y <= y0 && y0 <= yy || y <= yy0 && yy0 <= yy) end def atari_array(array) array.each do |a| if self.atari?(a) return a end end nil end end img_bar = Image.new(100, 20, C_WHITE) img_hwall = Image.new( 20, 480, C_BLUE) img_vwall = Image.new(640, 20, C_BLUE) img_ball = Image.new( 20, 20).circle_fill(10, 10, 10, C_RED) img_block = Image.new( 58, 18, C_GREEN) img_block_y = Image.new( 58, 18, C_YELLOW) bar = Sprite.new( 0, 460, img_bar) lwall = Sprite.new( 0, 0, img_hwall) rwall = Sprite.new(620, 0, img_hwall) twall = Sprite.new( 0, 0, img_vwall) walls = [bar, lwall, rwall, twall] ball = Sprite.new(300, 400, img_ball) dx = 2 dy = -2 def move(sprite, speed_x, speed_y) sprite.x += speed_x sprite.y += speed_y end blocks = [] 10.times do |x| 5.times do |y| blocks << Sprite.new(21 + 60 * x, 21 + 20 * y, img_block) end end Window.loop do bar.x = Input.mouse_pos_x Sprite.draw(walls) move(ball, dx, 0) if ball.atari_array(walls) ball.x -= dx dx = -dx end coll_x = ball.atari_array(blocks) if coll_x coll_x.image = img_block_y coll_x.draw #一瞬色が変わって表示 coll_x.vanish #消える ball.x -= dx dx = -dx end move(ball, 0, dy) if ball.atari_array(walls) ball. y -= dy dy = -dy end coll_y = ball.atari_array(blocks) if coll_y coll_y.image = img_block_y coll_y.draw #一瞬色が変わって表示 coll_y.vanish #消える ball. y -= dy dy = -dy end ball.draw Sprite.draw(blocks) end参考
プログラミング初心者向け:DXRubyで 1ステップずつ作っていく「ブロック崩し」 - Qiita
で作った「ブロック崩し」のプログラムです。
- block28.rb
block28.rbrequire 'dxruby' img_bar = Image.new(100, 20, C_WHITE) img_hwall = Image.new( 20, 480, C_BLUE) img_vwall = Image.new(640, 20, C_BLUE) img_ball = Image.new( 20, 20).circle_fill(10, 10, 10, C_RED) img_block = Image.new( 58, 18, C_GREEN) img_block_y = Image.new( 58, 18, C_YELLOW) bar = Sprite.new( 0, 460, img_bar) lwall = Sprite.new( 0, 0, img_hwall) rwall = Sprite.new(620, 0, img_hwall) twall = Sprite.new( 0, 0, img_vwall) walls = [bar, lwall, rwall, twall] ball = Sprite.new(300, 400, img_ball) dx = 2 dy = -2 def move(sprite, speed_x, speed_y) sprite.x += speed_x sprite.y += speed_y end blocks = [] 10.times do |x| 5.times do |y| blocks << Sprite.new(21 + 60 * x, 21 + 20 * y, img_block) end end Window.loop do bar.x = Input.mouse_pos_x Sprite.draw(walls) move(ball, dx, 0) if ball === walls ball.x -= dx dx = -dx end coll_x = ball.check(blocks) if coll_x[0] coll_x[0].image = img_block_y coll_x[0].draw #一瞬色が変わって表示 coll_x[0].vanish #消える ball.x -= dx dx = -dx end move(ball, 0, dy) if ball === walls ball. y -= dy dy = -dy end coll_y = ball.check(blocks) if coll_y[0] coll_y[0].image = img_block_y coll_y[0].draw #一瞬色が変わって表示 coll_y[0].vanish #消える ball. y -= dy dy = -dy end ball.draw Sprite.draw(blocks) end
- 投稿日:2020-02-16T15:19:37+09:00
SIerの僕、プログラミング始めてみた(10月スタート・初投稿)
簡単な自己紹介
SIerに2年間在籍しております、かなたです。
誰も興味がない趣味とか仕事とか、本記事のきかっけを初めに。
- 好き①:服(Margielaとか)
- 好き②:映画(おすすめは Into the Wild)
- 業務①:DataSpiderを用いたデータ連携基盤を構築
- 業務②:C#デスクトップ系業務アプリ
10月からWEBアプリケーションの勉強を独学で始めまして、よくよくエラー等ひっかかります。
昨日の自分自身に対して、教えるならどのように伝えるかを、ここに表現できればと思っています。
(あとモチベーションアップに繋がれば…という思いです)作っているもの
SIer(以外もそうだと思うんですが)は基本的に、実績ベースで予定・工数を積み上げ、スケジューリングします。
ですが、実績を記録しているPJ/チームを僕は見たことがありません。
そのため、予実データ化し改善までつながるアプリケーションを開発しよう!と始めてみました。成果
さてさて、10月からおよそ4ヶ月の成果はざっくり以下の通りです。
プログラミング基本
- HTML/CSS/JavaScript/Ruby/Railsの基本(Progate)
- Railsチュートリアル2周(GitHub~Herokuデプロイ)
- Vueサンプル複写(基礎から学ぶ Vue.js)
本
- リーダブルコード
- 初めてのRuby
- Webを支える技術
- Web API: The Good Parts
- テスト駆動開発
- リファクタリング
- エンジニアファースト
- エンジニアの知的生産術
- コンピュータはなぜ動くのか
- デザイン系の本を数冊
アプリケーションの実装状況
- フロントエンド ・・・ Vue.js + Vuex + VueRouter + Vuetify
- サーバサイド ・・・ RubyonRails
- 実装:メールアドレスを利用したユーザの登録〜ログインおよびユーザ情報の更新
- 詳細:ユーザログイン時には、WebStorageを利用。ログイン永続化を実装。
ざっくりこんな状況です。頑張らないと・・・
さいごに
また、目標・スケジュールをこちらに記載できればと思っています(もしかして、そういった場でない?)
そして、次回からは、冒頭で述べたとおり、自分自身の備忘録として、
学んだことを表現させていただきます。よろしくお願いいたします。
- 投稿日:2020-02-16T14:59:57+09:00
DXRuby:「当たり判定」を自分で作ってみよう
概要
この記事は中学高校生向けプログラミング教室の教材として作ったものを一部改変したものです。
ゲームで大変よく使う「当たり判定」(衝突判定)について、DXRubyでは
===
やcheck
などの便利な機能が付いています。しかし、いつもこのような機能が使えるとは限りません。では、自分で作るとしたらどうしたらよいでしょうか?実は、いろいろな判定方法が考えられます。
前の記事
・プログラミング初心者向け:DXRubyで 1ステップずつ作っていく「ブロック崩し」 - Qiita次の記事
・DXRuby:「当たり判定」を自分で作ってみよう A. 四角形の四隅の座標で判定する - Qiita当たり(衝突)判定の方法
いろいろなやり方が考えられるでしょうが、まずは以下の3通りのやり方が思いつきます。
A. 四角形の四隅の座標で判定する
B. 円の中心からの距離で判定する
C. 色で判定するそれぞれ、別記事になっています。
技術解説
使用ライブラリ
Windows向けRuby用2Dゲームライブラリ
DXRuby
を使用します。
バージョン1.4.2
以上を想定しています。
1.4.2
より前のバージョンとの主な相違点
Window.loop
が複数置けるマウス位置を取得する
Input.mouse_pos_x
、Input.mouse_pos_y
の新しい書き方として、Input.mouse_x
、Input.mouse_y
が追加→ DXRuby 1.4.6:更新履歴
http://mirichi.github.io/dxruby-doc/CHANGELOG.html
DXRubyインストールの注意点
→ DXRuby 1.4.6 をWindows10で使う時の注意点とインストール方法 - noanoa07 - Qiita
https://qiita.com/noanoa07/items/0ce14c2404df38de94b7参考サイト
DXRuby のホームページ
http://dxruby.osdn.jpDXRuby 1.4.6 リファレンスマニュアル
http://mirichi.github.io/dxruby-doc/index.html困ったときは、このページの「チュートリアル」と「マニュアル」にだいたい書いてあります。
- DXRuby 1.4.1 リファレンスマニュアル http://dxruby.osdn.jp/DXRubyReference/20095313382446.htm
古いバージョンのリファレンスも役に立つときがあります。
- 「ブロック崩し」追加課題1;衝突判定を自作してみよう - noanoa 日々の日記 http://blog.livedoor.jp/noanoa07/archives/2046177.html
このテキストのブログ記事での解説です。
ライセンス
ソースコード、本解説ともにパブリックドメイン
- 投稿日:2020-02-16T14:29:07+09:00
メソッド内にループがある場合の戻り値(返り値)について
皆さんこんにちは! プログラマーを目指して学習している、久保雄貴と申します。
今回は「メソッド内にループがある場合の戻り値(返り値)について」自分が疑問に思ったこと、考えたこと、知ったことについて書いてみようと思います。
あるときrubyの勉強中にエラーが起きました。メソッドの戻り値を使って演算をしようとした時です。
「undefined method '+' for nil:nilclass」 のような表示がされました。
空のオブジェクトと足し算はできません。ということのようです。
頭の中に「?」がたくさん出てきて、自分が戻り値についてよく理解できていないことがわかりました。
そこでいろいろ考え、実験して、調べてみたわけです。皆さんのお役に立てる内容であれば嬉しいです。
なお、間違っている点や「こういう風に書いたらいいよ」などアドバイスがありましたら、コメントをください。
では始めましょう!
1. 戻り値とは
戻り値とは、オブジェクトやメソッドが処理された後の最終的な値のことです。返り値とも言います。
Rubyのオブジェクト自体、またはメソッドを利用した「式」には、全て戻り値があります。Rubyにおける「式」とは文字列や数値の他に、変数やメソッド呼び出し、演算子式などが含まれます。
すなわち、"あいうえお", 5296, (4 + 24)などはすべて式になります。
そしてそれらすべてに戻り値があるということです。(上の例でいうと、"あいうえお", 5296, 28)2. メソッドの戻り値はどうなる?
では、メソッドの戻り値はどうなるのでしょうか。
Ruby Referenceで調べてみました。http://ruby-for-beginners.rubymonstas.org/writing_methods/return_values.html
以下のように書かれています。
In Ruby, a method always return exactly one single thing (an object).
Also note that in Ruby we do not have to use the statement return, as in other languages. In fact, most Ruby code does not use the keyword return at all.This is extremely convenient, but it is also something we need to learn:
If we don’t do anything else, then a method will return the value that was returned from the last evaluated statement. Most often, this is the last line in the method body.
端的に言えば、
「メソッドは一つの値を返が、他の言語と違って、returnと記述する必要はない。
もし記述しなかったら、最後の式の値が返される。」
という感じでしょうか。例えば、
def test(number) number + 1 ←メソッドの中の最後の式 end puts test(5)これを実行すると、6と表示されますね。
"number + 1" の答えである "6" がtestメソッドの戻り値となっているわけです。3. 実験: メソッドの戻り値の判定
冒頭で書きましたが、メソッドの戻り値を使って演算をしようとした時に、「戻り値は「nil」ですよ。」とエラーが出ました。実は、その時はメソッド内にwhile文(ループ)がありました。
条件を満たすまで、命令を実行し、条件を満たしたら、ループから抜け出して、メソッドの呼び出し元にもどる。
その戻り値で演算をしようとしてエラーが出たわけです。
そこでメソッドの戻り値が「nil」かそうでないかを判断してみたらどうかと思いつきました。
メソッドの戻り値が「nil」なのかそうでないのかを判断するコードを考えましたので、みていきたいと思います。
まずはwhile文なしのパターンです。def test(count) puts "0より大きい数字を入力してください。" count = gets.to_i end count = test(count) if count.nil? puts "test(count)の戻り値はnilです。" else puts "test(count)の戻り値は#{count}です。" end「.nil?」はcount(レシーバ)の中身が「nil」の場合trueを返し、「nilでない」場合falseを返すメソッドです
例えば、ターミナルで実行して、24という数字を入れたとすると、と表示されます。
上のコードでは予想通り、returnの記述がなくても戻り値は「nil」ではありませんでした。
では次はどうでしょう。
testメソッドの中にwhile文を入れて、10より大きい数字が入るまで、入力させ続けます。
そして、その戻り値が「nil」かどうかを判断します。def test(count) while count <=10 puts "10より大きい数字を入力してください。" count = gets.to_i end end count = 0 count = test(count) if count.nil? puts "test(count)の戻り値はnilです。" else puts "test(count)の戻り値は#{count}です。" endターミナルで実行してみましょう。
今回は、「4→24」の順で入れてみます。(while文が機能しているか判断するため。)なんと今回は戻り値が「nil」になりました!
次は、while文の後に「return count」を入れてみます。def test(count) while count <=10 puts "10より大きい数字を入力してください。" count = gets.to_i end return count ←追加しました end count = 0 count = test(count) if count.nil? puts "test(count)の戻り値はnilです。" else puts "test(count)の戻り値は#{count}です。" end実行してみましょう。
当然のことながら、戻り値は「24」ですね。
4. 結果
さて、もう一度まとめてみましょう。
メソッドの戻り値が「nil」かどうかを判断しました。
順番 条件 結果 1 while文なし 戻り値: 24 2 while文あり かつ returnメソッドなし 戻り値: nil 3 while文あり かつ returnメソッドあり 戻り値: 24 5. 考察
さて、上記の結果になりました。
ここからは、あくまで自分で考えた内容です。(信憑性はとても低いです)Rubyは、メソッド内において式から得られる「値」をどこかに仮置きしているのではないか。
例えば、1の実験ではdef test(count) puts "0より大きい数字を入力してください。" count = gets.to_i ←ここで入力された値をどこかに仮置きしている。 end count = test(count) if count.nil? puts "test(count)の戻り値はnilです。" else puts "test(count)の戻り値は#{count}です。" end1) 3行目で「値」をどこかに仮置きする。
2) もしメソッドの中に次の式があれば、仮置きしている「値」を破棄し、その次の「値」をまた仮置きする。(今回はなし)
3) メソッドが終わったら、一番最後に仮置きした「値」をメソッドの戻り値として返す。と行った感じです。
ただ、メソッドの中にループ文がある場合は、ループから抜け出す時になぜかその仮置きしておいた「値」を破棄してしまうのではないか。
なぜかはわかりません。。。(考察になっていない?)6. 結論
実は、このブログを書く前にいろいろと参考になるものはないかと探していたところ、答えになるものを見つけました。
Rubyのリファレンスマニュアルです。https://docs.ruby-lang.org/ja/latest/doc/spec=2fcontrol.html
この中のwhileに関する説明の一番下にこう書かれています。
while は nil を返します。
はっきり書かれてますね(笑)
なぜそういうふうになっているのかは書いてありませんが、そうなっているもんは仕方ない。
今回はそう割り切りましょう。ということで、
結論は、「Rubyのルールでそうなっているから」です。
7. 感想
なんか予想外な感じになってしまいました。
でも、まあ、すっきりできたかな?
さて、気を取り直して、
今後学習を進めていくにあたって、事情がない限り、returnメソッドを書いておこうと思いました。
実は、"return count" と書かずに直接 "count" と書いても同じ結果になります。
でもそれだとその記述が何をしているのかわかりません。ループの有無に関わらず、他のプログラマーのためにも、コードを見やすくしたり、そのメソッドが何をしているのかがわかりやすいように書いた方が良さそうです。
いかがだったでしょうか。
今回二回目の投稿ですが、学んだことは、
1) 疑問に思ったことは、自分で仮説を立てて、実験して、結果から自分なりの答えを出すことがとても大事ということ。
2) その過程は実は楽しいこと。
3) その過程の中でいろいろと調べるので、途中で答えが見つかることもあるということ。
4) ブログという形でアウトプットすることは思った以上に緊張するし怖い部分があるが予想以上に学びがあること
です。いいねをもらえたり、ストックしていただけるのもとても励みになります。
ありがとうございます。m(_ _)m今回は以上です。ありがとうございました。
おまけ
リファレンスマニュアルに
また、引数を伴った break により while 式の戻り値をその値にすることもできます。
と書かれていたので調べてみました。
https://hydrocul.github.io/wiki/programming_languages_diff/control_flow/break.html#ruby
breakの後ろに数字あるいは変数を書くといいみたいです。
def test(count) while count <=10 puts "10より大きい数字を入力してください。" count = gets.to_i break count ←ここです end end count = 0 count = test(count) if count.nil? puts "test(count)の戻り値はnilです。" else puts "test(count)の戻り値は#{count}です。" endやってみましょう。
「nil」になりませんでした!
もうお気づきかもしれませんが、これには問題が。。。そうです。ループされないんです。
ループの意味なし。
なんじゃこりゃ。。。。ということで 本当におしまいです。ありがとうございました。
- 投稿日:2020-02-16T14:21:34+09:00
Spreeで使われているfactorybot
spreeで使われているfactorybot。
勉強のために切り抜きました。参考までに。product_factory.rbFactoryBot.define do factory :base_product, class: Spree::Product do sequence(:name) { |n| "Product ##{n} - #{Kernel.rand(9999)}" } description { generate(:random_description) } price { 19.99 } cost_price { 17.00 } sku { generate(:sku) } available_on { 1.year.ago } deleted_at { nil } shipping_category { |r| Spree::ShippingCategory.first || r.association(:shipping_category) } # ensure stock item will be created for this products master before(:create) { create(:stock_location) unless Spree::StockLocation.any? } factory :custom_product do name { 'Custom Product' } price { 17.99 } tax_category { |r| Spree::TaxCategory.first || r.association(:tax_category) } end factory :product do tax_category { |r| Spree::TaxCategory.first || r.association(:tax_category) } factory :product_in_stock do after :create do |product| product.master.stock_items.first.adjust_count_on_hand(10) end end factory :product_with_option_types do after(:create) { |product| create(:product_option_type, product: product) } end end end endtaxon_factory.rbFactoryBot.define do factory :taxon, class: Spree::Taxon do sequence(:name) { |n| "taxon_#{n}" } association(:taxonomy, strategy: :create) parent_id { taxonomy.root.id } end endtaxonomy_factory.rbFactoryBot.define do factory :taxonomy, class: Spree::Taxonomy do sequence(:name) { |n| "taxonomy_#{n}" } end end詳細は本家githubのファイルで。
https://github.com/spree/spree/tree/master/core/lib/spree/testing_support/factories
- 投稿日:2020-02-16T13:27:00+09:00
RailsでJavaScriptでの遷移時にフラッシュを表示させる
やりたいこと
RailsでJavaScriptで遷移させるときに、フラッシュを表示させたい。
調べるとフラッシュに相当する文言を隠して( display: none とか?) おいて、JavaScriptで表示させる( display: block とか)の方法しかなかった。
GETパラメータで送るのヤダなぁと思ったので別の方法を考えた。やったこと
アクションを作ってフラッシュ付きでリダイレクトさせる
具体的にはこう。
items.jslocation.href = '/items/redirect_with_flash_message';items_controller.rbclass ItemsController < WebController def redirect_with_flash_message flash[:alert] = 'ログインが必要です' redirect_to new_user_session_path end endどうでもいいけどRailsのタグ、スペル間違ってない?
- 投稿日:2020-02-16T13:14:19+09:00
CarrierWaveでデフォルト画像の設定
CarrierWaveでユーザーアイコンの実装をしていたのですが、デフォルト画像の表示で少し躓いてしまったのでメモしておきます。
前提
- CarrierWaveは導入済み
- 登録した画像表示はできる
image_uploader.rbの設定
CarrierWaveを入れたときに
$ rails g uploader imageをしたらimage_uploader.rbというファイルが生成されます。
このファイルを以下のようにいじってください。
image_uploader.rb#アップロードした画像の表示 # Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end #デフォルト画像の設定 # Provide a default URL as a default if there hasn't been a file uploaded: def default_url(*args) # For Rails 3.1+ asset pipeline compatibility: ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) # "/images/fallback/" + [version_name, "default.png"].compact.join('_') endこれで登録時にファイル選択をしなかった場合、デフォルト画像をimageとして渡す準備ができました。
assets/images配下に画像を設置
assets/images配下にデフォルト画像を設置してください。
画像名はこの場合「default.png」にしときましょう。Viewの設定
Viewに、if文でユーザーのimageがある場合とない場合で表示が変わるように設定してあげましょう。
以下は例です。
_show.html.erb<% if post.user.image? %> <img src='<%= post.user.image %>' class="icon" alt="ユーザーアイコン"> <% else %> <image src="/assets/default.png" class="icon" alt="ユーザーアイコン" %> <% end %>まとめ
CarrierWaveさんは非常に便利なのですが、デフォルト画像設置に関しては画像パスとして渡っているので、dbを調べてもnullとしか表示されず焦ってしまうというパターンがよくあるようです。
よく使う機能だとは思いますので、誰かの助けになれば幸いです。
ではでは。
- 投稿日:2020-02-16T13:07:35+09:00
ツイッターデベロッパーでのapp作成手順
前回の記事で、TwitterAPIの利用申請が完了しました。
実際にRubyでbotを作成するには、デベロッパー上でappを作成する必要がありますので、本記事ではその手順を記載します。
手順1 Appの名称と説明を入力する
作成するAppの名称をApp name欄に入力してください。
(すでに登録されている名称は使用できません。)Application description欄には、アプリの説明を記載してください。簡単にで問題ありません。
手順2 必須のURLを入力する
Website URL、Callback URLを入力してください。
本来は本番環境でのURLを入力する欄ですが、とりあえず登録段階ではキータの自分のページや、ツイッターのトップページ等でも問題ありません。
開発段階では、
http://localhost:3000/
と記載したいところですが、2020年2月時点では認められませんでした。
※この部分については、キータでも記事によって記入方法が異なると思います。
しかし、登録の段階では何でも良いので入るものを入れてしまいましょう。
手順3 Appの使用方法について説明する
開発予定のアプリケーションがどのように使用されるのか記載しましょう。
簡単にで問題ありません。記入が完了したら、Createボタンを押してください。
その後出てくるポップアップ画面でも、Createボタンを押してください。
手順4 登録内容を確認する
以下のような画面が表示されたら登録完了です。
内容を変更したい場合は、右上のEditボタンから編集してください。
以上で登録作業は完了です。
次の記事では、登録したAppを使用して、実際にRubyファイルからツイートする方法を解説します。最後まで読んでいただきありがとうございました。
- 投稿日:2020-02-16T11:26:00+09:00
RubyでルールのあるSortプログラムを作る
はじめに
rubyでオリジナルのソートを作るためのメモ
JSONが入っているのは自分のローカルサーバで作りやすかったからコード
ruby.rbrequire 'json' $jsonfile = <<EOF [{"id":643,"name":"7_to_7_3","tag":"ミットナイトレストラン7to703,胡桃ちの,漫画","created_at":"2018-12-02T11:30:34.013Z","updated_at":"2018-12-02T11:30:34.013Z"}, {"id":644,"name":"7_to_7_4","tag":"ミットナイトレストラン7to704,胡桃ちの,漫画","created_at":"2018-12-02T11:31:05.979Z","updated_at":"2018-12-02T11:31:05.979Z"}, {"id":641,"name":"7_to_7_10","tag":"ミットナイトレストラン7to710,胡桃ちの,漫画","created_at":"2018-11-29T12:01:43.992Z","updated_at":"2018-11-29T12:01:43.992Z"}, {"id":645,"name":"7_to_7_11","tag":"ミットナイトレストラン7to711,胡桃ちの,漫画","created_at":"2018-12-02T11:31:47.163Z","updated_at":"2018-12-02T11:31:47.163Z"}] EOF def num_kaiseki(str) output = [] tmp = str num = str.rindex(/[0-9]/) out ="" count = 0 if (num !=nil) while(tmp[num-count]) if (tmp[num-count]=="_") elsif (tmp[num-count].index(/[0-9]/)==nil) if(out[0]==".") out = out[1..tmp.size] end break end if (tmp[num-count]=="_") out = "."+out else out = tmp[num-count]+out end count+=1 end else num = tmp.size end output = [tmp[0..tmp.size-out.size-1] ,out.to_f] end def sort_jouken(a,b) t_a = num_kaiseki(a) t_b = num_kaiseki(b) if (t_a[0] == t_b[0]) output = t_a[1]<=>t_b[1] else output = t_a[0]<=>t_b[0] end output end list = JSON.parse($jsonfile) list.each do |word| p num_kaiseki(word["name"]) end bb = list.sort { |a,b| sort_jouken(a["name"],b["name"]) } bb.each do|word| print word["id"],":",word["name"],"," end不満点
小数点のルール条件めちゃくちゃだから、どうにかしないと
- 投稿日:2020-02-16T04:06:47+09:00
FontAwesomeの導入
FontAwesomeとは?
ウェブフォントの一種。
文字を扱うのと同じようにアイコンを表示させることができる。導入方法
FontAwesome用のGemがをインストールする。
全ての環境で使用したいので、最下部に以下のコードを記載する。Gemfilegem 'font-awesome-sass'bundle installとサーバ再起動を忘れずに。
assetsフォルダに書き込み
application.scss@import "font-awesome-sprockets"; @import "font-awesome";補足
CSSの仕様で、paddingなどの設定を行った場合、その要素全体のサイズが
大きくなる場合がある。以下の記述を追加すると、paddingやborderの設定を行っても、
要素の大きさがwidthやheightで指定したサイズが維持される。messeges.scss* { box-sizing: border-box; }「*」は、全ての要素に適用させるという意味
- 投稿日:2020-02-16T03:17:00+09:00
rails 基礎講義資料2章 Scaffold を用いた高速なアプリケーション構築 及び MVCの理解
1章:環境構築
2章:Scaffold を用いた高速なアプリケーション構築 及び MVCの理解
3章:Scaffold を用いない開発方法 及び 応用1.Scaffold
この章では、Railsの強力な機能をいくつか紹介するためのアプリケーションを作成します。
大量の機能を自動的に生成するscaffoldジェネレータというスクリプトを使って蔵書管理アプリケーションを生成し、
それを元にRailsの概要を一緒にみていきましょう。*3章以降では、scaffold は使わずに、自力で作る方法を学びます。
scaffold コマンド
まずは、名前と学籍番号を登録できるだけの機能を作成します。
下記のコマンドは一字一句間違いなくタイプするか、コピペで行ってください。失敗した場合は、下記のページに解決策が記載してあります。(すこし複雑です)
scaffold作成時にカラム名(属性名)を打ち間違えた場合の修正手順terminal$bin/rails generate scaffold User name:string number:integer
Railsのscaffoldは、rails generateスクリプトにscaffoldコマンドを渡すことで生成されます。scaffoldコマンドの引数には、リソース名を単数形にしたもの (この場合はUser) を使い、必要に応じてデータモデルの属性をオプションとしてパラメータに追加します
リソースとは、コントローラが扱う対象に名前をつけたものです。
例:モデル、画像、セッション...etc自動で多数のファイルが生成されたとおもいます。
その中で重要なのは次のファイルです。terminalcreate app/models/user.rb create app/views/users/(略) create app/controllers/users_controller.rb route resources :users
ここで生成された Models Views Controllers の頭文字をとって
MVC と呼びます。MVCについては後ほど、説明します。データベースの利用
このアプリケーションではデータを保存するために、データベースを扱います。
下記コマンドを実行することで、データベースに users という名前のテーブルが作成されます。terminal$bin/rails db:migrate
下記のような結果が表示されていればテーブルの生成ができています。
(migrate については今後の章で解説します)terminal== CreateUsers: migrating ============================= -- create_table(:users) -> 0.0007s == CreateUsers: migrated (0.007s) =============================コマンド実行後に、結果の文章を読む癖もつけていきましょう
初学者が陥る問題に、terminalにエラー文が表示されているにも関わらず気付かない問題があります。
エラー文を見つけた場合は、エラー文をそのまま検索することで解決策を見つけることも難しくありません。
コマンド実行の結果、どういったことが行われているのかを見ることも理解を深めることに役立ちます。いま実行した2行で下記の機能が自動的に生成されています。
・ユーザーの作成
・ユーザーの一覧表示
・ユーザーの編集
・ユーザーの削除試しにサーバーを起動してみましょう。
terminal$bin/rails server
ブラウザで開いてみましょう。
下記URLにアクセスすると。それに対応した機能が呼び出されます。
一覧表示
http://localhost:3000/users
新規作成
http://localhost:3000/users/new
ユーザー表示
http://localhost:3000/users/1
ユーザー編集
http://localhost:3000/users/1/editたった2行で想像以上の機能が実装されてしまい驚きと困惑があると思います。
多くの初学者が、何が起きたのかわからず Rails を魔法のように感じてしまいます。自動で作られたファイルについて、簡略的な説明を行っていきます。
3章以降で、いちからつくるので事前に概要を知っておくことは、
今後の理解を深める上で重要です。ルーティング
まずはどの機能が、どのURLと紐付いているかですが、
下記のコマンドで確認できます。terminal$bin/rails routes
下記のような表示がなされていると思います。
GET /users(.:format) users#index POST /users(.:format) users#create GET /users/new(.:format) users#new GET /users/:id/edit(.:format) users#edit GET /users/:id(.:format) users#show PUT /users/:id(.:format) users#update DELETE /users/:id(.:format) users#destroyよくみると、show update destroy がすべて /users/:id という同じURLになっています。
同じURLでも機能が異なるのは、利用しているHTTPメソッドが異なるためです。show : GET データの取得
update : PUTデータの送信(主に更新の際)
destroy : DELETE:データの削除
HTTPメソッドについて、もっと知りたい方はこちらをご覧ください
https://tsuyopon.xyz/2019/01/31/understand-4-http-methods/この紐付け(ルーティング)は、scaffold によって自動的に行われたものですが、
自力で行う場合には config/routes.rb の中に結びつけを書いていきます。
いまは 紐付けは routes.rb で行われている。 とだけ覚えてもらえば大丈夫です。
3章以降で詳しく説明していきます。紐付けと言われても、すこし伝わりづらいとおもいます。
ルーティングの見方を、例をあげて説明します。
/users に対するルーティングをみると
GET /users(.:format) users#index
と書かれています。これは usersコントローラーの index アクションを呼び出す
と理解してください。コントローラー (app/controllers/users_controller.rb) を見てみると下記のコードが書かれています。
users_controller.rbdef index @users = User.all endUserモデルからもらったすべてのデータを、変数@users に代入せよ
という意味です。開かれる htmlファイルはどこにあるのでしょう?
実は Rails では、特に指定をしない場合、
アクション名.html.erb が自動的に呼び出されます。
重要なので覚えておいてください。
app/views/users/index.html.erb が呼びされます。ここまでの流れをまとめると、下記のようになります。
①URLにアクセスがあった場合
②ルーティングに従ってコントローラーが呼び出され
③モデルを経由してデータを受け取り、コントローラーにデータを返し
④コントローラーのアクションに従って、データがビューに渡され
⑤ビューは受け取ったデータを利用して、HTMLを生成する上記は、Rails を理解する上で重要な流れなので、覚えておいてください。
MVC(Model View Controller)については後ほど詳しく説明しますが、
Modelは、データベースとのやりとりを担う
Viewは、表示関連全般を担う
Controllerは、橋渡しの役割を担う
と、大まかにご理解ください。理屈だけより実際に触れてみると理解が深まるとおもうので、
一連のながれを体感するために、View と Controller を触っていきましょう。2.View
ページの編集
ブラウザから一覧ページを開いてみましょう
http://localhost:3000/usersまずは、メンバー一覧表示ページを編集してみましょう。
編集するファイルは、app/views/users/index.html.erb です。
3行目 h1タグ内の、 Users の部分を下記のように置き換えてみましょう。index.html.erb<h1>ユーザーの一覧</h1>編集が完了したら、上書き保存し、ブラウザを更新してください。
編集が反映されていれば成功です。erb
ERBとは、Embedded RuBy の略であり、Rubyを埋め込めるHTMLファイルのようなものと
いまは思っておいて頂いて結構です。ERBは、HTMLテンプレートエンジンと呼ばれ、他にも haml slim などあるので
興味がある方は、調べてみてください。Ruby の埋め込みも体験してみましょう。
erb 内に下記のコードを記述することで、その中にrubyを埋め込むことができます。<% %> この中にRubyコードを記述できる。
<%= %> この中に書かれた Ruby は文字列として出力される。erb:変数の利用
index.html.erb の1行目に下記の2行を追加してください。
index.html.erb<% name = "Player" %> <%= "ようこそ #{name} さん" %>Ruby と同様に、変数の代入と展開が行われ
ようこそ Playerさん と表示されます。Timeクラスの利用
下記のように追加すると、今日の日付が表示されます。
index.html.erb<% t = Time.now %> <%= "いまの時刻は #{t} です" %></br> <%= "今日は #{t.month} 月 #{t.day} 日です" %></br> <%= "一週間前は #{t.weeks_ago(1)} 日です" %></br> <%= "一週間前は #{t.weeks_ago(1).month} 月 #{t.weeks_ago(1).day} 日です" %>【課題1】 erbの変更
5分ほど使って index.html.erb を自由に変更してみてください。
変更例)日本語化
1, name,number をそれぞれ、名前,学籍番号 に変更
2, New user を、新規ユーザー作成 に変更
3, Show,Edit,Destoroy を 表示、編集、削除 に変更
4, Ruby のコードをerbの中に書いてみる...etbつづいてコントローラーをみていきましょう。
3.Controller
Controller から View への、データの受け渡しを確認
Controllerは、クライアント Model View の仲介を担っています。
Controller名は、複数形にする(命名規則)再度、コントローラー (app/controllers/users_controller.rb) の下記の行をみてください。
users_controller.rbdef index @users = User.all endこれは、Userモデルからもらったすべてのデータを、変数@users に代入せよ
という意味でした。今回はデータベースを使わずに、データを作成してみましょう。
(このあと Model の項目で、データベースを利用するように置き換えます)@book という連想配列を作成し、その中に情報を書き込んでいきます。
users_controller.rbdef index @users = User.all @book = Hash.new @book[:country] = "Japan" @book[:title] = "吾輩は猫である" @book[:author] = "夏目漱石" @book[:year] = 1905 @book[:book_id] = 1 @book[:comment] = "おもしろかった" end@book[:title] Hash(連想配列)のSymbolです。お忘れの方は
Array(配列)とHash(連想配列)入門
を御覧ください。本の情報を @book 連想配列に追加したので、 View で受け取れるか確認してみましょう。
(def index に記載しているので、 index.html.erb で受け取れます)index.html.erb<%= @book %></br> <%= "本のタイトルは #{@book[:title]} です" %></br> <%= "著者は #{@book[:author]} です" %></br>http://localhost:3000/users
ブラウザを更新すると下記のように表示されます。{:country=>"Japan", :title=>"吾輩は猫である", :author=>"夏目漱石", :year=>1905,
:book_id=>1, :comment=>"おもしろかった"}
本のタイトルは 吾輩は猫である です
著者は 夏目漱石 です無事、情報を受け取れていますね。
erbの応用
ここに和書かどうかを調べる機能を追加してみましょう。
erb はRubyが使えるので、条件分岐も利用できます下記のコードを追加してみましょう。
index.html.erb<% if @book[:country] == "Japan" %> <p>この本は、和書です</p> <% end %>この本は、和書です
と表示されます。すこし蔵書管理アプリっぽくなりました。
蔵書データを増やしていきたいところですが、問題があります。
Controller に書くには蔵書データはあまりに多すぎるという問題です。
(そしてユーザーは追記できない)これを解決するのが、データベースとModelです。
@book に関するコードは、すべて消してしまいましょう。
4.Model
Books リソースの作成
Modelは基本的に、1つのテーブルに対して1つのModelを作成します。
Model名は、複数形にする(命名規則)人に関するリソースは作成したので、本に関するリソースも作成していきましょう。
(usersテーブルとは、別にbooksテーブルを作成するので、Book Modelを作成します)再度、Scaffold を実行します。
terminal$bin/rails generate scaffold Book country:text title:text author:text year:integer user_id:integer comment:text
Users リソースの時と同様に、自動で多くのファイルが作成されます。
Model View Controller route もそれぞれ作成されています。terminalcreate app/models/book.rb create app/views/books/(略) create app/controllers/books_controller.rb route resources :books
前回同様、下記コマンドを実行することで、データベースに books という名前のテーブルが作成されます。
terminal$bin/rails db:migrate
ルーティングも確認してみましょう。
terminal$bin/rails routes
下記のように、紐付けされていることが確認できます。
GET /books(.:format) books#index POST /books(.:format) books#create GET /books/new(.:format) books#new GET /books/:id/edit(.:format) books#edit GET /books/:id(.:format) books#show PUT /books/:id(.:format) books#update DELETE /books/:id(.:format) books#destroyブラウザで確認してみましょう。本の情報を入力できるようになっています。
http://localhost:3000/users/newこのままではユーザーは自由に投稿できる状態です。
year と user_id は数値を入力してもらいたいので入力制限をかけてみましょう。Rails では制限(validation)も簡単に設定することができます。
Validation
app/models/book.rb を開き下記のように編集してください。
book.rbclass Book < ApplicationRecord validates :year, :user_id, numericality: true endこの1行だけで制限を設けることができます。
Book Model に追記しているので、 books テーブルの yearカラム と user_idカラムに対して制限をかけます。
実際に試してみると、下記のようなエラー文が表示されます。
【課題2】自作バリデーション
Railsバリデーションまとめ
を参考にして、制限を設けてみましょう。
例)
1, Title を空白禁止にする
2, 著者の名前を125文字以内にする ...etcバリデーションがうまくかけたかを試すために、
実際にブラウザから本のデータを2件登録してみてください。内容は自由で良いですが、 user の項目だけは 1 にしてください
rails console
うまく情報が登録されたかを確認するために、データベースから情報を取り出してみましょう。
SQL文が苦手な方もご安心ください。
Rails console を使えば、簡単にデータを取り出してみることができます。新規ターミナルを起動し、下記のコマンドを実行してください。
terminal$bin/rails c
すると >> といった表示がされるとおもいます。これでrails console が起動しました。
( exit 入力し、Enterを実行すると終了します )試しに、最初に登録したユーザー情報を、(Model を経由し)データベースから取り出してみましょう
railsConsole>> user = User.find(1)user はただの変数です。(名前は自由ですが、わかりやすく use にしました)
User.find(1) は User Model を利用して、 1番目の人を取り出せ
という意味ですので、 U は大文字です。(Model は頭文字が大文字で単数形でしたね)さきほど、ブラウザから入力したデータが登録されていると思います。
【課題3】 rails c を使った、データの取り出し
本のデータを取り出して表示してみましょう。
その際に、find(1) 意外の取り出し方も試してみましょう。
データ取得メソッドまとめ
例) .all を使用してみる。MVC総合 User が所持しているデータを表示してみる。
さてここまでで、冒頭に説明した下記の役割を体験してみました。
Modelは、データベースとのやりとりを担う
Viewは、表示関連全般を担う
Controllerは、橋渡しの役割を担うなにもわからなかった状態から、
ルーティング・DB・コンソール・MVC
と多くのことを吸収し、成長を感じられると思います。まだ大まかな理解だと思うので、更に理解を深めるべく
応用課題に取り組んでいきましょう!id: 1 のUserが所持している本のデータを取り出してみましょう。
ブラウザでの表示は View を編集する必要があり大変なので
まずは console の中で、取り出しを確認するところだけみていきましょう。
(小さく着実に作っていくことは大事です)rails console を起動した端末にて下記のコマンドを実行します。
railsConsole>> user = User.find(1) >> user.booksと入力することで、 id:1 のuserが持っている本のデータ
(booksテーブルの中で、 user_id を 1 にした本のデータ)
がすべて表示されます!.
..
...
されないとおもいます。
実行結果を見てみると、エラー文が出ていますねrailsconsole>> user.books Traceback (most recent call last): 1: from (irb):2 NoMethodError (undefined method `books' for #<User:0x00007fa63942dce0>)NoMethodError undefined method `books'
これは、 books がなにかわからない。定義されていない。という意味のエラーです。
(今後良くみかけることになるとおもいます。タイピングミスしてもこのエラーが表示されます)今回の原因は、 user テーブルと books テーブルが紐付いていないことによるものです。
booksテーブルで勝手に user_id というカラムを追加しただけで、
userテーブルにはなにも書いていないので当然ですね。
Userモデルから、bookテーブルのデータを取得できないのでエラーが出ています
こういったテーブル同士の紐付けも、Railsでは1行で出来ます。has_many belongs_to
いま、 users と books の2つのテーブルがあります。
どの蔵書データが、どのユーザーに紐付いているのかといった関連付けを行いたいとき
どうすれば良いのかを学んでいきます。1,一人のuserは、たくさんの本を持っています
こういう場合、 user.rb (UserのModel)に、
has_many :books (たくさんなので、複数形です)
と1行追加するだけで、上記のような紐付けが完了します。2,1冊の本は、一人のUserに紐付いています
こういう場合、 book.rb (BookのModel)に、
belongs_to :user (ひとつなので、単数形です)
と追加するだけで、上記のような紐付けが完了します。user.rbclass Book < ApplicationRecord has_many :books endbook.rbclass Book < ApplicationRecord belongs_to :user validates :year, :user_id, numericality: true endhas_many belongs_to コード追加が終われば
rails console を立ち上げ直してください
(exitとタイプしEnterで終了できます)再度 rails c を起動し、さきほどと同じコマンドを実行するとどう変わっているでしょうか。
railsConsole>> user = User.find(1) >> user.books↓出力結果例
railsConsoleLoading development environment >> user = User.find(1) User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] => #<User id: 1, name: "daichi", number: 10 >> user.books Book Load (0.1ms) SELECT "books".* FROM "books" WHERE "books"."user_id" = ? LIMIT ? [["user_id", 1], ["LIMIT", 11]] => #<ActiveRecord::Associations::CollectionProxy [#<Book id: 1, country: "Japan", title: "吾輩は猫である", author: "夏目漱石", year: 1905, user_id: 1, comment: "おもしろかった"紐付けられたことでエラーが解消され、上記のような結果が表示されます。
テーブルに関連性を持たせたいときは has_many belongs_to を使用すること
覚えておいてください。Modelにて、データベース内のテーブルの関連づけは出来き、
user.books にてユーザーが持っている本のデータを取り出せることが確認できました。さて、Modelで取り出したデータを、View に送るにはどうすればよかったでしょうか?
そうですね。Controller の役割でしたね。Controller
app/controllers/users_controller.rb
をひらきます(@bookを消していない人は消しておいてください)前回は、index.html.erb に情報を渡したかったので index アクションに
@book のデータを(データベースを使わずに直接)書きました。今回は、show.html.erb に情報を渡したいので、 show アクションに
モデルを用いて、データを取り出すコードを書きますapp/controllers/users_controller.rbdef show @user = User.find(1) @books = @user.books end(小文字大文字, s の有無に気をつけてください)
最後に、Controller から送られてきたデータの表示の部分をやっていきます。View
表示させたい場所は、1番目のユーザーのページなのでこちらです
http://localhost:3000/users/1【MVCの流れの復習】
ちなみに、ルーティングには下記のように書いてあります
GET /users/:id users#show
users/(idの数字) にGETリクエストがあったら users controller の show アクションを実行でしたね。
show アクションが、実行されたら自動的に、 show.html.erb が表示されるのでした。show.html.erb の一番上に下記コードを追記してください。
app/views/users/show.html.erb<% @books.each do |book| %> <p><%= "本のタイトルは #{book[:title]} です" %></p> <p><%= "著者は #{book[:author]} です" %></p></br> <% end %>これで、 Controller から受け取った @books (本の情報が格納された連想配列)
の中身が表示されていると思います。
(配列の中身を順番に取り出していくときは each でした。 Ruby をお忘れの方は復習を)【最終課題】
show.html.erb を自由に編集してください
例)
・本の情報をすべて表示まとめ
以上で、scaffold を用いた、高速蔵書アプリケーションの制作講座は終わりです。
お疲れ様でした。3章では、scaffold が自動生成していた部分を、1から自分で制作していきます。
今回の内容を再度読み返すか、もう一度素早く作成して復習をしておいてください。
- 投稿日:2020-02-16T03:17:00+09:00
Before Rails Tutorial2章 Scaffold を用いた高速なアプリケーション構築 及び MVCの理解
本投稿は講義資料であり、Rubyの基礎は理解しているが、rails tutorialで躓く読者を対象としています。
1章:環境構築
2章:Scaffold を用いた高速なアプリケーション構築 及び MVCの理解
3章:Scaffold を用いない開発方法 及び 応用1.Scaffold
この章では、Railsの強力な機能をいくつか紹介するためのアプリケーションを作成します。
大量の機能を自動的に生成するscaffoldジェネレータというスクリプトを使って蔵書管理アプリケーションを生成し、それを元にRailsの概要を一緒にみていきましょう。*3章以降では、scaffold は使わずに、自力で作る方法を学びます。
scaffold コマンド
まずは、名前と学籍番号を登録できるだけの機能を作成します。
下記のコマンドは一字一句間違いなくタイプするか、コピペで行ってください。失敗した場合は、下記のページに解決策が記載してあります。(すこし複雑です)
scaffold作成時にカラム名(属性名)を打ち間違えた場合の修正手順terminal$bin/rails generate scaffold User name:string number:integer
Railsのscaffoldは、rails generateスクリプトにscaffoldコマンドを渡すことで生成されます。scaffoldコマンドの引数には、リソース名を単数形にしたもの (この場合はUser) を使い、必要に応じてデータモデルの属性をオプションとしてパラメータに追加します
リソースとは、コントローラが扱う対象に名前をつけたものです。
例:モデル、画像、セッション...etc自動で多数のファイルが生成されたとおもいます。
その中で重要なのは次のファイルです。terminalcreate app/models/user.rb create app/views/users/(略) create app/controllers/users_controller.rb route resources :users
ここで生成された Models Views Controllers の頭文字をとって
MVC と呼びます。MVCについては後ほど、説明します。データベースの利用
このアプリケーションではデータを保存するために、データベースを扱います。
下記コマンドを実行することで、データベースに users という名前のテーブルが作成されます。terminal$bin/rails db:migrate
下記のような結果が表示されていればテーブルの生成ができています。
(migrate については今後の章で解説します)terminal== CreateUsers: migrating ============================= -- create_table(:users) -> 0.0007s == CreateUsers: migrated (0.007s) =============================コマンド実行後に、結果の文章を読む癖もつけていきましょう
初学者が陥る問題に、terminalにエラー文が表示されているにも関わらず気付かない問題があります。
エラー文を見つけた場合は、エラー文をそのまま検索することで解決策を見つけることも難しくありません。
コマンド実行の結果、どういったことが行われているのかを見ることも理解を深めることに役立ちます。いま実行した2行で下記の機能が自動的に生成されています。
・ユーザーの作成
・ユーザーの一覧表示
・ユーザーの編集
・ユーザーの削除試しにサーバーを起動してみましょう。
terminal$bin/rails server
ブラウザで開いてみましょう。
下記URLにアクセスすると。それに対応した機能が呼び出されます。
一覧表示
http://localhost:3000/users
新規作成
http://localhost:3000/users/new
ユーザー表示
http://localhost:3000/users/1
ユーザー編集
http://localhost:3000/users/1/editたった2行で想像以上の機能が実装されてしまい驚きと困惑があると思います。
多くの初学者が、何が起きたのかわからず Rails を魔法のように感じてしまいます。自動で作られたファイルについて、簡略的な説明を行っていきます。
3章以降で、いちからつくるので事前に概要を知っておくことは、
今後の理解を深める上で重要です。ルーティング
まずはどの機能が、どのURLと紐付いているかですが、
下記のコマンドで確認できます。terminal$bin/rails routes
下記のような表示がなされていると思います。
GET /users(.:format) users#index POST /users(.:format) users#create GET /users/new(.:format) users#new GET /users/:id/edit(.:format) users#edit GET /users/:id(.:format) users#show PUT /users/:id(.:format) users#update DELETE /users/:id(.:format) users#destroyよくみると、show update destroy がすべて /users/:id という同じURLになっています。
同じURLでも機能が異なるのは、利用しているHTTPメソッドが異なるためです。show : GET データの取得
update : PUTデータの送信(主に更新の際)
destroy : DELETE:データの削除
HTTPメソッドについて、もっと知りたい方はこちらをご覧ください
https://tsuyopon.xyz/2019/01/31/understand-4-http-methods/この紐付け(ルーティング)は、scaffold によって自動的に行われたものですが、
自力で行う場合には config/routes.rb の中に結びつけを書いていきます。
いまは 紐付けは routes.rb で行われている。 とだけ覚えてもらえば大丈夫です。
3章以降で詳しく説明していきます。紐付けと言われても、すこし伝わりづらいとおもいます。
ルーティングの見方を、例をあげて説明します。
/users に対するルーティングをみると
GET /users(.:format) users#index
と書かれています。これは usersコントローラーの index アクションを呼び出す
と理解してください。コントローラー (app/controllers/users_controller.rb) を見てみると下記のコードが書かれています。
users_controller.rbdef index @users = User.all endUserモデルからもらったすべてのデータを、変数@users に代入せよ
という意味です。開かれる htmlファイルはどこにあるのでしょう?
実は Rails では、特に指定をしない場合、
アクション名.html.erb が自動的に呼び出されます。
重要なので覚えておいてください。
app/views/users/index.html.erb が呼びされます。ここまでの流れをまとめると、下記のようになります。
①URLにアクセスがあった場合
②ルーティングに従ってコントローラーが呼び出され
③モデルを経由してデータを受け取り、コントローラーにデータを返し
④コントローラーのアクションに従って、データがビューに渡され
⑤ビューは受け取ったデータを利用して、HTMLを生成する上記は、Rails を理解する上で重要な流れなので、覚えておいてください。
MVC(Model View Controller)については後ほど詳しく説明しますが、
Modelは、データベースとのやりとりを担う
Viewは、表示関連全般を担う
Controllerは、橋渡しの役割を担う
と、大まかにご理解ください。理屈だけより実際に触れてみると理解が深まるとおもうので、
一連のながれを体感するために、View と Controller を触っていきましょう。2.View
ページの編集
ブラウザから一覧ページを開いてみましょう
http://localhost:3000/usersまずは、メンバー一覧表示ページを編集してみましょう。
編集するファイルは、app/views/users/index.html.erb です。
3行目 h1タグ内の、 Users の部分を下記のように置き換えてみましょう。index.html.erb<h1>ユーザーの一覧</h1>編集が完了したら、上書き保存し、ブラウザを更新してください。
編集が反映されていれば成功です。erb
ERBとは、Embedded RuBy の略であり、Rubyを埋め込めるHTMLファイルのようなものと
いまは思っておいて頂いて結構です。ERBは、HTMLテンプレートエンジンと呼ばれ、他にも haml slim などあるので
興味がある方は、調べてみてください。Ruby の埋め込みも体験してみましょう。
erb 内に下記のコードを記述することで、その中にrubyを埋め込むことができます。<% %> この中にRubyコードを記述できる。
<%= %> この中に書かれた Ruby は文字列として出力される。erb:変数の利用
index.html.erb の1行目に下記の2行を追加してください。
index.html.erb<% name = "Player" %> <%= "ようこそ #{name} さん" %>Ruby と同様に、変数の代入と展開が行われ
ようこそ Playerさん と表示されます。Timeクラスの利用
下記のように追加すると、今日の日付が表示されます。
index.html.erb<% t = Time.now %> <%= "いまの時刻は #{t} です" %></br> <%= "今日は #{t.month} 月 #{t.day} 日です" %></br> <%= "一週間前は #{t.weeks_ago(1)} 日です" %></br> <%= "一週間前は #{t.weeks_ago(1).month} 月 #{t.weeks_ago(1).day} 日です" %>【課題1】 erbの変更
5分ほど使って index.html.erb を自由に変更してみてください。
変更例)日本語化
1, name,number をそれぞれ、名前,学籍番号 に変更
2, New user を、新規ユーザー作成 に変更
3, Show,Edit,Destoroy を 表示、編集、削除 に変更
4, Ruby のコードをerbの中に書いてみる...etbつづいてコントローラーをみていきましょう。
3.Controller
Controller から View への、データの受け渡しを確認
Controllerは、クライアント Model View の仲介を担っています。
Controller名は、複数形にする(命名規則)再度、コントローラー (app/controllers/users_controller.rb) の下記の行をみてください。
users_controller.rbdef index @users = User.all endこれは、Userモデルからもらったすべてのデータを、変数@users に代入せよ
という意味でした。今回はデータベースを使わずに、データを作成してみましょう。
(このあと Model の項目で、データベースを利用するように置き換えます)@book という連想配列を作成し、その中に情報を書き込んでいきます。
users_controller.rbdef index @users = User.all @book = Hash.new @book[:country] = "Japan" @book[:title] = "吾輩は猫である" @book[:author] = "夏目漱石" @book[:year] = 1905 @book[:book_id] = 1 @book[:comment] = "おもしろかった" end@book[:title] Hash(連想配列)のSymbolです。お忘れの方は
Array(配列)とHash(連想配列)入門
を御覧ください。本の情報を @book 連想配列に追加したので、 View で受け取れるか確認してみましょう。
(def index に記載しているので、 index.html.erb で受け取れます)index.html.erb<%= @book %></br> <%= "本のタイトルは #{@book[:title]} です" %></br> <%= "著者は #{@book[:author]} です" %></br>http://localhost:3000/users
ブラウザを更新すると下記のように表示されます。{:country=>"Japan", :title=>"吾輩は猫である", :author=>"夏目漱石", :year=>1905,
:book_id=>1, :comment=>"おもしろかった"}
本のタイトルは 吾輩は猫である です
著者は 夏目漱石 です無事、情報を受け取れていますね。
erbの応用
ここに和書かどうかを調べる機能を追加してみましょう。
erb はRubyが使えるので、条件分岐も利用できます下記のコードを追加してみましょう。
index.html.erb<% if @book[:country] == "Japan" %> <p>この本は、和書です</p> <% end %>この本は、和書です
と表示されます。すこし蔵書管理アプリっぽくなりました。
蔵書データを増やしていきたいところですが、問題があります。
Controller に書くには蔵書データはあまりに多すぎるという問題です。
(そしてユーザーは追記できない)これを解決するのが、データベースとModelです。
@book に関するコードは、すべて消してしまいましょう。
4.Model
Books リソースの作成
Modelは基本的に、1つのテーブルに対して1つのModelを作成します。
Model名は、複数形にする(命名規則)人に関するリソースは作成したので、本に関するリソースも作成していきましょう。
(usersテーブルとは、別にbooksテーブルを作成するので、Book Modelを作成します)再度、Scaffold を実行します。
terminal$bin/rails generate scaffold Book country:text title:text author:text year:integer user_id:integer comment:text
Users リソースの時と同様に、自動で多くのファイルが作成されます。
Model View Controller route もそれぞれ作成されています。terminalcreate app/models/book.rb create app/views/books/(略) create app/controllers/books_controller.rb route resources :books
前回同様、下記コマンドを実行することで、データベースに books という名前のテーブルが作成されます。
terminal$bin/rails db:migrate
ルーティングも確認してみましょう。
terminal$bin/rails routes
下記のように、紐付けされていることが確認できます。
GET /books(.:format) books#index POST /books(.:format) books#create GET /books/new(.:format) books#new GET /books/:id/edit(.:format) books#edit GET /books/:id(.:format) books#show PUT /books/:id(.:format) books#update DELETE /books/:id(.:format) books#destroyブラウザで確認してみましょう。本の情報を入力できるようになっています。
http://localhost:3000/users/newこのままではユーザーは自由に投稿できる状態です。
year と user_id は数値を入力してもらいたいので入力制限をかけてみましょう。Rails では制限(validation)も簡単に設定することができます。
Validation
app/models/book.rb を開き下記のように編集してください。
book.rbclass Book < ApplicationRecord validates :year, :user_id, numericality: true endこの1行だけで制限を設けることができます。
Book Model に追記しているので、 books テーブルの yearカラム と user_idカラムに対して制限をかけます。
実際に試してみると、下記のようなエラー文が表示されます。
【課題2】自作バリデーション
Railsバリデーションまとめ
を参考にして、制限を設けてみましょう。
例)
1, Title を空白禁止にする
2, 著者の名前を125文字以内にする ...etcバリデーションがうまくかけたかを試すために、
実際にブラウザから本のデータを2件登録してみてください。内容は自由で良いですが、 user の項目だけは 1 にしてください
rails console
うまく情報が登録されたかを確認するために、データベースから情報を取り出してみましょう。
SQL文が苦手な方もご安心ください。
Rails console を使えば、簡単にデータを取り出してみることができます。新規ターミナルを起動し、下記のコマンドを実行してください。
terminal$bin/rails c
すると >> といった表示がされるとおもいます。これでrails console が起動しました。
( exit 入力し、Enterを実行すると終了します )試しに、最初に登録したユーザー情報を、(Model を経由し)データベースから取り出してみましょう
railsConsole>> user = User.find(1)user はただの変数です。(名前は自由ですが、わかりやすく use にしました)
User.find(1) は User Model を利用して、 1番目の人を取り出せ
という意味ですので、 U は大文字です。(Model は頭文字が大文字で単数形でしたね)さきほど、ブラウザから入力したデータが登録されていると思います。
【課題3】 rails c を使った、データの取り出し
本のデータを取り出して表示してみましょう。
その際に、find(1) 意外の取り出し方も試してみましょう。
データ取得メソッドまとめ
例) .all を使用してみる。MVC総合 User が所持しているデータを表示してみる。
さてここまでで、冒頭に説明した下記の役割を体験してみました。
Modelは、データベースとのやりとりを担う
Viewは、表示関連全般を担う
Controllerは、橋渡しの役割を担うなにもわからなかった状態から、
ルーティング・DB・コンソール・MVC
と多くのことを吸収し、成長を感じられると思います。まだ大まかな理解だと思うので、更に理解を深めるべく
応用課題に取り組んでいきましょう!id: 1 のUserが所持している本のデータを取り出してみましょう。
ブラウザでの表示は View を編集する必要があり大変なので
まずは console の中で、取り出しを確認するところだけみていきましょう。
(小さく着実に作っていくことは大事です)rails console を起動した端末にて下記のコマンドを実行します。
railsConsole>> user = User.find(1) >> user.booksと入力することで、 id:1 のuserが持っている本のデータ
(booksテーブルの中で、 user_id を 1 にした本のデータ)
がすべて表示されます!.
..
...
されないとおもいます。
実行結果を見てみると、エラー文が出ていますねrailsconsole>> user.books Traceback (most recent call last): 1: from (irb):2 NoMethodError (undefined method `books' for #<User:0x00007fa63942dce0>)NoMethodError undefined method `books'
これは、 books がなにかわからない。定義されていない。という意味のエラーです。
(今後良くみかけることになるとおもいます。タイピングミスしてもこのエラーが表示されます)今回の原因は、 user テーブルと books テーブルが紐付いていないことによるものです。
booksテーブルで勝手に user_id というカラムを追加しただけで、
userテーブルにはなにも書いていないので当然ですね。
Userモデルから、bookテーブルのデータを取得できないのでエラーが出ています
こういったテーブル同士の紐付けも、Railsでは1行で出来ます。has_many belongs_to
いま、 users と books の2つのテーブルがあります。
どの蔵書データが、どのユーザーに紐付いているのかといった関連付けを行いたいとき
どうすれば良いのかを学んでいきます。1,一人のuserは、たくさんの本を持っています
こういう場合、 user.rb (UserのModel)に、
has_many :books (たくさんなので、複数形です)
と1行追加するだけで、上記のような紐付けが完了します。2,1冊の本は、一人のUserに紐付いています
こういう場合、 book.rb (BookのModel)に、
belongs_to :user (ひとつなので、単数形です)
と追加するだけで、上記のような紐付けが完了します。user.rbclass Book < ApplicationRecord has_many :books endbook.rbclass Book < ApplicationRecord belongs_to :user validates :year, :user_id, numericality: true endhas_many belongs_to コード追加が終われば
rails console を立ち上げ直してください
(exitとタイプしEnterで終了できます)再度 rails c を起動し、さきほどと同じコマンドを実行するとどう変わっているでしょうか。
railsConsole>> user = User.find(1) >> user.books↓出力結果例
railsConsoleLoading development environment >> user = User.find(1) User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] => #<User id: 1, name: "daichi", number: 10 >> user.books Book Load (0.1ms) SELECT "books".* FROM "books" WHERE "books"."user_id" = ? LIMIT ? [["user_id", 1], ["LIMIT", 11]] => #<ActiveRecord::Associations::CollectionProxy [#<Book id: 1, country: "Japan", title: "吾輩は猫である", author: "夏目漱石", year: 1905, user_id: 1, comment: "おもしろかった"紐付けられたことでエラーが解消され、上記のような結果が表示されます。
テーブルに関連性を持たせたいときは has_many belongs_to を使用すること
覚えておいてください。Modelにて、データベース内のテーブルの関連づけは出来き、
user.books にてユーザーが持っている本のデータを取り出せることが確認できました。さて、Modelで取り出したデータを、View に送るにはどうすればよかったでしょうか?
そうですね。Controller の役割でしたね。Controller
app/controllers/users_controller.rb
をひらきます(@bookを消していない人は消しておいてください)前回は、index.html.erb に情報を渡したかったので index アクションに
@book のデータを(データベースを使わずに直接)書きました。今回は、show.html.erb に情報を渡したいので、 show アクションに
モデルを用いて、データを取り出すコードを書きますapp/controllers/users_controller.rbdef show @user = User.find(1) @books = @user.books end(小文字大文字, s の有無に気をつけてください)
最後に、Controller から送られてきたデータの表示の部分をやっていきます。View
表示させたい場所は、1番目のユーザーのページなのでこちらです
http://localhost:3000/users/1【MVCの流れの復習】
ちなみに、ルーティングには下記のように書いてあります
GET /users/:id users#show
users/(idの数字) にGETリクエストがあったら users controller の show アクションを実行でしたね。
show アクションが、実行されたら自動的に、 show.html.erb が表示されるのでした。show.html.erb の一番上に下記コードを追記してください。
app/views/users/show.html.erb<% @books.each do |book| %> <p><%= "本のタイトルは #{book[:title]} です" %></p> <p><%= "著者は #{book[:author]} です" %></p></br> <% end %>これで、 Controller から受け取った @books (本の情報が格納された連想配列)
の中身が表示されていると思います。
(配列の中身を順番に取り出していくときは each でした。 Ruby をお忘れの方は復習を)【最終課題】
show.html.erb を自由に編集してください
例)
・本の情報をすべて表示まとめ
以上で、scaffold を用いた、高速蔵書アプリケーションの制作講座は終わりです。
お疲れ様でした。3章では、scaffold が自動生成していた部分を、1から自分で制作していきます。
今回の内容を再度読み返すか、もう一度素早く作成して復習をしておいてください。
- 投稿日:2020-02-16T03:16:43+09:00
rails 基礎講義資料3章 Scaffold を用いない開発
1章:環境構築
2章:Scaffold を用いた高速なアプリケーション構築 及び MVCの理解
3章:Scaffold を用いない開発方法 及び 応用前章では、Scaffoldを用いて高速でアプリケーションを構築しました。
自動化された部分も多く、現段階では、大まかな理解であるとおもいます。今回は、route Model View Controller それぞれ自分で作っていきます。
とはいっても、継承まで含めてすべて書くには理解することが膨大で大変ですので、
前回も使用した generate は使用していきます。まずは、Railsの新しいアプリケーションを作成します。
1章:環境構築の内容を参考に作成してみましょう。terminal$ cd ~/rails_app $ mkdir bukukore $ bundle init (Gemfileにgem "rails","~> 5.2.3"を追加し保存してください) $ bundle install --path vendor/bundlesa $ bin/rails shttp://localhost:3000/ にアクセスして表示されていればokです。
$ rails s -p 3100 などとポートを変更することでサーバーを複数起動可能です。
この場合は http://localhost:3100/ にアクセスします。MVC 復習
前章では、アプリ制作を通して、MVCの流れを理解してきました。
Modelは、データベースとのやりとりを担う
Viewは、表示関連全般を担う
Controllerは、橋渡しの役割を担う前回、制作したながれを図を見ながら復習していきます。
それぞれの番号が、コードではどうなっていたか思い出しながら見てください。1, ブラウザから /users へのリクエストを Rails sever に送信する
2, router によって、/users は Users controller の index アクションを呼び出す
3, index アクションから、User Model が呼び出される
4, User Model は DataBase からデータを取り出す
5, 取り出したデータを、Controller に返す
6, 受け取ったデータを @users に保存し、 View (indexアクションなので index.html.erb) に渡す。
7, ERBを実行し、@users のデータを含んだ HTMLを生成し、Controller へ返す
8, Controller は、受け取ったHTMLをブラウザにわたす今回も Model View Controller を構築していくので、適宜図を見返してください。
Controller と View の作成
作成は基本的に generate コマンドを用います。
(gは generateコマンドの短縮形です)
g の後は、controller に続けて、コントローラーの名前(複数形)を書きます。
rails g controller Books index show new
そのうしろ(引数といいます)に書いたものは、同名のviewとアクションが自動生成されます。tarminal$ rails g controller Books index show new create app/controllers/books_controller.rb route get 'books/index' get 'books/show' get 'books/new' create app/views/books create app/views/books/index.html.erb create app/views/books/show.html.erb create app/views/books/new.html.erbルーティングが生成されているので、確認してみましょう。
terminal$ rails routes Verb URI Pattern GET /books/index books#index GET /books/show books#show GET /books/new books#newこれは具体的には、 http://localhost:3000/books/index
というURLに対するリクエストがあれば、 books_controller の index アクション を呼び出すというものでした。
今回アクションの中身が空なので、Model は呼び出されず、単に対応するView (index.html.erb) が実行されるだけです。ルーティングがうまくいってみるか確認するために、試しにアクセスしてみましょう。
http://localhost:3000/books/indexBooks#index
Find me in app/views/books/index.html.erbと表示されているとおもいます。
Viewの変更
erbの変更は前回行ったとおりですね。とてもシンプルなものでした。
Books#index の部分を、全蔵書一覧などに変更しておきましょう。app/views/books/index.html.erb<h1>全蔵書一覧</h1>erb の中身がシンプルすぎて不思議な方もいらっしゃるかもしれません。
【気になって次にすすめない人向けの解説】
app/views/layouts/application.html.erb を開いてください。
コード内の、<%= yiels %> の部分に、 index.html.erb が移植されて HTML を生成しています。
いまはこの程度の理解で問題ありません。 https://railstutorial.jp/ でより深く理解できます。Controllerの変更
コントローラーの中にアクションが本当に作られているかも確認してみましょう。
app/controllers/books_controller.rb を開いてみてください。app/controllers/books_controller.rbclass BooksController < ApplicationController def index end def show end def new end endデータベース内のデータを取り出すには、Controllerのアクションから
Model を呼び出せば良いのでした。app/controllers/books_controller.rbclass BooksController < ApplicationController def index end def show @book = Book.find(1) end def new end endこのままではエラーがでます。(Modelも、本の情報も作っていないので)
generate コマンドを使用して、Model を作成していきます。Model の作成
booksテーブルには、前章と同じカラムを持たせていきます。
terminal$ bin/rails g model Book country:text title:text author:text year:integer user_id:integer comment:text create db/migrate/20200202020202_create_books.rb create app/models/book.rbg の後は、model に続けて、Model名(単数形)を書きます。
データベースにテーブルを作成するには migrate を実行するのでしたね。terminla$ bin/rails db:migrate == 20200202020202 CreateBooks: migrating ====================================== -- create_table(:books) -> 0.0008s == 20200202020202 CreateBooks: migrated (0.0009s) =============================補足. migrate はマイグレーションファイルを実行しています。
db/migrate/(作成日時)_create_books.rb というファイルです。
ひらいてみると、下記のようなコードがあると思います。class CreateBooks < ActiveRecord
def change
create_table :books do |t|
t.text :country
t.text :title
t.text :author
t.integer :year
t.integer :user_id
t.text :comment
t.timestamps
end
end
end上記は text型であるcountryというカラム(他6つ)を持つ books テーブルを作成
せよという意味です。 change 意外に up down などもあります。詳細は下記サイトなどを参照ください
https://www.sejuku.net/blog/14229これでbooksテーブルが作成されました。
テーブルは作成したけども、本の情報はまだなにもいれてませんね。
初期データをいれるには db/seeds.rb ファイルを使用します。
( seed = 種 という意味です )
大量のデータを入力するのは手間なのでseed.rbを作成していきます。
(そもそもブラウザからデータをいれる機能もまだ作っていません)下記の seed ファイルを実行すると、bookテーブルに本の情報が3件保存されます
db/seeds.rb@book = Book.new @book.country = "jp" @book.title = "吾輩は猫である" @book.author = "夏目漱石" @book.year = 1905 @book.user_id = 1 @book.comment = "おもしろかった" @book.save @book = Book.new @book.country = "jp" @book.title = "人間失格" @book.author = "太宰治" @book.year = 1948 @book.user_id = 2 @book.comment = "すばらしかった" @book.save @book = Book.new @book.country = "gb" @book.title = "Alice's Adventures in Wonderland" @book.author = "Lewis Carroll" @book.year = 1865 @book.user_id = 1 @book.comment = "Amazing" @book.saveseed ファイルは、下記のコマンドで実行できます。
terminal$ bundle exec rake db:seedデータが保存されたかの確認は。rails c でコンソールを起動すると確認できます。
railsConsole@book = Book.find(1)ブラウザ(show)で表示してみましょう。
app/view/books/show.html.erb<p>本のタイトル: <%= @book.title %></p> <p>著者: <%= @book.author %></p>本のタイトル: 吾輩は猫である
著者: 夏目漱石
と表示されていればOKです。
課題1,
@book はどこで定義したか、再確認してください。
URLからパラメーターの取得
本のデータを取り出して表示するところまでうまくいきました!
すごい進歩です!ただ、まだ不満点があります。
それは、 id:1 の本のデータしか表示できていない点です。
理由は、Contoroller の show アクションをみると、
@book = Book.find(1)
となっているためです(id:1 の本の情報しか見つけてきていない)ここをidパラメーターが1以外も入力できるように変更するにはどうすればよいでしょうか。
@book = Book.find(params[:id])
とすることで、1以外のパラメーターを見つけてこれます。app/controllers/books_controller.rbdef show @book = Book.find(params[:id]) endパラメーター(数値)は、どこで指定すればよいでしょうか。
URL にパラメーターを含めて渡すテクニックがあるので覚えておきましょう。
例)ID:2の本の情報を取得したい場合 http://localhost:3000/books/show/2
このままではルーティングエラーが表示されます。
books/show へのリクエストに関しては記述していますが、
books/show/(数字) へのリクエストについてはなにも書いていない為です。config/routes.rb を開いてください。
URLに含まれる数字をパラメーターとして取得するには、下記のように記述します。config/routes.rb# get 'books/show'(# でコメントアウトしてます) get 'books/show/:id', to:'books#show'こうすることで /books/show/2 の 2の部分が、:id パラメーターとして利用可能になります。
( 利用するときは、params[:id] とかきます)to: 'books#show'
books Cコントローラーの show アクションを呼び出す指示になります。これで、任意のidの本情報を取得できるようになりました。
http://localhost:3000/books/show/1
http://localhost:3000/books/show/2Model 検索
いま本の情報の取り出しに id を利用していますが、
id 以外のカラムを用いて取り出す方法も覚えておくと便利です。コンソールを起動してください。 ( rails c )
下記を参考に色々と試してみてください。railsConsole>> Book.all #bookテーブルのすべてのデータを取得します。 >> Book.find_by(title: "人間失格") #条件に合ったデータを、1件だけ取得します。 >> Book.where(country: "jp") #条件に合ったデータを、すべて取得します。 >> Book.where(country: "jp").where(year: 1905) #AND検索。 和書で 1905年出版の本を取得しています。 >> Book.where("(country = ?) OR (year = ?)","jp",1905) #OR検索。 和書 または 1905年出版の本を取得しています。 >> Book.order(create_at: :asc) #並び順を指定します。 作成日時の昇順で取得しています。 >> Book.where(user_id: 1).order(id: :desc) #user_id 1さんの蔵書を、idの降順で取得しています。where の利用
検索条件を学んだのでこれ使って、蔵書管理アプリケーションらしく
個人の蔵書を一覧表示する機能を構築してみましょう。app/controllers/books_controller.rbdef show # @book = Book.find(params[:id]) コメントアウトしました。 @book = Book.where(user_id: params[:id]) enduser_id が パラメーター番号の人の蔵書データをすべて取得して@bookに格納しています。
View も編集していきましょう。 @book のなかに複数のデータがある場合(連想配列)
each を用いて、順に表示させていくのでしたね。(2章の復習です)app/views/books/show.html.erb<% @book.each do |book| %> <p>本のタイトル: <%= book.title %></p> <p>著者: <%= book.author %></p> <% end %>http://localhost:3000/books/show/1
にアクセスしてみると、 user_id:1 になっている本のデータがすべて表示されました。本のタイトル: 吾輩は猫である
著者: 夏目漱石本のタイトル: Alice's Adventures in Wonderland
著者: Lewis Carroll【補足】「あれ? has_many とかつけなくてよいんだっけ?」
と思った方は、前章の内容を覚えてくれていますね。
ただ少し勘違いがあります。 has_many,belongs_to は異なるテーブルの紐付けに使います。
今回は、 Book Modelを経由し、Bookテーブルだけにアクセスしているので不要です。
User Model から、Bookテーブルのデータを取り出すならば必要になってきます。データ登録フォームの作成
さて、データベースから情報を取り出したり加工したりする方法は覚えました。
しかしこのままではユーザーは、本を登録することができません。本を登録するための機能を作成する方法を学んでいきましょう。
登録形式は、フォーム。
URL は http://localhost:3000/books/new
とします。form_for
データベースに新しいデータを保存したいので、 Model を呼び出しましょう。
場所はどこに書きましょう。
new.html.erb に登録フォームを置くので、 new アクションの中ですね。
新しいデータを登録するときは、 Model名.new とします。下記のコードを追記してください。app/controllers/books_controller.rbdef new @book = Book.new endnew.html.erb に 入力フォームを作成していきましょう。
rails では、フォームを簡単につくれる form_forヘルパーというものがあります。app/views/books/new.html.erb<%= form_for(@book) do |f| %> <%= f.label :country %> <%= f.text_field :country %> <%= f.label :title %> <%= f.text_field :title %> <%= f.label :author %> <%= f.text_field :author %> <%= f.label :year %> <%= f.number_field :year %> <%= f.label :user_id %> <%= f.number_field :user_id %> <%= f.label :comment %> <%= f.text_area :comment %> <%= f.submit "送信" %> <% end %>form_for に関する詳しい使い方は、こちらのサイトで学習してください。
form_forの使い方を徹底解説!ここでは重要な部分だけ、簡単に解説します。
上の form_forヘルパーにより、下記のような HTML が生成されます。(少しシンプル化してます)new.html<form class="new_book" id="new_book" action="/books" method="post"> <label for="book_country">Country</label> <input type="text" name="book[country]" id="book_country" /> <label for="book_title">Title</label> <input type="text" name="book[title]" id="book_title" /> <label for="book_author">Author</label> <input type="text" name="book[author]" id="book_author" /> <label for="book_year">Year</label> <input type="number" name="book[year]" id="book_year" /> <label for="book_user_id">User</label> <input type="number" name="book[user_id]" id="book_user_id" /> <label for="book_comment">Comment</label> <textarea name="book[comment]" id="book_comment"> </textarea> <input type="submit" name="commit" value="送信" /> </form>ここで重要な属性は、
< form class="new_book" id="new_book" action="/books" method="post" >
の中の、 action="/books" と method="post" の2つです。この2つは送信ボタンが押されたら、
/books に対して、 POST リクエストを送信する
という指示をしています。なので、 /books 対して、 POST リクエストがあった場合の処理を書いていきましょう。
送信したあとは、books Controller の create アクションに飛ばしたいです。
(のちほどデータベースに保存する処理を create アクションに書いていきます)post 'books', to: 'books#create'
コードはこのようになるので、 routes.rb に追記しましょう。
(ルーティング関係は、 routes.rb でしたね)config/routes.rbRails.application.routes.draw do get 'books/index' get 'books/show/:id', to: 'books#show' get 'books/new' post 'books', to: 'books#create' endindex と new は to: が書かれていませんね。
前章でも説明したとおり、Railsは、アクションが呼び出されると、
自動的に アクション名.html.erbが呼び出されるので、
下記と同じ意味になります。
get 'books/index' to: 'books#index'
get 'books/new', to: 'books#new'1,登録ボタンが押される
2,フォームに入力されたデータを、create アクションに飛ばすという流れで、データが動いているので最後に、create アクションの中で
情報をデータベースに保存する処理を書きます。Modelを呼び出します。書き込みの仕方は、seed.rb でもやりましたね。
seed.rb@book = Book.new @book.country = "jp" @book.title = "吾輩は猫である" @book.author = "夏目漱石" @book.year = 1905 @book.user_id = 1 @book.comment = "おもしろかった" @book.save【備考】
ちなみに、このままなにも受け取り処理を書かずに情報を送信してみるとどうなるでしょうか。
試しに、本の情報をフォームに入力し送信してみると、なにも動きません。送信しているので、フォームから パラメーターは飛んでいます。
このパラメーターですが、実は見ることが出来るんです。rails s を起動している、 terminalをみてください。
いつの間にか、いろんな文字が出力されていますね。
サーバーが受け取ったデータなどの情報が表示されています。
この先、困ったときにここをみると解決できることがあると思います。"どういったデータがどういう形式で動いているかは、サーバーのログをみる"
自分でサービスをつくるのに、重要なテクニックなので覚えておいてください
サーバーログの一番下をみてみましょう。(下図は、ややシンプル化しています)terminalStarted POST "/books" Processing by BooksController#create as HTML Parameters: {"book"=>{"country"=>"jp", "title"=>"吾輩は猫である", "author"=>"夏目漱石", "year"=>"1905", "user_id"=>"1", "comment"=>"おもしろかった"}}パラメーターをみると、二重の連想配列になっているのがわかると思います。
( parameters{} の中に book{} が入っている )通常の連想配列の場合は、params[:title] として取得できていました。
二重の連想配列の場合は、params[:book][:title] とすることで取得できます。
( bookキー の中のtitleキー のデータを取得しています )
連想配列について詳しくはこちらを参照してください Array(配列)とHash(連想配列)入門さて、ここまで理解できていれば create アクションの中身も想像できると思います。
( seed.rb の、本の情報が書かれていた部分をパラメーターの中身に書き換えるだけです )app/controllers/books_controller.rbdef create @book = Book.new @book.country = params[:book][:country] @book.title = params[:book][:title] @book.author = params[:book][:author] @book.year = params[:book][:year] @book.user_id = params[:book][:user_id] @book.comment = params[:book][:comment] @book.save redirect_to '/books/show/1' end最後の、redirect_to '/books/show/1' の部分ですが、
登録ボタンを押したあとに、画面遷移してほしいので、リダイレクト先を指定しました。http://localhost:3000/books/new ここで本の情報を登録
http://localhost:3000/books/show/1 ここで登録内容を確認
(Userの欄を、1以外にした人は、該当ユーザーのページを開いてください)課題
1, show ページに、タイトルと著者以外の情報も表示してください。
2, リダイレクト先を、 http://localhost:3000/books/index に変更してください。
3, index ページに、全蔵書のタイトルを表示させてださい。
- 投稿日:2020-02-16T03:16:43+09:00
Before Rails Tutorial3章 Scaffold を用いない開発
本投稿は講義資料であり、Rubyの基礎は理解しているが、rails tutorialで躓く読者を対象としています。
1章:環境構築
2章:Scaffold を用いた高速なアプリケーション構築 及び MVCの理解
3章:Scaffold を用いない開発方法 及び 応用前章では、Scaffoldを用いて高速でアプリケーションを構築しました。
自動化された部分も多く、現段階では、大まかな理解であるとおもいます。今回は、route Model View Controller それぞれ自分で作っていきます。
とはいっても、継承まで含めてすべて書くには理解することが膨大で大変ですので、
前回も使用した generate は使用していきます。まずは、Railsの新しいアプリケーションを作成します。
1章:環境構築の内容を参考に作成してみましょう。terminal$ cd ~/rails_app $ mkdir bukukore $ bundle init (Gemfileにgem "rails","~> 5.2.3"を追加し保存してください) $ bundle install --path vendor/bundlesa $ bin/rails shttp://localhost:3000/ にアクセスして表示されていればokです。
$ rails s -p 3100 などとポートを変更することでサーバーを複数起動可能です。
この場合は http://localhost:3100/ にアクセスします。MVC 復習
前章では、アプリ制作を通して、MVCの流れを理解してきました。
Modelは、データベースとのやりとりを担う
Viewは、表示関連全般を担う
Controllerは、橋渡しの役割を担う前回、制作したながれを図を見ながら復習していきます。
それぞれの番号が、コードではどうなっていたか思い出しながら見てください。1, ブラウザから /users へのリクエストを Rails sever に送信する
2, router によって、/users は Users controller の index アクションを呼び出す
3, index アクションから、User Model が呼び出される
4, User Model は DataBase からデータを取り出す
5, 取り出したデータを、Controller に返す
6, 受け取ったデータを @users に保存し、 View (indexアクションなので index.html.erb) に渡す。
7, ERBを実行し、@users のデータを含んだ HTMLを生成し、Controller へ返す
8, Controller は、受け取ったHTMLをブラウザにわたす今回も Model View Controller を構築していくので、適宜図を見返してください。
Controller と View の作成
作成は基本的に generate コマンドを用います。
(gは generateコマンドの短縮形です)
g の後は、controller に続けて、コントローラーの名前(複数形)を書きます。
rails g controller Books index show new
そのうしろ(引数といいます)に書いたものは、同名のviewとアクションが自動生成されます。tarminal$ bin/rails g controller Books index show new create app/controllers/books_controller.rb route get 'books/index' get 'books/show' get 'books/new' create app/views/books create app/views/books/index.html.erb create app/views/books/show.html.erb create app/views/books/new.html.erbルーティングが生成されているので、確認してみましょう。
terminal$ bin/rails routes Verb URI Pattern GET /books/index books#index GET /books/show books#show GET /books/new books#newこれは具体的には、 http://localhost:3000/books/index
というURLに対するリクエストがあれば、 books_controller の index アクション を呼び出すというものでした。
今回アクションの中身が空なので、Model は呼び出されず、単に対応するView (index.html.erb) が実行されるだけです。ルーティングがうまくいってみるか確認するために、試しにアクセスしてみましょう。
http://localhost:3000/books/indexBooks#index
Find me in app/views/books/index.html.erbと表示されているとおもいます。
Viewの変更
erbの変更は前回行ったとおりですね。とてもシンプルなものでした。
Books#index の部分を、全蔵書一覧などに変更しておきましょう。app/views/books/index.html.erb<h1>全蔵書一覧</h1>erb の中身がシンプルすぎて不思議な方もいらっしゃるかもしれません。
【気になって次にすすめない人向けの解説】
app/views/layouts/application.html.erb を開いてください。
コード内の、<%= yiels %> の部分に、 index.html.erb が移植されて HTML を生成しています。
いまはこの程度の理解で問題ありません。 https://railstutorial.jp/ でより深く理解できます。Controllerの変更
コントローラーの中にアクションが本当に作られているかも確認してみましょう。
app/controllers/books_controller.rb を開いてみてください。app/controllers/books_controller.rbclass BooksController < ApplicationController def index end def show end def new end endデータベース内のデータを取り出すには、Controllerのアクションから
Model を呼び出せば良いのでした。app/controllers/books_controller.rbclass BooksController < ApplicationController def index end def show @book = Book.find(1) end def new end endこのままではエラーがでます。(Modelも、本の情報も作っていないので)
generate コマンドを使用して、Model を作成していきます。Model の作成
booksテーブルには、前章と同じカラムを持たせていきます。
terminal$ bin/rails g model Book country:text title:text author:text year:integer user_id:integer comment:text create db/migrate/20200202020202_create_books.rb create app/models/book.rbg の後は、model に続けて、Model名(単数形)を書きます。
データベースにテーブルを作成するには migrate を実行するのでしたね。terminla$ bin/rails db:migrate == 20200202020202 CreateBooks: migrating ====================================== -- create_table(:books) -> 0.0008s == 20200202020202 CreateBooks: migrated (0.0009s) =============================補足. migrate はマイグレーションファイルを実行しています。
db/migrate/(作成日時)_create_books.rb というファイルです。
ひらいてみると、下記のようなコードがあると思います。class CreateBooks < ActiveRecord
def change
create_table :books do |t|
t.text :country
t.text :title
t.text :author
t.integer :year
t.integer :user_id
t.text :comment
t.timestamps
end
end
end上記は text型であるcountryというカラム(他6つ)を持つ books テーブルを作成
せよという意味です。 change 意外に up down などもあります。詳細は下記サイトなどを参照ください
https://www.sejuku.net/blog/14229これでbooksテーブルが作成されました。
テーブルは作成したけども、本の情報はまだなにもいれてませんね。
初期データをいれるには db/seeds.rb ファイルを使用します。
( seed = 種 という意味です )
大量のデータを入力するのは手間なのでseed.rbを作成していきます。
(そもそもブラウザからデータをいれる機能もまだ作っていません)下記の seed ファイルを実行すると、bookテーブルに本の情報が3件保存されます
db/seeds.rb@book = Book.new @book.country = "jp" @book.title = "吾輩は猫である" @book.author = "夏目漱石" @book.year = 1905 @book.user_id = 1 @book.comment = "おもしろかった" @book.save @book = Book.new @book.country = "jp" @book.title = "人間失格" @book.author = "太宰治" @book.year = 1948 @book.user_id = 2 @book.comment = "すばらしかった" @book.save @book = Book.new @book.country = "gb" @book.title = "Alice's Adventures in Wonderland" @book.author = "Lewis Carroll" @book.year = 1865 @book.user_id = 1 @book.comment = "Amazing" @book.saveseed ファイルは、下記のコマンドで実行できます。
terminal$ bundle exec rake db:seedデータが保存されたかの確認は。rails c でコンソールを起動すると確認できます。
railsConsole@book = Book.find(1)ブラウザ(show)で表示してみましょう。
app/view/books/show.html.erb<p>本のタイトル: <%= @book.title %></p> <p>著者: <%= @book.author %></p>本のタイトル: 吾輩は猫である
著者: 夏目漱石
と表示されていればOKです。
課題1,
@book はどこで定義したか、再確認してください。
URLからパラメーターの取得
本のデータを取り出して表示するところまでうまくいきました!
すごい進歩です!ただ、まだ不満点があります。
それは、 id:1 の本のデータしか表示できていない点です。
理由は、Contoroller の show アクションをみると、
@book = Book.find(1)
となっているためです(id:1 の本の情報しか見つけてきていない)ここをidパラメーターが1以外も入力できるように変更するにはどうすればよいでしょうか。
@book = Book.find(params[:id])
とすることで、1以外のパラメーターを見つけてこれます。app/controllers/books_controller.rbdef show @book = Book.find(params[:id]) endパラメーター(数値)は、どこで指定すればよいでしょうか。
URL にパラメーターを含めて渡すテクニックがあるので覚えておきましょう。
例)ID:2の本の情報を取得したい場合 http://localhost:3000/books/show/2
このままではルーティングエラーが表示されます。
books/show へのリクエストに関しては記述していますが、
books/show/(数字) へのリクエストについてはなにも書いていない為です。config/routes.rb を開いてください。
URLに含まれる数字をパラメーターとして取得するには、下記のように記述します。config/routes.rb# get 'books/show'(# でコメントアウトしてます) get 'books/show/:id', to:'books#show'こうすることで /books/show/2 の 2の部分が、:id パラメーターとして利用可能になります。
( 利用するときは、params[:id] とかきます)to: 'books#show'
books Cコントローラーの show アクションを呼び出す指示になります。これで、任意のidの本情報を取得できるようになりました。
http://localhost:3000/books/show/1
http://localhost:3000/books/show/2Model 検索
いま本の情報の取り出しに id を利用していますが、
id 以外のカラムを用いて取り出す方法も覚えておくと便利です。コンソールを起動してください。 ( rails c )
下記を参考に色々と試してみてください。railsConsole>> Book.all #bookテーブルのすべてのデータを取得します。 >> Book.find_by(title: "人間失格") #条件に合ったデータを、1件だけ取得します。 >> Book.where(country: "jp") #条件に合ったデータを、すべて取得します。 >> Book.where(country: "jp").where(year: 1905) #AND検索。 和書で 1905年出版の本を取得しています。 >> Book.where("(country = ?) OR (year = ?)","jp",1905) #OR検索。 和書 または 1905年出版の本を取得しています。 >> Book.order(create_at: :asc) #並び順を指定します。 作成日時の昇順で取得しています。 >> Book.where(user_id: 1).order(id: :desc) #user_id 1さんの蔵書を、idの降順で取得しています。where の利用
検索条件を学んだのでこれ使って、蔵書管理アプリケーションらしく
個人の蔵書を一覧表示する機能を構築してみましょう。app/controllers/books_controller.rbdef show # @book = Book.find(params[:id]) コメントアウトしました。 @book = Book.where(user_id: params[:id]) enduser_id が パラメーター番号の人の蔵書データをすべて取得して@bookに格納しています。
View も編集していきましょう。 @book のなかに複数のデータがある場合(連想配列)
each を用いて、順に表示させていくのでしたね。(2章の復習です)app/views/books/show.html.erb<% @book.each do |book| %> <p>本のタイトル: <%= book.title %></p> <p>著者: <%= book.author %></p> <% end %>http://localhost:3000/books/show/1
にアクセスしてみると、 user_id:1 になっている本のデータがすべて表示されました。本のタイトル: 吾輩は猫である
著者: 夏目漱石本のタイトル: Alice's Adventures in Wonderland
著者: Lewis Carroll【補足】「あれ? has_many とかつけなくてよいんだっけ?」
と思った方は、前章の内容を覚えてくれていますね。
ただ少し勘違いがあります。 has_many,belongs_to は異なるテーブルの紐付けに使います。
今回は、 Book Modelを経由し、Bookテーブルだけにアクセスしているので不要です。
User Model から、Bookテーブルのデータを取り出すならば必要になってきます。データ登録フォームの作成
さて、データベースから情報を取り出したり加工したりする方法は覚えました。
しかしこのままではユーザーは、本を登録することができません。本を登録するための機能を作成する方法を学んでいきましょう。
登録形式は、フォーム。
URL は http://localhost:3000/books/new
とします。form_for
データベースに新しいデータを保存したいので、 Model を呼び出しましょう。
場所はどこに書きましょう。
new.html.erb に登録フォームを置くので、 new アクションの中ですね。
新しいデータを登録するときは、 Model名.new とします。下記のコードを追記してください。app/controllers/books_controller.rbdef new @book = Book.new endnew.html.erb に 入力フォームを作成していきましょう。
rails では、フォームを簡単につくれる form_forヘルパーというものがあります。app/views/books/new.html.erb<%= form_for(@book) do |f| %> <%= f.label :country %> <%= f.text_field :country %> <%= f.label :title %> <%= f.text_field :title %> <%= f.label :author %> <%= f.text_field :author %> <%= f.label :year %> <%= f.number_field :year %> <%= f.label :user_id %> <%= f.number_field :user_id %> <%= f.label :comment %> <%= f.text_area :comment %> <%= f.submit "送信" %> <% end %>form_for に関する詳しい使い方は、こちらのサイトで学習してください。
form_forの使い方を徹底解説!ここでは重要な部分だけ、簡単に解説します。
上の form_forヘルパーにより、下記のような HTML が生成されます。(少しシンプル化してます)new.html<form class="new_book" id="new_book" action="/books" method="post"> <label for="book_country">Country</label> <input type="text" name="book[country]" id="book_country" /> <label for="book_title">Title</label> <input type="text" name="book[title]" id="book_title" /> <label for="book_author">Author</label> <input type="text" name="book[author]" id="book_author" /> <label for="book_year">Year</label> <input type="number" name="book[year]" id="book_year" /> <label for="book_user_id">User</label> <input type="number" name="book[user_id]" id="book_user_id" /> <label for="book_comment">Comment</label> <textarea name="book[comment]" id="book_comment"> </textarea> <input type="submit" name="commit" value="送信" /> </form>ここで重要な属性は、
< form class="new_book" id="new_book" action="/books" method="post" >
の中の、 action="/books" と method="post" の2つです。この2つは送信ボタンが押されたら、
/books に対して、 POST リクエストを送信する
という指示をしています。なので、 /books 対して、 POST リクエストがあった場合の処理を書いていきましょう。
送信したあとは、books Controller の create アクションに飛ばしたいです。
(のちほどデータベースに保存する処理を create アクションに書いていきます)post 'books', to: 'books#create'
コードはこのようになるので、 routes.rb に追記しましょう。
(ルーティング関係は、 routes.rb でしたね)config/routes.rbRails.application.routes.draw do get 'books/index' get 'books/show/:id', to: 'books#show' get 'books/new' post 'books', to: 'books#create' endindex と new は to: が書かれていませんね。
前章でも説明したとおり、Railsは、アクションが呼び出されると、
自動的に アクション名.html.erbが呼び出されるので、
下記と同じ意味になります。
get 'books/index' to: 'books#index'
get 'books/new', to: 'books#new'1,登録ボタンが押される
2,フォームに入力されたデータを、create アクションに飛ばすという流れで、データが動いているので最後に、create アクションの中で
情報をデータベースに保存する処理を書きます。Modelを呼び出します。書き込みの仕方は、seed.rb でもやりましたね。
seed.rb@book = Book.new @book.country = "jp" @book.title = "吾輩は猫である" @book.author = "夏目漱石" @book.year = 1905 @book.user_id = 1 @book.comment = "おもしろかった" @book.save【備考】
ちなみに、このままなにも受け取り処理を書かずに情報を送信してみるとどうなるでしょうか。
試しに、本の情報をフォームに入力し送信してみると、なにも動きません。送信しているので、フォームから パラメーターは飛んでいます。
このパラメーターですが、実は見ることが出来るんです。rails s を起動している、 terminalをみてください。
いつの間にか、いろんな文字が出力されていますね。
サーバーが受け取ったデータなどの情報が表示されています。
この先、困ったときにここをみると解決できることがあると思います。"どういったデータがどういう形式で動いているかは、サーバーのログをみる"
自分でサービスをつくるのに、重要なテクニックなので覚えておいてください
サーバーログの一番下をみてみましょう。(下図は、ややシンプル化しています)terminalStarted POST "/books" Processing by BooksController#create as HTML Parameters: {"book"=>{"country"=>"jp", "title"=>"吾輩は猫である", "author"=>"夏目漱石", "year"=>"1905", "user_id"=>"1", "comment"=>"おもしろかった"}}パラメーターをみると、二重の連想配列になっているのがわかると思います。
( parameters{} の中に book{} が入っている )通常の連想配列の場合は、params[:title] として取得できていました。
二重の連想配列の場合は、params[:book][:title] とすることで取得できます。
( bookキー の中のtitleキー のデータを取得しています )
連想配列について詳しくはこちらを参照してください Array(配列)とHash(連想配列)入門さて、ここまで理解できていれば create アクションの中身も想像できると思います。
( seed.rb の、本の情報が書かれていた部分をパラメーターの中身に書き換えるだけです )app/controllers/books_controller.rbdef create @book = Book.new @book.country = params[:book][:country] @book.title = params[:book][:title] @book.author = params[:book][:author] @book.year = params[:book][:year] @book.user_id = params[:book][:user_id] @book.comment = params[:book][:comment] @book.save redirect_to '/books/show/1' end最後の、redirect_to '/books/show/1' の部分ですが、
登録ボタンを押したあとに、画面遷移してほしいので、リダイレクト先を指定しました。http://localhost:3000/books/new ここで本の情報を登録
http://localhost:3000/books/show/1 ここで登録内容を確認
(Userの欄を、1以外にした人は、該当ユーザーのページを開いてください)課題
1, show ページに、タイトルと著者以外の情報も表示してください。
2, リダイレクト先を、 http://localhost:3000/books/index に変更してください。
3, index ページに、全蔵書のタイトルを表示させてださい。
- 投稿日:2020-02-16T02:52:55+09:00
あとからgem sqlite3を削除したらエラーが出た
rails new するときに '-o' コマンドを入れてなくて、あとからgem 'sqlite3'を消したら以下のエラーが出た
ActiveRecord::ConnectionNotEstablished: No connection pool with 'primary' found.
環境はRails5.2
まずは config/application.rb から
require "ative_record/railtie"をコメントアウト。
次に、config/environments/development.rb 内を "active_record"で検索して
config.active_record.migration_error = :page_load config.active_record.verbose_query_logs = trueこの2つをコメントアウト!
多分これで問題ない!おっと。
production.rbの方もコメントアウトしなければ。。。config.active_record.dump_schema_after_migration = false
- 投稿日:2020-02-16T02:09:37+09:00
RailsアプリでFacebook Twitter GitHubのOAuth認証を可能にした
表題のとおりです。
とりあえず、主要SNSと個人的に入れたかったGitHubを対応させました。
パラメータそれ自体は汎用性が高いので、今後その他のサービスの認証機能も用意に対応できそうな感じ。注意
この記事は、1年ほど前にQiitaに投稿したものを、同じ内容で再投稿したものになります。
そのため、内容が古くなっている可能性があります。以下のコードは、Herokuにデプロイをする前提で書いています。
参考
RailsでFacebookログインを実装する
【Rails4.2.x】omniauth(twitter/facebook/github)実装まとめ
Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ正直コーディングそのものより、API申請の方が大変だったような・・・
必要なGemの準備
Gemfile# OAuth gem 'omniauth' gem 'omniauth-github' gem 'omniauth-twitter' gem 'omniauth-facebook' # 本番環境と開発環境でCredentialsを分けるために使用 group :development, :test do gem 'rails-env-credentials' endUserモデルを作成
下記の構成のUserモデルを作りました。
schema.rb# $ be rails g model user name provider uid:text oauth_token icon email create_table "users", force: :cascade do |t| t.string "name" t.string "provider" t.text "uid" t.string "oauth_token" t.string "icon" t.string "email" t.datetime "created_at", null: false t.datetime "updated_at", null: false endその他に、例えばTwitterのプロフィールにあるような『住所』カラムが欲しい場合自由に追加してOKです。
omniauth.rbを作成
config/initializersに以下のファイルを追加。
config/initializersRails.application.config.middleware.use OmniAuth::Builder do provider :github, Rails.application.credentials.github[:key], Rails.application.credentials.github[:secret], scope: "user,repo" provider :twitter, Rails.application.credentials.twitter[:key], Rails.application.credentials.twitter[:secret] provider :facebook, Rails.application.credentials.facebook[:key], Rails.application.credentials.facebook[:secret] end上記コードでは、APIの ClientID と ClientSecret を、Credentialsなる機能を使って管理しています。
Credentialsだと、本番環境の秘匿情報しか扱えなかったので、便利なGem"rails-env-credentials"を使って、開発環境でもCredentialsを使えるようにしました。Rails 5.2 の Credentials を各環境でも使えるようにする gem を作りました
Credentialsの中身
本番用・開発用どちらも同じように ClientID と ClientSecret を設定します。
EDITOR="nano" be rails env_credentials:edit
EDITOR="nano" be rails credentials:edit
config/credentials.uml.encgithub: key: xxxxxxxxxxxxx secret: XXXXXXXXXXXXXXXXXXXxX twitter: key: xxxxxxxxxxxxx secret: XXXXXXXXXXXXXXXXXXXxX facebook: key: xxxxxxxxxxxxx secret: XXXXXXXXXXXXXXXXXXXxXこのとき、TwitterとGitHubに関しては、本番用アプリと開発用アプリのそれぞれで、別の ID と Secret を取得しました。
Facebookの方は、そもそも非暗号化通信ではAPIを使用できないみたいなので、とりあえずエラー回避のために本番用と同じ ID/Secret を、開発用Credentialsに書いておきました。
(つまり、FacebookのOAuth認証は、本番環境でしか行なえません)
ローカルでFacebookのOAuth認証テストを行う場合は、少し面倒くさい手順が必要のようです。
Facebookログインがhttps必須になったので、localhost開発でも対応するmodel/user.rbを編集
model/user.rbを以下に書き換えます。
model/user.rbclass User < ApplicationRecord def self.find_or_create_from_auth(auth) email = auth[:info][:email] provider = auth[:provider] uid = auth[:uid] icon = auth[:info][:image] oauth_token = auth[:credentials][:token] case provider when "twitter", "facebook" then name = auth[:info][:name] when "github" then name = auth[:info][:nickname] end self.find_or_create_by(provider: provider, uid: uid) do |user| user.email = email user.name = name user.icon = icon user.provider = provider user.uid = uid user.oauth_token = oauth_token end end end例えば先程、Userモデルを作った際にLocationカラムも追加した場合、このuser.rbに下記を追記すれば対応できるはずです・
location = auth[:info][:location] self.find_or_create_by(provider: provider, uid: uid) do |user| user.location = location end一部、Case文でprovider毎にパラメータを変えなければならない箇所が出てきます。
login処理
sessioinsControllerを作成し、以下のコードを追記します。
class SessionsController < ApplicationController def create auth = request.env['omniauth.auth'] user = User.find_or_create_from_auth(request.env['omniauth.auth']) session[:user_id] = user.id redirect_to root_path end def destroy reset_session redirect_to root_path end endapplication_controller.rbも編集。
class ApplicationController < ActionController::Base protect_from_forgery with: :exception helper_method :current_user, :logged_in? private def current_user return unless session[:user_id] @current_user ||= User.find(session[:user_id]) end def logged_in? !!session[:user_id] end def authenticate return if logged_in? redirect_to root_path, alert: 'ログインしてください' end endView
config/route.rb
config/route.rbRails.application.routes.draw do get 'auth/:provider/callback', to: 'sessions#create' get '/logout', to: 'sessions#destroy' root 'homes#top' endhtml
<% if logged_in? %> <%= link_to 'log out', '/logout' %> <%= @user.name %>さん、こんにちは。 <%= image_tag(@user.icon) %> <% else %> <%= link_to 'GitHubアカウントでログイン', '/auth/github' %> <%= link_to 'Twitterアカウントでログイン', '/auth/twitter' %> <%= link_to 'Facebookアカウントでログイン', '/auth/facebook' %> <% end %>完成
最後に、HerokuでCredentialsを使うために下記を実行。
heroku config:set RAILS_MASTER_KEY=`cat config/master.key`思った以上に各APIでパラメータが重複してて楽に実装できました!
先人の方々の知恵に本当に感謝です。
- 投稿日:2020-02-16T00:28:03+09:00
resourcesメソッドはとっても便利!
はじめに
この記事はプログラミング初学者である私自身の備忘録として残します。
プログラミングの学習を初めてからというもの、ルーティングの記述ではずっとresourcesメソッドを使い続けていたので、なぜこのメソッドを使うのかおさらいしてみました。結論「やっぱり便利だな〜」。
ルーティング(routes.rb)の記述に際して
resourcesメソッドの 不使用時 と 使用時 のコードを比べてみました。
あれ?そもそもルーティングってなんだっけ?って思った方は、こちらを読んでみてください。
### resourcesメソッド ** 不使用時 ** root to: 'posts#index' get '/posts', to: 'posts#index' get '/posts/new', to: 'posts#new' post '/posts', to: 'posts#create'### resourcesメソッド ** 使用時 ** root to: 'posts#index' resources :posts, only: [:index, :new, :create]resourcesメソッド不使用時の
get '/posts', to: 'posts#index'
を説明すると、HTTPメソッドの
get
を使ってposts
パス(URIパターン)を取得した際の処理として、posts
コントローラのindex
アクションを指定する。という意味です。
形としてはHTTPメソッド 'パス(URIパターン)', to: 'コントローラー名#アクション名'てなかんじです。
resourcedメソッド使用時の
resources :posts, only: [:index, :new, :create]
を説明すると、
posts
コントローラーを参照(resource)して、コントローラーが持つ7つのアクションからindex
、new
、create
のみを使う。という意味です。
形としてはresources :コントローラー名, only: [:アクション名, :アクション名・・・]となります。
実はこれ、only
を省けば7つのアクションすべて使えるという意味になります。まとめ
どちらも同じ処理を行うコードですが、
resourcesメソッド不使用時では3行使って記述されているコードが、使用時ではたった1行にまとめられています。さらにもう一点、resourcesメソッドを使えば、HTTPメソッド
とパス(URIパターン)
を指定する必要がありません。これだけで十分このメソッドの便利さが分かると思います。HTTPメソッド や パス(URIパターン)について気になった方は、自分が作業中のファイルをターミナルで開いて、
rails routes
で確認してみてください。(言葉の意味が分からない場合は文字をクリック)もっと詳しく知りたい方は
以下にリンクを貼っておきます。
・Samurai Blog
【Rails入門】resourcesの使い方まとめ・Pikawaka
【Rails】resourcesメソッドを徹底解説!