ActiveRecord入門

More than 3 years have passed since last update.

SQLを意識せずにデータベースをRubyオブジェクトのように扱えるもの


引用: ActiveRecord入門 (全14回)-ドットインストール



1 ActiveRecordとは

Ruby on RailsのORマッパー

ObjectとRelational Data Baseをつなぐ

Mac-no-MacBook-Pro:sinatora_lessons Mac$ gem list activerecord

*** LOCAL GEMS ***

activerecord (4.2.0)
Mac-no-MacBook-Pro:sinatora_lessons Mac$ gem list sqlite3

*** LOCAL GEMS ***

dbd-sqlite3 (1.2.5)
sqlite3 (1.3.10)
sqlite3-ruby (1.3.3)
Mac-no-MacBook-Pro:sinatora_lessons Mac$ gem -v
2.2.2


2データベースの準備をしよう

ar_lessons

┣blog.db

┗import.sql


import.sql

create table posts( #テーブル名は英単語の複数形

id integer primary key,
title text,
body text,
create_at, #日時
updated_at 

);


Mac-no-MacBook-Pro:sinatora_lessons Mac$ cd ../

Mac-no-MacBook-Pro:Mac Mac$ cd ar_lessons
Mac-no-MacBook-Pro:ar_lessons Mac$ sqlite3 blog.db
SQLite version 3.8.5 2014-08-15 22:37:57
Enter ".help" for usage hints.
Mac-no-MacBook-Pro:ar_lessons Mac$ sqlite3 blog.db
SQLite version 3.8.5 2014-08-15 22:37:57
Enter ".help" for usage hints.
sqlite> .read import.sql
sqlite> .schema
CREATE TABLE posts(
id integer primary key,
title text,
body text,
create_at,
updated_at 

);
sqlite> select * from posts
...> ;
sqlite>.exit

テーブルが完成したので次回ActiveRecordから扱う方法


3 はじめてのAR

RubyファイルからARをつかってテーブルを操作

ar_lessons

┣main.rb

┣blog.db

┗import.sql


main.rb

require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" =>"sqlite3",
"database" => "./blog.db"
)

class Post < ActiveRecord::Base #import.sqlのテーブル名postsを大文字、単数形に変える
end
#これでARとRubyのオブジェクトが紐付けられた

post = Post.new(:title => "title1",:body => "hello" )
post.save

p Post.all


SQL文を書かなくても操作できるのがメリット

sqlite> drop table posts 

...> ;
sqlite> .schema
sqlite> .read import.sql
sqlite> .schema
CREATE TABLE posts(
id integer primary key,
title text,
body text,
created_at,
updated_at
);
sqlite> .exit
Mac-no-MacBook-Pro:ar_lessons Mac$ ruby main.rb
#<ActiveRecord::Relation [#<Post id: 1, title: "title1", body: "hello", created_at: "2015-02-13 15:08:28.961826", updated_at: "2015-02-13 15:08:28.961826">]>


4レコードを挿入してみよう

レコードの挿入方法について


main.rb

require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" =>"sqlite3",
"database" => "./blog.db"
)

class Post < ActiveRecord::Base #import.sqlのテーブル名postsを大文字、単数形に変える
end
#これでARとRubyのオブジェクトが紐付けられた

#post = Post.new(:title => "title1",:body => "hello" )

=begin
post = Post.new
post.title = "title2"
post.body = "hello2"
post.save
=end

=begin
post = Post.new do |p|
p.title = "t"
p.body = "h"
end
post.save
=end

Post.create(:title => "title4",:body => "hello4" )
#これなら1行で.newと.saveの機能がある

p Post.all



5all,first,last,findをつかう

レコードを抽出するために基本的な命令について学ぶ


main.rb

require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" =>"sqlite3",
"database" => "./blog.db"
)

class Post < ActiveRecord::Base #import.sqlのテーブル名postsを大文字、単数形に変える
end
#これでARとRubyのオブジェクトが紐付けられた

1.p Post.all
2.p Post.first
3.p Post.last.title
4.p Post.find(3)
5.p Post.find_by_title("title2")
6.p Post.find_by_title_and_id("title2",2)


findを使えば任意のレコードを抽出できる


6whereをつかってみよう


main.rb

require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" =>"sqlite3",
"database" => "./blog.db"
)

class Post < ActiveRecord::Base #import.sqlのテーブル名postsを大文字、単数形に変える
end
#これでARとRubyのオブジェクトが紐付けられた

1.p Post.where(:title => "title1",:id => 1)
2.p Post.where(:title => ? and id = ?,"title1",1)
3.p Post.where(:title => :title and id = :id,{:title => "title1",:id => 1})

4.p Post.where("id > ?",2)
5.p Post.where("body like ? ,"hello%")



7order,limit,scopeを使ってみよう

並び替えや抽出件数を指定する方法、抽出条件を定義できるscopeの使い方について解説していきます。


main.rb

require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" =>"sqlite3",
"database" => "./blog.db"
)

AcriveRecord::Base.logger = Logger.new(STDOUT)

