SQL文を読み解こう①(Pundit, Simple_form,FormObject,scope)
joinsでテーブルをくっつけた時に発行されたSQL文を読み解くための記事です。RailsのORMであるActiveRecordと実際に発行されるSQLを理解することで、今後ActiveRecordを扱うときのreading力を高めることができると考えやした。#やした
下記項目をざっくり学べます。
・INNER JOIN句
・IN句
・Pluckメソッド
・Pundit gem
・Simple_form gem
・FormObject
・scope
まず下記SQLを読み解く。
SELECT "taxonomies"."id" ・・①
FROM "taxonomies" ・・②
INNER JOIN "article_tags" ・・③
ON "taxonomies"."id" = "article_tags"."tag_id" ・・④
WHERE "taxonomies"."type"
IN ('Tag') AND "article_tags"."article_id" = ? [["article_id", 21]] ・・⑤
①何を: taxnomies.idを
②どこから: taxonomiesテーブルから
③どのように: article_tags テーブルとtaxonomiesテーブルをinner joinさせて
④どんな条件で1: taxonomies.idとarticle_tags.tag_idが一緒である
⑤どんな条件で2:Tagモデルにある taxonomies.typeと、article_tags.article_idが22である
補足:
IN句とは
複数の一致するかの条件判定をまとめて行うために使用する命令
【フルーツテーブル(fruit)の、名前が「みかん」か「りんご」の要素を取得する】
SELECT * FROM fruit WHERE name = "みかん" OR name = "りんご";
↑を↓は同じ意味
SELECT * FROM fruit WHERE name IN("みかん","りんご");
どんなコードを書いたら先のSQL文が発行されるか。
順を追って読み解いていきます。
- 補足:
- IN句とは
- どんなコードを書いたら先のSQL文が発行されるか。
- 1. simple_formって何
- 2. いやpluckって何
- 3. controllerの挙動どうなってるん?
- controller
- simple_formって何
- いやpluckって何
- controllerの挙動どうなってるん?
- Punditて何
- FormObjectて何
- ほんでscopeて何なんw
1. simple_formって何
フォームの作成局面で先のSQL文が発行されています。
今回はsimple_formを使い、記事投稿におけるtagの作成を行うフォームを作成しています。
# edit.html.slim
= simple_form_for @article, url: admin_article_path(@article.uuid) do |f|
= f.input :tag_ids, as: :select2, collection: Tag.pluck(:name, :id), include_blank: false, input_html: { multiple: true }
解説:
@article モデルにf.inputの内容を格納して admin_article_pathに渡しています。admin_article_pathに遷移するときのparams[:uuid]を指定するために(@article.uuid)をadmin_article_pathの後ろにつけています。
simple_formとは
カラムの型に応じてformの種類の自動で判断し生成してくれる便利なgemです。
今回は、select2というタイプを使って、下記のようなフォームを作成しています。値を入れる場所をクリックしたらスクロールで候補を出現させてくれるようなフォームになりますね。
2. いやpluckって何
Tag.pluck(:name, :id)
モデル.pluck(カラム名 [, ...])
Tag.pluck(:name,:id)
# SELECT tag.id, tag.name FROM tag
# [['ruby',1], ['php',2], ['python'],3]
このTagは下記のように構成されていて、pluckを使って、idカラムとnameカラムを上記のように配列形式で表示することができます。
Tag(id: integer, type: string, name: string, slug: string, description: text, created_at: datetime, updated_at: datetime)
3. controllerの挙動どうなってるん?
controller
フォームを入力したときの挙動を記入してあります。
Articleから、渡されたuuidと同じ@articleを取り出しています。ここでは、punditと言うgemを使用し、編集権限を精査しています。punditとは専門家と言う英単語を由来としていて、おそらく、専門⇨その道のプロ⇨プロにしかできないこと⇨ プロ = 管理権限のあるユーザーと言うロジックでしょう。知らんけども。#知らんけども
# controller
class Admin::ArticlesController < ApplicationController
layout 'admin'
before_action :set_article, only: %i[edit update destroy]
def edit
authorize(@article)
//とってきたuuidを持つユーザーに編集権限がなければ例外を出す。
end
private
def set_article
@article = Article.find_by!(uuid: params[:uuid])
end
end