SuzuBlog

webのお勉強はじめたばかりの初心者。備忘録

Rails Modelの規約・命名規則

Modelの規約、命名規則メモ

モデル名とテーブル名の規約
  • 英大文字から始まる
  • 英数字のみ
  • 単語の区切りでは、先頭文字を大文字
  • 単数形の名詞
  • ファイルはapp/modelsディレクトリに格納
  • ファイル名は、モデル名の単語区切りを「_」にし、すべて小文字にしたもの
命名規則

モデル名→先頭は大文字で単数形【User】

モデルのファイル名→先頭は小文字で単数形 【user.rb】

テーブル名→先頭は小文字で複数形 【users】

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_atupdated_atは登録日時、更新日時。このカラムとidは勝手に作ってくれる。 newしただけだと、created_atupdated_atnilであることが確認できる。

有効性のチェック 

#有効性のチェック(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_atupdated_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が発行され、条件WHEREemailとなっている。任意の属性で検索する場合は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)の実装

getpostはリンクを作るときに特に指定しなくてもRailsがいい感じに解釈してくれていたが、DELETEの場合は明示的に指定してあげる必要がある。

Postモデルがあったとして、その削除機能のリンクを作るときは以下のようになる

<%= link_to '[削除]', post_path(post), method: :delete %>

pathはrails routesでルーティングをチェック。post_pathで良さそう。

f:id:hpsuzucat:20201028145305p:plain

そして、明示的に「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について学んでいて感じた。