3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MicroPostにおける投稿機能

Last updated at Posted at 2018-08-30

この記事では、Micorpostにおける投稿機能について、
Modelのコーディングを簡単に理解した後、検証を通じて理解を深める事を目的としている。

投稿機能は以下の手順でコーディングを行う

  • モデルファイルとマイグレーションファイルの作制
  • Micropostmodel
  • UserModel

投稿機能は簡単に説明すると
ユーザーがツイートを投稿する際、そのツイートにユーザ情報を持たせる、
という機能を実装する。

では、手順に沿って解説を行う。

1.モデルファイルとマイグレーションファイルの作成

railsコマンドにより、Micropostモデルを作成します。
カラムはcontent:stringuser:referencesの二つです。

Commandline

qiita.rb
$ rails g model Micropost content:string user:references

      create    db/migrate/20170207073121_create_microposts.rb
      create    app/models/micropost.rb

一対多を設定する場合には、user:references のように、
データの型として references を指定します

references の詳しい説明は後述します。

### ①マイグレーションファイル
マイグレーションファイルを見てみましょう。

db/migrate/年月日時_create_microposts.rb

qiita.rb
class CreateMicroposts < ActiveRecord::Migration[5.0]
  def change
    create_table :microposts do |t|
      t.string :content
      t.references :user, foreign_key: true

      t.timestamps
    end
  end
end

Micropost が持つカラムは、 contentuser です。
content はツイートメッセージであり
user は User と一対多の関係を保存するためのカラムです。

テーブルを作成するマイグレーションファイル内で
t.references という記述は「別のテーブルを参照させる」という意味になります。

User にカラムを追加せずとも、Micropost に User 用のカラムを追加するだけで
データベース上の一対多の関係が表現可能になります。

t.references :user, foreign_key: true は、
実際のデータベース上では、 user_id カラムとして存在し、
そこにMicropostインスタンスの User の id が保存されます。
Railsの方で自動的にUserを参照するようになっている。

これで Micropost を発言したユーザを特定することができます。
また、foreign_key は外部キー制約というものです。
外部キー制約についてはここでは説明しません。

### ②Micropost Model
app/models/micropost.rb

qiita.rb
class Micropost < ApplicationRecord
  belongs_to :user
end

belongs_to :userは、User と Micropost の一対多を表現している。
つまり、「参照元テーブルから参照先テーブルにアクセスする」のである。
belongs_toの記述よってMicropostのuser_idと、Userのidの値が紐付きます。

このコードのおかげで、micropost.user とすると、
この micropost インスタンスを持っている User を取得することができる。

Railsドキュメント:belongs_to

2.モデルファイルとマイグレーションファイルの作成

### ①マイグレーションファイル
db/migrate/20170206063439_create_users.rb

qiita.rb
class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email
      t.string :password_digest

      t.timestamps
    end
  end
end

### ②User Model
app/models/user.rb

qiita.rb
class User < ApplicationRecord
  before_save { self.email.downcase! }
  validates :name, presence: true, length: { maximum: 50 }
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i },
                    uniqueness: { case_sensitive: false }
  has_secure_password

  has_many :microposts
end

User モデルファイルも一対多を表現しておきます。
User から Micropost をみたとき、複数存在するので、
has_many :micropostsとします。

これによりuser.microposts にて
User のインスタンスが自分の Microposts を取得することができます。

テーブルを作成するマイグレーションファイル内で
t.references という記述は別のテーブルを参照させるという意味になります。

#3.[検証]rails console で投稿を作成

qiita.rb
user = User.first

firstは、データベースに保存された最もid の若いユーザレコードの
インスタンスを取得することができます。

このuserは、user_idの1を保持している。

qiita.rb
> user.microposts
  Micropost Load (0.5ms)  SELECT `microposts`.* FROM `microposts` WHERE `microposts`.`user_id` = 1
 => #<ActiveRecord::Associations::CollectionProxy []>

Userモデルのhas_many :microposts'により、 user.microposts` が使えるようになっている。

この時点でuser.microposts を使って
User のインスタンスが自分の投稿(microposts) を取得しても、
中身はまだ空っぽである。

ここでは、Micropostモデルの操作が、最終的には SQL を生成し、
micropostsテーブルからuser_idが1のレコードを検索し、結果が空となっている。

qiita.rb
> micropost = user.microposts.build(content: 'hello')
 => #<Micropost id: nil, content: "hello", user_id: 1, created_at: nil, updated_at: nil>

今度は投稿(micropost)のインスタンスを生成してみよう。
投稿の作成は user.microposts.build のように操作する。
先ほどfirstにより取得したインスタンスを元に、ポストを作成する。

user.microposts.build 、いわゆるbuild
Micropost.new(user: user) と同じようにインスタンス生成の処理である。
※userカラムに予め変数が代入されている。

このコードにより、Micropostのインスタンスが生成され、
生成されたインスタンスは、User_idが付保されることで、
Userとの紐付がなされる。

belongs_toの記述よってMicropostのuser_idと、Userのidの値が紐付いているので、
Micropost.new(user: user)でも値を渡す際に、
内部的にこの関連付けが使われるので、上手くいくということです。

ただ、ここはMicropost.new(user: user)より
Micropost.new(user_id: user.id)の方が、イメージしやすい。
belongs_toによってテキストのようにも書ける、と覚えておけば良い。

user_idに値が入っており、これにより、
投稿をユーザーと紐付けて作成しているのである。

qiita.rb
> micropost.save
   (0.3ms)  BEGIN
  SQL (0.7ms)  INSERT INTO `microposts` (`content`, `user_id`, `created_at`, `updated_at`) VALUES ('hello', 1, '2017-02-07 07:52:59', '2017-02-07 07:52:59')
   (5.0ms)  COMMIT
 => true

保存する

qiita.rb
> User.first.microposts
  User Load (0.3ms)  SELECT  `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
  Micropost Load (0.3ms)  SELECT `microposts`.* FROM `microposts` WHERE `microposts`.`user_id` = 1
 => #<ActiveRecord::Associations::CollectionProxy [#<Micropost id: 1, content: "hello", user_id: 1, created_at: "2017-02-07 07:52:59", updated_at: "2017-02-07 07:52:59">]>

改めて、ユーザーの投稿を確認してみよう。
先ほどのレコードが保存されていることが分かる。

User.first.micropostsとは、
user = User.firstuser.micropostsを繋げて書いたものである。
has_many :micropostsのアソシエーションで使えるようになったメソッドである。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?