データベースとモデルとモデルの基本
データベースとは
何らかのデータ(人、商品の情報など)を集めてデータの操作や検索を行えるようにしたもの。
いろいろな種類があるけどよく使われてるのはリレーショナルデータベース。
データベースはテーブルの集合でできている。テーブルとは情報を縦横に並べたもの。※エクセルっぽいやつね。
エクセルとの違いはデータベースのテーブルには法則がある。
各行をレコードと呼び、レコードが1つのデータを表し、列をカラムと呼び、データの内容を表す。
※横=レコード、縦=カラム
各カラムに入るデータは型が決まっている。列の型が整数なら整数しか入らない、型が文字列なら文字しか入らない。
こうしたデータをデータベースマネジメントシステム(DBMS)で管理する。
※MySQLやPostgreSQLなど。※勉強してる本ではSQLite3。SQLite3は勉強用に向いてる。サービスを作るならMySQL
Railsのモデル
Railsではデータベースとやり取りを行うクラスをモデルと呼ぶ
データベースとモデル
モデルクラスのインスタンスは、1つの行(レコード)を表すオブジェクトになり、
テーブルの列(カラム)に相当する属性を持つ。
Railsのモデルではレコードを取り出すにはモデルクラスのメソッドに番号を渡し、
レコードから値を出し入れするときには「変数名.カラム名」のように記述する。
product = Product.find(123) # 123番の商品
name = product.name # nameカラムから値を取り出す
procduct.price = 1980 # priceカラムに値を設定
Railsはメソッド読み出しを自動的にSQL文に変換してくれる。
主キーについて
主キーとは、上記の例のfindメソッドに渡している番号のこと(主キーの値)。
主キーはレコードを識別するためのカラム。
1つのテーブルでは、複数のレコード間で主キーは重複できない。
Railsでは、テーブルに決まった形式の主キーを1つ設定する。主キーのカラム名はid。
テーブルから特定のレコードを取り出す時は、モデルクラスのfindメソッドにidの値を渡す。
データベースの設定
データベース作成の作業は下記の流れで行う。
- DBMSへの接続の設定
- データベーステーブルの作成
- テーブルの定義と作成
- テーブルに入れるデータの作成
接続の設定
DBMSへの接続の設定はconfigフォルダにあるdatabase.ymlで行う
このファイルはRailsアプリケーションを作成したときに勝手にできる
※YAML形式で書かれている。
YMAL形式はインテンドが重要な意味を持つ。
Rails3つのモード
Railsにはアプリケーションのモードが3つある。
それぞれ別のデータベースを使う。
モード名 | 説明 | |
---|---|---|
開発 | development | コードを書きながらブラウザで確認するための環境 |
テスト | test | 自動テストのための環境 |
本番 | production | ウェブサイトを一般に公開するときの環境 |
config/environmentsフォルダの下には、3つのモードごとの設定ファイルがある。
3つのモードは環境変数で区別される。
それぞれ、設定ファイルを編集すると、本番では◯◯、など各自の設定ができる。
データベースの作成
まずはdatabase.ymlの設定に従って開発用につくっていく。
データベースを作るには?
データベースはrakeコマンドで行う
bin/rake db:create
SQLite3は1つのデータベースを1つのファイルとしてあつかう。
上記コマンドで、dbフォルダにはdevelopment.sqlite3とtest.sqlite3のファイルができる。
本番用のデータベースを作成するときは
bin/rake db:create RAILS_ENV=production
を実行すると、dbフォルダ下にproduction.sqlite3ができる。
RAILS_ENVはRailsの実行モードを表す環境変数。
データベースを削除するときは
bin/rake db:drop
bin/rake db:drop RAILS_ENV=production
タイムゾーンの設定
モデルを作詞したりマイグレーションを行なったりする前に
Railsアプリケーションのタイムゾーンの設定を行う。
configフォルダのapplication.rbを編集する
config.time_zone = 'Tokyo'
Railsはデータベースかのテーブルに時刻情報を保存する際に時刻をUTC(協定世界時)に
変換して保存する。このタイムゾーンの設定をすることでその地域似あわせた時差を反映して
データベースから時刻情報を取り出せるようになる。
また、Railsではタイムゾーン機能があるので、
ユーザーの場所によって時間を変えることもできる。※176ページ
Rakeについて
RakeとはRubyで書かれたビルドツールです。
ビルドツールとは指定した一連の手順に従ってファイルの依存関係を調べ自動的にコマンドを実行するソフトウェアのこと。
rakeコマンドに与える db:createなどをタスクと呼ぶ
どんなタスクを使えるかは「bin/rake -T」で確認できる。
こうしたタスクはGemパッケージの中に書かれているが、
自分のRailsアプリケーション用にタスクを書くこともできる。
lib/tasksフォルダの下に拡張子が.rakeのファイルをつくり、
「task :タスク名 do ~ end」の中にタスクのコードを書く。
例:bin/rake member_list で実行できるmembersテーブルから会員番号とユーザー名の一覧を出力するRakeタスク
desc "List all members"
task member_list: :enviroment do
Member.all.each do |member|
puts "#{member.number}\t#{member.name}"
end
end
テーブルの作成
モデルの作成
モデルは「bin/rails g model モデル名」で作成する。
命名規約により、データベースのテーブル名はモデル名の複数形になり、
モデルのクラス名は、モデル名の先頭大文字になる。
modelsフォルダには「モデル名.rb」のファイルができる。
モデルに関するコードはここに記述していく。
※モデル名は必ず単数形にすること!!!
マイグレーション
データベースの中にモデルに対応するテーブルを作っていく。
マイグレーションとはなんぞや
Railsではデータベースのテーブルの作成、変更にマイグレーションという機能を使う。
マイグレーションは自動的にテーブルのカラムを定義してくれたり、開発途中でカラムを追加したり変更したりできる。
「bin/rails g model モデル名」でモデルを作ると
db/migrateフォルダの中に「年月日時分秒_create_テーブル名.rb」というファイルができる。
これがマイグレーションスクリプト。
マイグレーションスクリプトにはchangeメソッドがある。
この中のcreate_tableメソッドはテーブル作成を行うもので、このメソッドに渡すブロックの中にカラムを記述する。
class CreateMembers < ActiveRecord::Migration
def change
create_table :members do |t|
t.timestamps null: false
end
end
end
カラムは「t.カラムの型 :カラム名」という形で記述する。
例えばnameという文字列型のカラムを追加するには
create_table :members do |t|
t.string :name
t.timestamps null: false
end
とする。
membersテーブルの作成
サンプルコード
class CreateMembers < ActiveRecord::Migration
def change
create_table :members do |t|
t.integer :number, null: false
t.string :name, null: false
t.string :full_name
t.string :email
t.date :birthday
t.integer :gender, null: false, default: 0
t.boolean :administrator, null: false, default: false
t.timestamps
end
end
end
「null: false」というオプションは空の値が保存されないようにカラムにNOT NULL制約をつける指定
「null: false, default: 0」のオプションはカラムにNOT NULL制約をつけデフォルト値を0にするという指定。
t.timestampsについて
上記サンプルコードにもあるt.timestampsは「created_at」と「updated_at」という時刻型のカラムを2つ作ってくれる。
Railsはレコードを作成したときにcreated_atカラムに自動的にその時刻を入れる。
またレコードを更新した時はupdated_atカラムに時刻を入れる。
子の2つのカラムを作っておけば、レコード作成と更新の時刻を調べられる。
マイグレーションスクリプトを編集したら必ず実行が必要。
下記コマンドを実行する。
bin/rake db:migrate
これで開発用のデータベースにテーブルが加えられる。本番用で作りたければ本番用の環境変数を付けて実行する。
ちなみにカラム名にtypeは使えない。なんでかって言うと、Railsでの機能のためにtypeカラムが使われているから
つかいたければモデルクラスの定義の中で特別な記述が必要。
マイグレーションの詳細
マイグレーションには機能が色々ある。
カラムの追加
既存のテーブルにカラムを追加したくなることがある。
その作業もマイグレーションでできる。
「bin/rails g migration クラス名」を実行すれば、OK
そうするとカラム追加用のマイグレーションスクリプトができる。
例えばmembersテーブルにカラムを追加したい場合は
bin/rails g migration ModifyMembers
を実行し、
新しいマイグレーションスクリプトのModifyMemberクラスのchangeメソッドに
add_columnメソッドを記述する。
add_columnメソッドの引数には、テーブル名、追加するカラム名、カラムの型を順に指定する。
記述した後は「bin/rake db: migrate」を忘れないこと。
マイグレーションのバージョン
マイグレーションスクリプトファイル名の年月日時分秒はバージョンをあらわしている。
この年月日時分秒のバージョンを指定するとマイグレーションのバージョンを古いものに戻せる。
bin/rake db:migrate VERSION=戻したいバージョン(年月日時年月日)
マイグレーションのバージョンはscima_migrationsテーブルで管理されている。
下記タスクを実行すると現在のマイグレーションのバージョンを確認できる。
bin/rake db:migrate:status
またデータベースを古いバージョンに戻すのは、db:rollbackタスクも使える。
これは直前に行われたマイグレーションを1つだけ取り消すタスク。
bin/rake db:rollback
このロールバックとのマイグレーションはオプションを指定することで直前の複数個を取り消せる。
bin/rake db:rollback STEP=3
バージョンを下げるマイグレーションスクリプトファイル内のchangeメソッド内に、
create_tableメソッドが含まれている場合テーブが削除されるので注意。
カラムの変更と削除
下記メソッドを使うとマイグレーションでカラムを変更したり削除したりできる。
メソッド | 機能 |
---|---|
add_column(テーブル名, カラム名, 型, オプション) | カラムの追加 |
rename_column(テーブル名, カラム名, 新しい名前) | カラム名の変更 |
change_column(テーブル名, カラム名, 型, オプション) | カラムの型の変更 |
remove(テーブル名, カラム名) | カラムの削除 |
change_columnメソッドとremove_columnメソッドににはchangeメソッドの中で
使用するとマイグレーションのロールバックができないという制限がある。
※エラーになる。
changeメソッドではできないロールバックを行うときは
upメソッドとdownメソッドを記述する。
upメソッドにマイグレーションを進める処理を書いて、downメソッドに取り消す処理をかけばロールバックできる。
class ModifyMembers < ActiveRecord::Migration
def up
rename_column :members, :name, :nickname
change_column :members, :gender, :integer :null, false, default: 1
end
def down
change_column :members, :gender, :integer :null, false, default: 1
rename_column :members, :nickname, :name
end
end
インデックス
カラムにはインデックスを加えることができる。インデックスとは索引のための情報。
カラムにインデックスを加えると特定のカラムを使った検索を高速化できます。
但しテーブルと別に索引情報を持つのでメモリが消費される。
※add_indexメソッドを使う。
add_index :members, :name, unique: true, name: 'name_index'
インデックスを削除する場合は、remove_indexメソッドを使う。
columnオプションでカラム名を指定するか、nameオプションでインデックス名を指定します。
remove_index :members, column: 'name'
remove_index :members, name: 'name_index'
add_indexやremove_indexは、change、up、downの各メソッド内に記述できる。
indexについて
インデックスは簡単なアプリケーション、や開発するだけのものは良いですが、
実用するアプリケーションの場合はインデックスが必要。
インデックスがないとレコードが何十万件となると反応に何十秒もかかるウェブサイトになる。
インデックス大事。
開発中と本番でのマイグレーション
開発中にテーブルのカラム定義を変更する方法としては二通りある。
- 新しいマイグレーションスクリプトを追加し、マイグレーションを行う。
- 既存のマイグレーションスクリプトを書き換え、マイグレーションを最初からやり直す。
アプリケーションリリースの前ならどちらでも良いが、
マイグレーションを最初からやり直すときは、Rakeのdb:migrate:resetタスクを使える。
リリース後の本番サーバーでカラムを変更する場合は、データベースの破棄はできないので、1の方法を撮ること。
リリース後のマイグレーション変更は慎重に!!!
アプリケーションをリリースしたあとのマイグレーションは簡単でない。
Backupをとり、テスト環境で必ずテストしましょう。
データの保存
実データベースとテーブルができてもレコードがないとできないっすよね。
開発用のデータを入れてみるで。
レコードの作成と更新
モデルを使ってテーブルにレコードを保存する方法
Railsコンソール
モデルの機能を使って簡単にチェックするには、サーバーを起動せずに
Railsコンソールを使うのが良い。
bin/rails c
レコードの作成
テーブルに新しいレコードを追加する手順は、
「モデルのインスタンスの作成→saveメソッドの呼び出し」となる。
例えばmemberテーブルに新しい会員を登録するには、
newでインスタンスを作り、属性を設定して、saveメソッドでレコードを保存。
saveメソッドの呼び出しを忘れるとデータベースには何も反映されない。
モデルクラスのnewには、「カラム名: 値」を並べたハッシュを渡せる。
※ member = Member.new(number: 1, name: “Taro”)
モデルオブジェクトを作成したあとで、「member.assign_attributes(ハッシュ)」で
値をいれることができる。
クラスメソッドcreateを使うとモデルオブジェクトの作成と保存が同時にできる。
saveとsave!の違い
saveメソッドはモデルのバリデーションの検証を行うときに、
検証に成功するとtrue、失敗すればfalseになる。
レコードを保存するメソッドにはsave!もある。
これは、バリデーションの検証が失敗すれば、falseが返るのではなく、例外が発生します。
保存するときにデータベースにエラーが発生したときは、saveでもsave!でも例外が発生します。
レコードの更新
テーブルに入ってるレコードの情報を変更するときもsaveメソッドを使う。
また、assign_attributesメソッドでも属性を変更できる。
updata_attributesメソッドは、assign_attributesメソッドとsaveメソッドを
合わせたものです。オブジェクトの属性を変更し、ただちにデータベースに保存する。
Railsコンソールは「exit」で終了できる。
シードデータの投入
シードデータの使い方
サイトをリリースする際に、予めデータベースに初期化用のデータを入れておく必要があり、そうしたデータをシードデータと呼ぶ。
※管理者のアカウント情報や、都道府県の名前等
dbフォルダのseeds.rbのファイル内に、シードデータを保存するスクリプトを書く。
例:Memberモデルを使って会員情報を保存するスクリプト。
Member.create(number: 1, name: "Taro", administrator: true)
これで、Rakeのdb:seedタスクを実行すれば、このスクリプトが実行されて、開発用データベースに会員「Taro」のレコードが保存される。
※RAILS_ENV=productionを加えると本番用のデータベースへの保存となる。
bin/rake db:seed
Railsの標準的な手法ではないが、開発用のデータとしてシードデータを用いる方法がある。
もっともらしいデータを入れておいた方が楽しく作業できるからという理由があるらしい。
table_names = %w(members)
table_names.each do |table_name|
path = Rails.root.join("db/seeds", Rails.env, table_name + ".rb")
if File.exist?(path)
puts "Creating #{table_name}..."
require path
end
end
seed.rbを編集
このコードはdb/seeds/developmentフォルダの下に「テーブル名.rb」のファイルがあれば、それをrequireメソッドで実行するもの。
開発用データを入れ込む必要があるので、
dbフォルダの中にseedsフォルダを作り、その中にdevelopmentフォルダを作成し、
members.rbファイルを作る
names = %w(Taro Jiro Hana John Mike Sophy Bill Alex Mary Tom)
fnames = ["佐藤", "鈴木", "高橋", "田中"]
gnames = ["太郎", "次郎", "花子"]
0.upto(9) do |idx|
Member.create(
number: idx + 10,
name: names[idx],
full_name: "#{fnames[idx % 4]} #{gnames[idx % 3]}",
email: "#{names[idx]}@example.com",
birthday: "1981-12-01",
gender: [0, 0, 1][idx % 3],
administrator: (idx == 0)
)
end
上記サンプルコードは10人の会員を作成するコード。
開発初期ではシードデータを書き換えることが多いので、db:resetタスクを使う。
※テーブルの内容をクリアしてからデータを投入するということ。
bin/rake db:reset
bin/rake db:migrate:reset
bin/rake db:seed
マイグレーションファイルを書き換えた時は、db:migrate:resetタスクで
データベースを作りなおしてから投入する。
データベースの確認
データベースの作成、テーブルの作成、データの投入が上手くいっているかどうかを確認するためのコマンドがある。
※SQLite3の場合
sqlite3 db/development.sqlite3 # まずはSQLite3にログイン
sqlite> .table # テーブル一覧を表示
sqlite> .schema members # 「.schema テーブル名」でテーブル定義を表示
sqlite> SELECT * from members; # SQLコマンドの結果を確かめれる。
sqlite> .quit # これでログアウト
レコードの取り出しと検索
Railsのモデル(Active Record)はデータベースからデータを取り出したり検索したりする強力な機能を備えている。
findとfind_byメソッド
テーブルのレコード1つをモデルオブジェクトとして取り出すメソッド
findメソッド
findメソッドにidカラム(主キー)の値を指定すると
その値を持つレコード(モデルオブジェクト)を取り出せる。
※「bin/rails c」で確かめていく。
find_byメソッド
find_byメソッドはあるカラムを使ってレコードを検索し、最初に一致したものを返すモデルクラスのクラスメソッド。引数には「カラム名: 値」を指定する。
検索対象のカラムはいくつも指定できる。.find_by(~~: ~, ~~: ~)的な感じ。
指定された条件に一致しない場合nilが返る。
findメソッドとfind_byメソッドの使い分けに関して
findメソッドを使うときは例外が発生することを前提としたプログラムを作る。
例外を発生させたくない時は、find_byメソッドにidを指定する。この場合は
例外が発生せず、レコードが見つからない場合nilが返る。
クエリーメソッドとリレーションオブジェクト
クエリーメソッドを使うことで検索条件を読みやすく記述できる
また検索条件を細かく指定する方法もある。
クエリーメソッドとリレーションオブジェクトを見る
クエリーメソッドで一番よく使われてるのはwhereメソッド
これを使うと検索条件に一致する複数のレコードを取り出せる。
引数にハッシュで「nameカラムの値がTaro」という検索条件の場合下記
Member.where(name: "Taro")
クエリーメソッドが実際に返しているのは配列ではなくActiveRecord::Relationクラスのオブジェクト。これをリレーションオブジェクトという(本の中だけ??)
リレーションオブジェクトの役割はデータベースからデータを取り出すための検索条件を保持することと、検索を実行してその結果をモデルの配列として使えるようにすること。
保持している検索条件から作られるSQL文を調べるには「to_sql」メソッドを使う。
引数に指定する検索条件を文字列で指定することもできる。
Member.where("number < 20")
検索が実行されるタイミング
whereメソッドでリレーションオブジェクトを作成すると
検索条件を保持している段階で止まっている。
リレーションオブジェクトはRubyの配列と同じ名前のメソッドを持っている。
※each,map,lengthなど。
こうしたメソッドを呼び出すことでSQLによる検索と実行を行ないモデルオブジェクトの配列を利用できるようになります。
ちなみにRailsConsoleでは自動的にinspectメソッドが呼び出されるので、検索が実行されている。
コントローラの中でインスタンsぬ変数@memberにリレーションオブジェクトをセットしても検索は実行されない※下記例
@members = Member.where(gender: 0)
次のようにビューの中でeachメソッドを呼び出すことで、検索が実行される
※「if 条件」が成立しないときは、検索は実行されない
<% if 条件 %>
<% @members.each do |member| %>
<%= member.name %>
<% end %>
<% end %>
つまりコントローラでリレーンションオブジェクトをインスタンス変数にセットしても
ビューでメソッドを呼び出してあげないと検索は実行されない。
見かけ上は配列と同じように振舞っているが、リレーンションオブジェクトは
「実際に検索を実行してデータを取り出すのはデータが必要になった時」という特徴を持っている。
これはLazy Loadingと呼ばれている。
また即座に検索を実行してモデルオブジェクトの配列を作りたい場合は、
loadメソッドを使う。
@members = Member.where(gender: 1).load
上記のようにするとインスタンス変数@membersはリレーションオブジェクトですが
内部にモデルオブジェクトの配列を持つ状態になる。
lengthメソッドとsizeメソッド
lengthメソッドとsizeメソッドを使うと、リレーションオブジェクトが何件の件察結果を返すのかを調べられる。
2つのメソッドは動作が違い、前者は検索を実行してモデルオブジェクトの配列を作り、その配列の長さを返します。
後者はcountメソッドを呼び出してSQLの機能で件数を直接取得します。
普通は後者のsizeメソッドを使うが、検索条件が確定していて、後で必ずモデルオブジェクトの配列を作ることになるなら前者のlengrhメソッドを使うほうがデータベースへの問い合わせが減る。
クエリーメソッドの重ね合わせ
リレーションオブジェクトに対して、さらにクエリーメソッドを呼び出すと検索条件を追加できる。
例:「nameカラムの値がTaro」かつ「numberカラムの値が20未満」の検索条件
members = Member.where(name: "Taro")
members = members.where("number < 20")
# 上記を一行にまとめることもできる。
members = Member.where(name: "Taro").where("number < 20")
検索結果のソート順を指定するにはクエリメソッドorderをつかう。
genderカラムが1の会員をnumberカラムの昇順で取り出す。
※デフォルトが昇順
members = Member.where(gender: 1).order("number")
members = Member.where(gender: 1).order(number: :desc) #降順
※降順にしたい場合は引数をハッシュにして「カラム名: :desc」を指定する。
クエリーメソッド一覧
メソッド | SELECT文の構成部分 | 補足 |
---|---|---|
select(文字列) | SELECT | |
from() | FROM | |
joins() | JOIN | テーブル結合 |
includes() | DBMSによる | 関連付けの名前を指定すると関連するモデルオブジェクトを同時にロードする |
where() | WHERE | 検索条件の指定 |
group() | GROUP BY | |
having() | HAVING | |
limit() | LIMIT | 取得するレコード数の上限 |
offset() | DBMSによる | 何行目からレコードを取得するか |
order() | ORDER BY | ソート対象のカラム名 |
reoder() | ORDER BY | ORDER BY句の上書き |
reverse_order | ORDER BY | ORDER BY句の昇順降順を逆にする |
lock() | DBMSによる | MySQLのロック機能を使う |
readonly | ||レコードを読み込み専用にする | |
distinct | |検索結果の重複をなくす| | |
none | |何も検索しないリレーションオブジェクトを返す| |
ファインダーメソッドとの組み合わせについていて
リレーションオブジェクトにはファインダーメソッドというのがある。
たとえばfirstメソッドは検索条件に一致するレコードを先頭から1個だけ取り出し、
モデルオブジェクトを1個(存在しなければnil)を返す。
末尾からレコードを1つ取り出すのがlastメソッド。
firstメソッドもlastメソッドも使うときはorderメソッドでソート順を指定してあげないとダメ。ソート順がないと結果が不安定になる。
ファインダーメソッドには他にも
findとfind_byメソッドがあり、機能としてはモデルクラスメソッドのものと同じ。
ファインダーメソッドはクエリーメソッドの検索条件に縛られる。
検索条件にマッチしたレコードの中から探すということ。
whereメソッドの便利な使い方
whereメソッドに「カラム名: 配列」のハッシュを渡すとカラムの値が
「複数の候補のどれかと同じ」という検索条件を指定できる。
またハッシュの値を範囲オブジェクトにすると、あるカラムの値がその範囲にあるという
検索条件を指定できる。
whereメソッドの直後にnotメソッドを指定すると「◯◯」でないという検索条件が使える。
このときwhereメソッドには引数をなしにして、notメソッドの引数に条件を指定する。
プレースホルダー
whereメソッドには文字列を指定することができて、
この文字列に疑問符(?)を含めるとプレースホルダーとなる。
プレースホルダーとは、指定した値をSQL文の中に埋め込むための印のこと
irb(main):019:0> name = "Taro"
=> "Taro"
irb(main):020:0> members = Member.where("name = ?", name) ; nil
=> nil
irb(main):021:0> puts members.to_sql
SELECT "members".* FROM "members" WHERE (name = 'Taro')
=> nil
whereメソッドには引数を2つ指定している。
第一引数はプレースホルダーを入れたSQL文のWHERE句で、第二引数は文字列
第一引数にプレースホルダーが幾つもある場合は、その個数に応じて非キスの数を増やす。
プレースホルダーを使えば、単純なwhereメソッドでは作れないものを作れる。
wehereメソッドでの注意
whereメソッドで検索を行うときに、変数を直接埋め込んではいけない。
変数の中に、SQL文にとって意味のある文字が含まれているとデータベースが不正に利用されるから。どうしてもヘンスを使いたい場合はハッシュで指定すると良い。
集計用のメソッド。
モデルクラスで用意されている集計用のメソッド
メソッド | 機能 |
---|---|
average(カラム名) | 平均 |
count | レコードの数 |
maximum(カラム名) | 最大値 |
minimum(カラム名) | 最小値 |
sum(カラム名) | 合計 |
集計用のオブジェクトはリレーションオブジェクトでも使える。
SQL文を直接指定する方法
モデルクラスではfindメソッドだけでなく、find_by_sqlメソッドを使ってSQL文を直接指定することもできる。
whereメソッドと同じくプレースホルダー(?)も使える
ただし引数全体を配列で指定する必要がある。
今日は長かったな、ここまでにしよう。
本記事は下記本の勉強記事です。初学者にとても良い本です。