Help us understand the problem. What is going on with this article?

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;
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした