質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.00%

Ajaxを使い非同期で画像投稿を行いたい(ActiveStorage,rails-ujs)

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 316

widget11

score 173

Rails5.2.1
rails-ujs
jQuery-ujs

行いたい事としては掲示板でコメントを投稿した時にコメントを非同期で投稿すると共に
コメントしたユーザーの名前と画像も載せたいということです。
現状ユーザーの名前とコメントは反映できているのですが、ActiveStorageを用いて保存している画像を
サーバー側で引っ張ってきて非同期で投稿する方法が分からないということです。

#コントローラー
class CommentsController < ApplicationController
  def create
     @comment = Comment.new(params_comment)
     #①
     @comment.save!
   #②
     ajax_post = Comment.joins(:account).select('name, comment')
     .where(work_id: 8, account_id: 1).last
     render :json => ajax_post
  end

 def params_comment
     params.require(:t_workcomment).permit(:work_id, :account_id, :comment)
 end

end
//Javascript
function set_ajax() {
    {
      $('#ajax_sample').on('ajax:success', function(event) {
        data = event.detail[0];
        $('#t_workcomment_comment').val('');
        $(data).each(function(i, obj){ 
      //④
          $('#comments').append('<li>' + obj.name + obj.comment  + '</li>') 
        });
      });

      $('#ajax_sample').on('ajax:error', function(event) {
        alert("失敗!");
      });
    }
  }

    $(document).on('turbolinks:load', set_ajax);

行っている事は
①コントローラー側に送られたコメントを保存
②保存が成功したらコメントモデルに対して、アカウント(ユーザー)モデルをjoinし、whereメソッドでユーザーが投稿した一番新しい
投稿を絞り込み、selectでコメントとそのユーザーの名前を取得
③絞り込んだ内容をjsonにしてjs側に渡す
④変数dataにサーバー側から渡されたコメント、名前があるのでappendメソッドでhtmlに要素として付け加える
というものです。

しかしActiveStorageを用いてアカウントモデルにアタッチしている画像をどのように持ってきたらいいかが分かりません。
普通にrailsでActiveStorageを用いる場合は

class Account < ApplicationRecord
  has_one_attached :image
end


のようにすれば特に何もしなくても
@account = Account.find(params[:id])
@accountの中にActiveStorageを用いて保存した画像が入っていると思います。
しかしjsと組みあわせると途端に勝手が分からないです。

まず②の部分でaccountモデルをjoinした際にActiveStorageオブジェクトも入ってきているのかが分からないのと
またjs,jquery側でどう扱えばよいかが分かりません。

#imageを取ってこれていないみたいです
 Comment.joins(:account).select('name, comment, image')
     .where(work_id: 8, account_id: 1).last
//detail[0]の中に画像は入ってくるのか
data = event.detail[0];
//どのようにしてappendすればよいか
$('#comments').append('<li>' + obj.name + obj.comment  + '</li>') 

説明不足の点が多々あると思いますが、よろしくお願い致します。

追記 schema.rb

ActiveRecord::Schema.define(version: 2019_04_25_165918) do

    create_table "active_storage_attachments", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
      t.string "name", null: false
      t.string "record_type", null: false
      t.bigint "record_id", null: false
      t.bigint "blob_id", null: false
      t.datetime "created_at", null: false
      t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
      t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
    end

    create_table "active_storage_blobs", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
      t.string "key", null: false
      t.string "filename", null: false
      t.string "content_type"
      t.text "metadata"
      t.bigint "byte_size", null: false
      t.string "checksum", null: false
      t.datetime "created_at", null: false
      t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
    end

    create_table "accounts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
      t.string "email", default: "", null: false
      t.string "encrypted_password", default: "", null: false
      t.string "reset_password_token"
      t.datetime "reset_password_sent_at"
      t.datetime "remember_created_at"
      t.string "confirmation_token"
      t.datetime "confirmed_at"
      t.datetime "confirmation_sent_at"
      t.string "unconfirmed_email"
      t.datetime "created_at", null: false
      t.datetime "updated_at", null: false
      t.string "name"
      t.integer "postaclcode"
      t.text "address"
      t.string "handlename"
      t.text "profile"
      t.bigint "m_rank_id"
      t.boolean "delflg"
      t.index ["email"], name: "index_accounts_on_email", unique: true
      t.index ["m_rank_id"], name: "index_accounts_on_m_rank_id"
      t.index ["reset_password_token"], name: "index_accounts_on_reset_password_token", unique: true
    end

    create_table "comments", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
      t.bigint "work_id"
      t.bigint "account_id"
      t.text "comment"
      t.boolean "delflg"
      t.datetime "created_at", null: false
      t.datetime "updated_at", null: false
      t.index ["account_id"], name: "index_comments_on_account_id"
      t.index ["work_id"], name: "index_comments_on_work_id"
    end


    add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
    add_foreign_key "comments", "accounts"
    add_foreign_key "comments", "works"
  end
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 8zca

    2019/08/25 10:33

    CommentとAccountの関連付けはされているでしょうか?
    https://railsguides.jp/association_basics.html

    キャンセル

  • widget11

    2019/08/26 10:26

    ご返信ありがとうございます。
    コメントモデルとアカウントモデルの関連付けはされております。
    コメントに belongs_to:account
    アカウントに has_many:comments
    といった具合です。

    キャンセル

  • 8zca

    2019/08/27 23:21

    ありがとうございます。
    一応scheme.rbも追記していただいてよろしいでしょうか?

    キャンセル

  • widget11

    2019/08/29 15:03 編集

    ご返信ありがとうございます。
    schemaを全て書いていると非常に冗長になる為、関連しているところをピックアップし追記しました。
    お手数をおかけしますがご確認よろしくお願い致します。

    キャンセル

回答 1

checkベストアンサー

+1

②の部分ですが、

c = Comment.joins(:account).where(work_id: 8, account_id: 1).last


でとってあげたあとにAPIでレスポンスする内容を整形してあげるとよいんじゃないでしょうか。
コメントは c.comment で、アカウント名は c.accout.name でとれます。
同様に画像も c.account.image でとれます。
ただ、c.account.imageはActiveStorage::Attachedのオブジェクトのため、APIでそのまま返してもJS側で画像を表示できるわけではありません。

公式ドキュメントに画像のURLに変換するメソッドがあるようですので、url_forを使ってURLを生成してクライアントに返却、JSの④でimgタグを作成してAPIで受け取ったURLを設定してあげればいけそうですね。
https://railsguides.jp/active_storage_overview.html

※url_forは5分の期限付きURLになるので、長時間表示する場合はconfigで上書きできるようです。
https://stackoverflow.com/questions/52571555/how-do-you-change-the-active-storage-service-url-expires-in-timeout

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/03 13:05

    ありがとうございます!
    url_forという便利メソッドがあったんですね!
    重ねてですがありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.00%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる