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引数に渡したブロックが実行される)
第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 |
環境
- OS : Mac OS X バージョン 10.8.4
- Ruby バージョン 2.3.1
- Ruby on Rails バージョン 4.2.6