Rails URLにidや特定にパラメータを含める
URLにidや特定にパラメータを含める
投稿の詳細画面や、ユーザーのプロフィール画面等、同じ表示でパラメータ毎によって表示を変えたいときは、
config/routes.rb
で以下のようにルーティングを行う
get "posts/:id" => "post#show"
ただし、posts/index
のようなルーティングの下に記述すること。
渡されたパラメータを受け取る
上記の方法で渡されたパラメータは、コントローラで受け取ることができる。
id
が渡されたのならば、params[:id]
と記述すれば良い。
posts_controller.rb
def show @id = params[:id] end
変数を用意してコントローラー内で受け取ることで、viewで使用することが可能になる。
show.html.erb
<%= @id %>
Rails ルートパスの設定
ルートパス"/"への設定
config/routes.rb
Rails.application.routes.draw do get "/" => "home#top" end
のようにroutes.rb
ファイルで"/"を設定することで、rootへのルーティングが可能。
この場合は、rootパスが呼ばれた時に、home#top
アクションが実行される。
久しぶりに勉強を再開したので基本的なことから復習していく。
Rails基礎 Active Recordの基本操作(メモ)
実行結果・実行されているSQLを確認するための自分用メモです。 作成~登録~更新~削除
新規オブジェクトの作成
#新規オブジェクトを作成 >> user = User.new(name: "Michael Hartl", email: "michael@example.com") (0.1ms) begin transaction => #<User id: nil, name: "Michael Hartl", email: "michael@example.com", created_at: nil, updated_at: nil>
created_at
とupdated_at
は登録日時、更新日時。このカラムとidは勝手に作ってくれる。
newしただけだと、created_at
とupdated_at
はnil
であることが確認できる。
有効性のチェック
#有効性のチェック(DBの存在チェックは行えない) >> user.valid? => true
エラーがなければtrue
、エラーが発生したらfalse
が返却される。
登録前のチェック等に。
実行結果が逆になる.invalid?
も存在する。
オブジェクトの保存
#保存 >> user.save (0.1ms) SAVEPOINT active_record_1 User Create (3.9ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Michael Hartl"], ["email", "michael@example.com"], ["created_at", "2020-11-21 15:11:49.849711"], ["updated_at", "2020-11-21 15:11:49.849711"]] (0.1ms) RELEASE SAVEPOINT active_record_1 => true
INSERT
が発行されていて、DBに保存されていることがわかる。また、先ほどはnil
だったcreated_at
とupdated_at
に値が入っていることを確認できる。
またSAVEPOINT
が作成されているので、トランザクションが発行されていて、失敗した場合はロールバックしてくれるような感じがする(自分では未検証)
情報取得
#各情報の参照 >> user => #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2020-11-21 15:11:49", updated_at: "2020-11-21 15:11:49"> >> user.name => "Michael Hartl" >> user.email => "michael@example.com" >> user.updated_at => Sat, 21 Nov 2020 15:11:49 UTC +00:00
上記のINSERT
の時にはid
は含まれていなかったが、ちゃんと値が入っている。ということは内部で勝手に自動採番してくれているらしい。
createで生成と削除を同時に行う
#モデルの生成と保存を同時に行う >> User.create(name: "A Nother", email: "another@example.org") (0.1ms) SAVEPOINT active_record_1 User Create (0.1ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "A Nother"], ["email", "another@example.org"], ["created_at", "2020-11-21 15:12:58.282793"], ["updated_at", "2020-11-21 15:12:58.282793"]] (0.1ms) RELEASE SAVEPOINT active_record_1 => #<User id: 2, name: "A Nother", email: "another@example.org", created_at: "2020-11-21 15:12:58", updated_at: "2020-11-21 15:12:58"> >> foo = User.create(name: "Foo", email: "foo@bar.com") (0.1ms) SAVEPOINT active_record_1 User Create (0.1ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Foo"], ["email", "foo@bar.com"], ["created_at", "2020-11-21 15:13:06.291513"], ["updated_at", "2020-11-21 15:13:06.291513"]] (0.1ms) RELEASE SAVEPOINT active_record_1 => #<User id: 3, name: "Foo", email: "foo@bar.com", created_at: "2020-11-21 15:13:06", updated_at: "2020-11-21 15:13:06">
save
のときは戻り値がtrue(真偽値)
だったが、create
のときは作成されたオブジェクトが返却されてくる違いがあるので、
なんでも便利だからcreate
で済まそう!とはいかなさそう。
削除
#削除 >> foo.destroy (0.1ms) SAVEPOINT active_record_1 User Destroy (0.2ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 3]] (0.1ms) RELEASE SAVEPOINT active_record_1 => #<User id: 3, name: "Foo", email: "foo@bar.com", created_at: "2020-11-21 15:13:06", updated_at: "2020-11-21 15:13:06"> >> foo => #<User id: 3, name: "Foo", email: "foo@bar.com", created_at: "2020-11-21 15:13:06", updated_at: "2020-11-21 15:13:06">
DELETE
が発行され削除されている。しかし、オブジェクト内にはメモリ上の情報が残っている。
実際に削除されたかどうかはこの方法で調べないように。(以下のfindメソッド等を使用しSELECT文を発行して確認するのが良さげ)
クラス、継承元の調べ方
#クラスと継承元を調べる >> user.name.class => String >> user.email.class => String >> user.created_at.class => ActiveSupport::TimeWithZone >> user.updated_at.class => ActiveSupport::TimeWithZone
find
#id:1を検索 >> User.find(1) User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] => #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2020-11-21 15:11:49", updated_at: "2020-11-21 15:11:49"> >> User.find(3) User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]] Traceback (most recent call last): 1: from (irb):18 ActiveRecord::RecordNotFound (Couldn't find User with 'id'=3)
SELECT
が発行されている。find
はidで調べる用。
find_by
#特定の属性で検索 >> User.find_by(email: "michael@example.com") User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "michael@example.com"], ["LIMIT", 1]] => #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2020-11-21 15:11:49", updated_at: "2020-11-21 15:11:49">
SELECT
が発行され、条件WHERE
がemail
となっている。任意の属性で検索する場合はfind_by
を使用する。
first
#最初のデータ >> User.first User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] => #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2020-11-21 15:11:49", updated_at: "2020-11-21 15:11:49">
SELECT
が発行され、id
でソート(`ORDER BY~ASC``)をかけたあと、最初の1件を取得していることがわかる。
all
#すべてのデータ >> User.all User Load (0.2ms) SELECT "users".* FROM "users" LIMIT ? [["LIMIT", 11]] => #<ActiveRecord::Relation [#<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2020-11-21 15:11:49", updated_at: "2020-11-21 15:11:49">, #<User id: 2, name: "A Nother", email: "another@example.org", created_at: "2020-11-21 15:12:58", updated_at: "2020-11-21 15:12:58">]>
SELECT
ですべてのデータを取得している。[["LIMIT", 11]]
の11はどこから来たのか不明…いつか調べたい。もしかしたら色々登録してて、idの最大値が入っているだけかも。
find_by_name
#名前で検索 >> User.find_by_name("Michael Hartl") User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."name" = ? LIMIT ? [["name", "Michael Hartl"], ["LIMIT", 1]] => #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2020-11-21 15:11:49", updated_at: "2020-11-21 15:11:49">
WHERE name =
で名前検索してくれる。
length
#要素の長さを取得 >> User.all.length User Load (0.2ms) SELECT "users".* FROM "users" => 2
SELECT~FROM
だけのシンプルなSQLだった。
COUNT
で件数を取得してるのかと思っていたが、どうやら違うらしい。別のところで件数を数えてくれているっぽい。
更新(save)
#更新 >> user.email = "mhartl@example.net" => "mhartl@example.net" >> user.save (0.1ms) SAVEPOINT active_record_1 User Update (0.2ms) UPDATE "users" SET "email" = ?, "updated_at" = ? WHERE "users"."id" = ? [["email", "mhartl@example.net"], ["updated_at", "2020-11-21 15:27:55.850900"], ["id", 1]] (0.1ms) RELEASE SAVEPOINT active_record_1 => true
すでにあるIDのオブジェクトをsave
すると、勝手にUPDATE
してくれるっぽい。有能。さらに、名前からして当然ではあるが、UPDATEではcreated_at
は更新されない。
取消
#save前に取消 >> user.email = "foo@bar.com" => "foo@bar.com" >> user.reload.email User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] => "mhartl@example.net"
DBにまだ保存されていないので、SQLで特に何かしているわけではないっぽい。
更新(update)
#updateで更新 >> user.update(name: "The Dude", email: "dude@abides.org") => true >> user.name => "The Dude" >> user.email => "dude@abides.org"
update
を使用すると成功したかどうかの真偽値が返却される。
検証を回避しつつ更新
#検証を回避しつつ更新 >> user.update_attribute(:name, "El Duderino") => true >> user.name => "El Duderino"
実装の中で検証が失敗するようになることもあるらしい。これから学んでいく。
RailsでBootstrapを導入する
RailsでBootstrapを導入する方法
メモ書き程度の備忘録。 最初に一度やるだけの手順ってどうしても繰り返しにくいから忘れがちなんだよなぁ~ってことで…
Gemfileにbootstrap-sassを追加
gem 'bootstrap-sass', '3.4.1'
BootstrapではLESS CSS言語を使用しているが、RailsはSass言語をデフォルトでサポートしているため、上記のgemでLESS→Sassの変換を可能にする。
$ bundle install
でインストールするのを忘れずに。
Sassファイルを作成
$ touch app/assets/stylesheets/hogehoge.scss
として、Sassファイルを作成。もちろん、他の方法でファイル作成できるならそちらでもOK。
SassファイルにCSSを追加
先ほど作ったファイルに以下の記述をして、Bootstrapと関連するsprocketsを読み込んでいく。
@import "bootstrap-sprockets"; @import "bootstrap";
これでRailsでBootstrapを使用する準備は整った。 あとはViewファイルでBootstrapで使用したいクラスを指定したり、CSSをカスタマイズしていけばOK!
Rails基礎 削除機能の実装(destroy)
削除機能(destroy)の実装
get
やpost
はリンクを作るときに特に指定しなくてもRailsがいい感じに解釈してくれていたが、DELETE
の場合は明示的に指定してあげる必要がある。
Post
モデルがあったとして、その削除機能のリンクを作るときは以下のようになる
<%= link_to '[削除]', post_path(post), method: :delete %>
pathはrails routes
でルーティングをチェック。post_path
で良さそう。
そして、明示的に「deleteアクションを呼んでね」と指定する場合に
method: :delete
としてあげればOKのようです。
ちなみに、なんのワンクッションもなく削除されてしまうと困る場合も多いと思うので、 確認ダイアログを出したい場合は以下のように。
<%= link_to '[削除]', post_path(post), method: :delete, class: 'command', data: {confirm: '削除してよろしいですか?'} %>
そして、コントローラーにアクションを記述していく。
def destroy @post = Post.find(params[:id]) @post.destroy redirect_to posts_path end
どのPostに対するものなのかをまず特定し、@postに格納、それに対してdestroy
を実行。
posts_path
(記事の一覧が設定してあります)にリダイレクトする。
これで、基本の削除機能の実装ができるようになる。
ちなみに、whereで条件を指定して複数削除するdestroy_all
というものもあるようなので、覚えておきたい。
Rails基礎 フォームの共通部品(partial)
partialとは?
複数の画面で同じ部品を使用している場合に、その部分を切り出してpartialファイルに置くことで、 使用するviewで呼び出すだけでその部品を展開してくれる仕組み。
_(アンダーバー)から始める慣例があるため、_名前.html.erb
というファイルを作成する。
呼び出す方法
呼び出す(使用する)フォームでpartialにある部品を使用したい箇所で
<%= render (partial:) '名前' %>
とすれば、その場所に展開してくれる。
変数を渡す
共通部品に変数を渡したい場合は 呼び出す側で
<%= render '名前', 変数名 :変数 %>
としてあげて、共通部品のフォームで
<%= 変数名 %>
で表示したりできる。
renderとは
レンダリングは、ビューファイルからHTMLを生成し、見た目、装飾を変換してブラウザに表示してくれる流れのこと。
renderはその元になるファイルを指定してあげることができるので、
「ここはこのフォームを読み込んで表示してね」
といった指定をすることが可能になる。
ビューや、コントローラーでも使用することができる。
これがあることで、同じコードを何回も書く必要がなくなり、メンテする場合も1箇所で済むようになるので、 呼び出す側のコードも短くなるし、保守性も上がる。
Railsの基本哲学のうちの1つ、 DRY:Don't Rpeat Yourself(同じことを繰り返さない) に繋がるのかな、と、partialについて学んでいて感じた。