Rails + Nuxt ~編集(update)、削除(delete)~

Rails + Nuxt ~編集(update)、削除(delete)~

前回の記事まででコンテンツ一覧、詳細表示、コンテンツ新規作成まで実装できたので、今回の記事はコンテンツの編集、削除の機能を実装していきます。

前回の記事はこちら:

Rails + Nuxt モダンなアプリケーションの作成~投稿の新規作成から詳細表示まで~

1.編集画面作成(Nuxt)

まず、詳細画面の「Topへ」のボタンの横に「編集」ボタンを設置し、それをクリックすると新規作成時と同じような投稿フォームがモーダル で表示されるように実装します。

front/pages/posts/_id.vue

...省略

    Topへ
  </b-button>
  <b-button
    size="sm"
    variant="success"
    @click="openModal()"
  >
    編集
  </b-button>
</b-card>

<b-modal
  hide-header
  hide-footer
  id="edit-modal"
>
  <b-form-textarea
    v-model="content"
  >
  </b-form-textarea>
  <b-button
    class="mt-3"
    variant="primary"
    :disabled="disabled"
    @click="update()"
  >
    更新
  </b-button>
</b-modal>


<script>
export default {
  data: () => {
    return {
      content: '',
      post: {},
    }
  },
  methods: {
    ...省略
    openModal() {
      this.content = this.post.content
      this.$bvModal.show('edit-modal')
    },

modalの使い方はこちら

https://bootstrap-vue.org/docs/components/modal#modals

これで編集ボタンをクリックするとモーダル が開きtextareaにcontentのデータが入っていると思います。

axios通信: 送信(Nuxt)

次は「更新」ボタンをクリックした時にrailsのupdateメソッドが実行されるように実装していきます。

front/pages/posts/_id.vue

...省略
  computed: {
    params() {
      return {
        post: {
          content: this.content
        }
      }
    },
  }

  methods: {
    update() {
      const url = `/api/v1/posts/${this.$route.params.id}`
      this.$axios.put(url, this.params)
        .then((res) => {
          // 成功時の処理
        })
        .catch((err) => {
          // 失敗時の処理
        })
    },

これで更新ボタンを押した時にaxios通信でRails側のupdateアクションを実行するようになりました。次はRails側のupdateアクションを実装していきます。

updateアクション実装(Rails)

前回実装したcreateアクションと同様にupdateアクションを実装していきます。

流れは

  • ルーティングの生成
  • コントローラのupdateアクション実装

です。

  • ルーティングの生成
api/config/routes.rb

Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :hello, only: [:index]
      resources :posts, only: [:index, :create, :show, :update]
    end
  end
end
  • コントローラのupdateアクション実装
api/app/controllers/api/v1/posts_controller.rb

def update
  post = Post.find_by(id: params[:id])
  if post.update(content: params[:post][:content])
    render json: '更新に成功しました', status: 200
  else
    render json: '更新に失敗しました', status: 500
  end
end

これでRails側の実装は完了しました。次はNuxt側のレスポンスを実装します。

axios通信: レスポンス(Nuxt)

thenとcatchのなかの処理を加えていきます。

front/pages/posts/_id.vue

    update() {
      const url = `/api/v1/posts/${this.$route.params.id}`
      this.$axios.put(url, this.params)
        .then((res) => {
          // 成功時の処理
          this.$bvModal.hide('edit-modal')
          this.fetchContent()
          this.$bvToast.toast(res.data, {
            title: '成功',
            variant: 'success'
          })
        })
        .catch((err) => {
          // 失敗時の処理
          const message = err.response.data
          this.$bvToast.toast(message, {
            title: 'エラー',
            variant: 'danger'
          })
        })
    },

これでコンテンツの編集機能が実装できました。

削除ボタン実装(Nuxt)

最後に削除機能を実装していきます。

手順は更新と同じように実装します。

front/pages/posts/_id.vue

...省略

        編集
      </b-button>

      <b-button
        v-b-modal.confirm-delete
        size="sm"
        variant="danger"
      >
        削除
      </b-button>

...省略

    <b-modal
      id="confirm-delete"
      hide-header
      @ok="destroy()"
    >
      <p>投稿を削除しますか?</p>
    </b-modal>
  </div>
</template>

これで編集の横に削除ボタンが表示されクリックすると削除確認のモーダル が表示されます。

axios通信: 送信(Nuxt)

次は削除モーダル を押した時にdestroyアクションが実行されるように実装していきます。

front/pages/posts/_id.vue

<script>
export default {
...省略

  methods: {
    ... 省略

    destroy() {
      const url = `/api/v1/posts/${this.$route.params.id}`
      this.$axios.delete(url)
        .then(() => {
          this.toTop()
        })
        .catch((err) => {
          const message = err.response.data
          this.$bvToast.toast(message, {
            title: 'エラー',
            variant: 'danger'
          })
        })
    }
  }
}

これで削除に成功したらトップページに戻ルようになりました。

最後にRails側のdestroyアクションを実装します。

destroyアクション実装(Rails)

これまでと同じように

  • ルーティング生成
  • destroyアクション実装

の手順で進めます。

  • ルーティング生成
api/config/routes.rb

Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :hello, only: [:index]
      resources :posts, only: [:index, :create, :show, :update, :destroy]
    end
  end
end
  • destroyアクション実装
api/app/controllers/api/v1/posts_controller.rb

module Api
  module V1
    class PostsController < ApplicationController
      ...省略
      def destroy
        post = Post.find(params[:id])
        if post.destroy
          render json: '削除に成功しました', status: 200
        else
          render json: '削除に失敗しました', status: 500
        end
      end
    end
  end
end

これでNuxtとRailsで単一モデルのCRUDを作成することができました。

プログラミングカテゴリの最新記事