LoginSignup
1
0

More than 5 years have passed since last update.

accepts_nested_attributes_forによるCRUD操作について学ぶ_100DaysOfCodeチャレンジ7日目(Day_7:#100DaysOfCode)

Last updated at Posted at 2018-06-22

はじめに

この記事はTwitterで人気のハッシュタグ#100DaysOfCodeをつけて、
100日間プログラミング学習を続けるチャレンジに挑戦した7日目の記録です。

動作環境

  • ruby 2.4.1
  • Rails 5.0.1

現在学習している内容のリポジトリ

本日学んだこと

  • accepts_nested_attributes_forによるCRUD操作

accepts_nested_attributes_forについては以下の記事で解説しています。

accepts_nested_attributes_forについて学ぶ_100DaysOfCodeチャレンジ6日目(Day_6:#100DaysOfCode)

CRUD(クラッド)とは?

CRUDとは、以下の頭文字を組み合わせて作成された用語です。

  • Create(登録)
  • Read(参照)
  • Update(更新)
  • Destroy(削除)

CRUDはシステムを構築する上で重要な4つのメイン機能を、一つの言葉として表しているんですね。

乱暴な言い方をすれば、CRUD操作ができれば、最低限システムとして成り立っていることになります。

accepts_nested_attributes_forでCRUD操作をやってみる

accepts_nested_attributes_forメソッドを使ってCRUD操作を行う時、いくつかポイントがあるのでみて行きましょう。

Create(Strong_paramaters)

Strong_paramatersは、Rails4系から搭載されたActiveRecordの機能。

requireメソッドでモデル名、permitメソッドでモデルが持つ属性名を指定することで、その指定条件にマッチしたパラメーターだけを受け付けるというものです。

accepts_nested_attributes_forでCreateをする場合、Strong_paramatersで対象となるモデルの属性名を指定する必要があります。

#{関連したモデル名}_attributes: [:属性名]の形式でpermitメソッドの引数に渡してあげればCreateできるようになりますね。

Contactモデル

# app/models/contact.rb
class Contact < ApplicationRecord
  # モデル同士の関連付け
  belongs_to :kind
  has_many :phones

  accepts_nested_attributes_for :phones
end

Phoneモデル

class Phone < ApplicationRecord
  belongs_to :contact, optional: true
end

contactコントローラー


# POST /contacts
  def create
    @contact = Contact.new(contact_params)

    if @contact.save
      render json: @contact, status: :created, location: @contact
    else
      render json: @contact.errors, status: :unprocessable_entity
    end
  end

private

  def contact_params
    params.require(:contact).permit(:name, :email, 
                                    :birthdate, :kind_id,
                                    phones_attributes: [:number])
  end

Read(include)

accepts_nested_attributes_forのRead操作は、対象となるアクションにincludeメソッドを使ってモデル名をシンボルで渡してあげればOK。

contactコントローラー

# GET /contacts/1
  def show
    render json: @contact, include: [:kind, :phones]
  end

renderによってJSONでの表示結果が、KindモデルとPhoneモデルもネストされた状態で出力されるようになります。

# render jsonによる出力結果
{
    "id": 4,
    "name": "菅原 拓海",
    "email": "providenci@swaniawski.co",
    "birthdate": "2012-06-03",
    "created_at": "2018-06-20T14:02:48.716Z",
    "updated_at": "2018-06-20T14:02:48.716Z",
    "kind_id": 1,
    "kind": {
        "id": 1,
        "description": "Goodmorning!",
        "created_at": "2018-06-20T14:02:47.349Z",
        "updated_at": "2018-06-20T14:02:47.349Z"
    },
    "phones": [
        {
            "id": 6,
            "number": "080-8807-5906",
            "contact_id": 4,
            "created_at": "2018-06-20T14:02:49.660Z",
            "updated_at": "2018-06-20T14:02:49.670Z"
        },
        {
            "id": 7,
            "number": "080-6345-8352",
            "contact_id": 4,
            "created_at": "2018-06-20T14:02:49.678Z",
            "updated_at": "2018-06-20T14:02:49.684Z"
        },
        {
            "id": 8,
            "number": "090-5822-0671",
            "contact_id": 4,
            "created_at": "2018-06-20T14:02:49.691Z",
            "updated_at": "2018-06-20T14:02:49.698Z"
        },
        {
            "id": 225,
            "number": "070-1407-9142",
            "contact_id": 4,
            "created_at": "2018-06-20T14:46:42.691Z",
            "updated_at": "2018-06-20T14:46:42.691Z"
        }
    ]
}

Update(id)

accepts_nested_attributes_forのUpdate操作は、対象となるIDを指定する必要があります。

Contactモデル

# app/models/contact.rb
class Contact < ApplicationRecord
  # モデル同士の関連付け
  belongs_to :kind
  has_many :phones

  accepts_nested_attributes_for :phones
end

この場合、Phoneモデルの情報を更新させたい場合には、contact_idに紐づいたPhoneモデルのidを指定する必要があるということになりますね。

Before


{
    "id": 4,
    "name": "菅原 拓海",
    "email": "providenci@swaniawski.co",
    "birthdate": "2012-06-03",
    "created_at": "2018-06-20T14:02:48.716Z",
    "updated_at": "2018-06-20T14:02:48.716Z",
    "kind_id": 1,
    "kind": {
        "id": 1,
        "description": "Goodmorning!",
        "created_at": "2018-06-20T14:02:47.349Z",
        "updated_at": "2018-06-20T14:02:47.349Z"
    },
    "phones": [
        {
            "id": 6,
            "number": "080-8807-5906",
            "contact_id": 4,
            "created_at": "2018-06-20T14:02:49.660Z",
            "updated_at": "2018-06-20T14:02:49.670Z"
        }
    ]
}

たとえばPhonesのnumberを更新させたい場合、最低限Afterのように記述する必要があります。

After

{
    "id": 4,
    "name": "菅原 拓海",
    "email": "providenci@swaniawski.co",
    "birthdate": "2012-06-03",
    "created_at": "2018-06-20T14:02:48.716Z",
    "updated_at": "2018-06-20T14:02:48.716Z",
    "kind_id": 1,
    "kind": {
        "id": 1,
        "description": "Goodmorning!",
        "created_at": "2018-06-20T14:02:47.349Z",
        "updated_at": "2018-06-20T14:02:47.349Z"
    },
    "phones": [
        {
            "id": 6,
            "number": "0120-234-5678",
        }
    ]
}

Delete(allow_destroy: true,_destroy)

accepts_nested_attributes_forによるDelete操作は、モデルにallow_destroy: trueを指定するという特殊な方法で行います。

APIでPhoneモデルのレコードを削除する場合、対象となるidを指定した上でハッシュのkeyに_destroy、valueに1またはtrueを記述します。

その後、Strong_Paramatersのpermitメソッドにシンボルで:_destroyを渡すと、削除されるようになります。

{
    "id": 4,
    "name": "菅原 拓海",
    "email": "providenci@swaniawski.co",
    "birthdate": "2012-06-03",
    "created_at": "2018-06-20T14:02:48.716Z",
    "updated_at": "2018-06-20T14:02:48.716Z",
    "kind_id": 1,
    "kind": {
        "id": 1,
        "description": "Goodmorning!",
        "created_at": "2018-06-20T14:02:47.349Z",
        "updated_at": "2018-06-20T14:02:47.349Z"
    },
    "phones": [
        {
            "id": 6,
            "_destroy": 1
        }
    ]
}

参考リンク

1
0
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
1
0