yucatio@システムエンジニア

趣味で作ったものいろいろ

Ruby初心者 AcriveRecordのscope定義式の意味を理解する

Ruby on Railsの環境構築が終わったので、"パーフェクト Ruby on Rails"に載っていサンプルアプリを作っていきます。

プロジェクトの作成とモデルの作成

rails new プロジェクト名

で新しいプロジェクトを作成します。本のサンプルに従って、プロジェクト名は book_admin としました。

$ rails new book_admin

モデルの生成には rails g model コマンドを使用します。カラム名とデータ型の対は複数指定できます

rails g model モデル名 カラム名 : データ型 カラム名 : データ型 ...

$ ./bin/rails g model Book name:string published_on:date price:integer number_ofpage:integer

scope定義の文

scopeを定義することでwhere文に名前をつけて管理することができます。 値段(price)が3000以上のデータを抽出するスコープを定義します。

class Book < ActiveRecord::Base
  scope :costly, -> { where("price > ?", 3000) }
end

Java エンジニア、悩む

本に従ってこのコードを書いてみたのですが、文の意味がわかりません。どのような要素で成り立っているのか、costlyの最初のコロン(:)はシンボルを表すらしいけれどシンボルとは何なのか、カンマは何なのか矢印(->)は何を意味するのか。

ひとつひとつ解読していく

クラス宣言

まずはクラス宣言の部分をみていきます

class Book < ActiveRecord::Base
  # 略
end

Bookクラスを宣言しています。 "< ActiveRecord::Base" はActiveRecord::Baseクラスの拡張していることを意味します。 ActiveRecord::BaseはActiveRecordモジュールのBaseクラスを表します。

スコープ定義文
scope :costly, -> {where("price > ?", 3000) }

はじめ、この文を見たときに、矢印(->)で文が区切られているのかと思って悩みました("scope :costly," と "{where(..)}" で分かれるのかと思った)

実際はscopeメソッドとその引数なので、対応関係は以下のようになります

役割
メソッド scope
第1引数 :costly
第2引数 -> { where("price > ?", 3000) }

第1引数はシンボルです。シンボルについてまだよく理解できてはいませんが、以下の記事が役に立ちました。シンボルは"名前に対応した整数"だそうです。なので、引数に渡したシンボルで新たなメソッドを定義できるというわけです。(上記の例だとBook.costlyで第2引数に渡したブロックが実行される)

Rubyのシンボルは文字列の皮を被った整数だ!

第2引数は手続きオブジェクトです。矢印とカッコ(-> {...})はlambda記法です。lambda { where("price > ?", 3000) } と書いても同じです。

whereメソッドSQLインジェクション

where()はSQLのwhere条件を追加するためのメソッドです。"price > ?" の クエスチョンマークはプレースホルダーと呼ばれ、第2引数以降の値が割り当てられます。where("price > ?", 3000) と where("price > 3000") はほぼ同じ内容を表します(完全に同じではない)。

where("price > 3000") と書かずに、プレースホルダーを使ってwhere("price > ?", 3000) と書くのは、SQLインジェクションという攻撃を無効にするためです。今回、第2引数は数値でしたが、通常はユーザの任意の入力をSQL文として組み立てることになります。ユーザの入力をSQL文として組み立てるとき、開発者の意図しないSQL文が組み立てられることがあります(ユーザ入力にSQLのキーワードが含まれる場合)。プレースホルダーを使うことで、この脆弱性をなくすことができます。

SQLインジェクションに対する脆弱性を作らないようにするため、検索条件には必ずプレースホルダーを使わなければなりません。

パーフェクトRuby on Rails

パーフェクトRuby on Rails
著者:すがわらまさのり
価格:3,110円(税込、送料込)
楽天ブックスで詳細を見る

環境