class Post < ActiveRecord::Base
scope :top3,order(created_at).limit(3)

end
#これでARとRubyのオブジェクトが紐付けられた

1.p Post.where(:id => 1..3)
2.p Post.where(:id => [1,3])

並び替え(orderは基本昇順)、3つ降順(desc)
3.p Post.order("id desc").limit(3)

抽出条件をscopeで定義
4.p Post.top3

条件を組み立てているときにどういうsqlを組み立てているか確認できる5.AcriveRecord::Base.logger = Logger.new(STDOUT)



08 first_or_createを使ってみよう

今まではレコードの挿入と抽出してきた

抽出結果がなかったらレコードの新規作成をしてくれるfirst_or_createについて見ていきます。


main.rb

require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" =>"sqlite3",
"database" => "./blog.db"
)

class Post < ActiveRecord::Base #import.sqlのテーブル名postsを大文字、単数形に変える
end

title4がある場合は表示
1.p Post.where(:title => "title4").first_or_create

title5がない場合は新規作成
2.Post.where(:title => "title5").first_or_create
3.p Post.all

4.Post.where(:title => "title6").first_or_create do |p|
p.body = "hello6"
end
5.p Post.all



09 レコードを更新してみよう


main.rb

require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" =>"sqlite3",
"database" => "./blog.db"
)

class Post < ActiveRecord::Base #import.sqlのテーブル名postsを大文字、単数形に変える
end

post = Post.find(1)

1.=begin
post.title = "(new)title"
post.save
=end

2.post.update_attribute(:title,"(new2)title")

3.post.update_attributes(:title=>"(new2)title",":body"=>"")

4.Post.where(:id => 1..2).update_all(:title =>"",:body => "")

p Post.all



10 レコードを削除してみよう

レコードを削除するdelete、destroyについて見ていきます。

deleteは単にレコードの削除で早い

destroyは関連するオブジェクトを削除することができるが遅い


main.rb


require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" =>"sqlite3",
"database" => "./blog.db"
)

class Post < ActiveRecord::Base
end

1.Post.where(:id =>1..2).delete_all
2.Post.find(3).destroy


複数削除は_allを付ける


delete from developer_games where id > 92;


11 バリデーションを使ってみよう

フィールドの妥当性をチェックするバリデーションの使い方について見ていきます。

ルールを付ける


main.rb


require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" =>"sqlite3",
"database" => "./blog.db"
)

class Post < ActiveRecord::Base
タイトルは必ず付ける
validates :title, :presence => true
長さを5文字以上
validates :body, :length => {:minimum => 5}
これを満たさない場合はsaveされない
end

post = Post.new(:body =>"123")
post.save

エラー表示
1.post.save!

2.if !post.save
p post.errors.messages
end



12 アソシエーションを使ってみよう (1)

関連するデータをまとめて扱うことができるアソシエーションについて見ていきます。まずはテーブルを用意します。


import.sql

drop table if exists posts;

create table posts(
id integer primary key,
title text,
body text,
created_at,
updated_at
);
insert into posts(id,title,body) values (1,"title1","hello1");
insert into posts(id,title,body) values (2,"title2","hello2");
insert into posts(id,title,body) values (3,"title3","hello3");

drop table if exists comments;
create table comments(
id integer primary key,
post_id integer,
title text,
body text,
created_at,
updated_at
);
insert into posts(id,post_id,body) values (1,1,"comment1");
insert into posts(id,post_id,body) values (2,1,"comment2");
insert into posts(id,post_id,body) values (3,2,"comment3");
insert into posts(id,post_id,body) values (4,2,"comment4");
insert into posts(id,post_id,body) values (5,3,"comment5");
insert into posts(id,post_id,body) values (6,3,"comment6");



13 アソシエーションを使ってみよう (2)

アソシエーションを設定し、抽出したpostに関連するcommentを表示してみます。


main.rb

require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" =>"sqlite3",
"database" => "./blog.db"
)

class Post < ActiveRecord::Base #import.sqlのテーブル名postsを大文字、単数形に変える
has_many :comment
end

class Comment < ActiveRecord::Base #import.sqlのテーブル名commentsを大文字、単数形に変える
belongs_to :post
end

#postとcommentsの関係が一対多

post = Post.find(1)
post.comments.each do |comment|
p comment.body
end



14 アソシエーションを使ってみよう (3)

postを削除したときに、それに関連したcommentも削除してみます。


main.rb

require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" =>"sqlite3",
"database" => "./blog.db"
)

class Post < ActiveRecord::Base #import.sqlのテーブル名postsを大文字、単数形に変える
has_many :comment, :dependent => :destroy
end

class Comment < ActiveRecord::Base #import.sqlのテーブル名commentsを大文字、単数形に変える
belongs_to :post
end

#postとcommentsの関係が一対多

p Post.all
p Comment.all

Post.find(1).destroy
#関連するモデルを消すのでdestroy

p Post.all
p Comment.all



csv出力

sqlite> .mode csv

sqlite> .output game.csv
sqlite> select * from developer_games;