railsからjsonデータをVue.jsの方に受け渡すことができたが、画像のデータがうまいことVue.jsのほうに渡っていないきがするのですね。
app/javascript/app.vue
のほうに{{dirnk.image}}
とやると、
"name": "image", "record": { "id": 10, "name": "ddd", "price": 3000, "explain": "dddddd", "user_id": 7, "created_at": "2021-08-06T06:50:21.611Z", "updated_at": "2021-08-06T06:50:21.649Z", "region_id": 1, "body_id": 1, "acidity_id": 1, "processing_id": 1, "likes_count": null } }
このようなjsonデータがviewに表示される。
考えられる原因第1
users_controller.rb
class Api::UsersController < ApplicationController
def show
@user = User.find(params[:id])
@drinks = @user.drinks.order('created_at DESC').includes(image_attachment: :blob)
end
end
drinksの方はあくまでユーザークラスのインスタンスなので、drink.image
とやってもうまくいかない説がある。
考えられる原因第2
.erbで<%= image_tag @drink.image%>
とやるように、
vueのほうにも画像を表示させるメソッドがあるかも
考えられる原因第3
画像データをvueの方に渡すときに、jsonの特別な書き方がある。
https://qiita.com/youichiro/items/2987cd9b4ab29691eb77
このきじを参考に色々みていきたい
考えられる原因第4
俺にはまだ早い説
だとしたら、画像はrailsのactive storageに処理を任せて、
テキスト情報だけは vueの方で書くしかない。。。
考えられる原因第1
にまずはアプローチ。そもそもrailsのほうでは、@drink.imageとやって上手く言ってるのか確かめていきます
views/users/show.html.erb
<% @drinks.each do |drink| %>
<%= image_tag drink.image%>
<% end %>
にこんな感じでやればうまくいきました。
drink.imageでやればうまくいくので、
jsonで上手く画像データをvueに受け渡せているなら、vueの方でもimage_tag的な画像を表示させるメソッドを使えばdrink.imageでも上手くいきそうですね。
ちなみにvueのほうには、
app/views/api/users/show.json.jbuilder
json.array! @drinks, :id ,:name , :price , :explain ,
:image , :region_id , :body_id ,
:acidity_id , :processing_id ,
:likes_count , :user_id
こんな感じでデータをvueに受け渡しています。
drink.nameとかではしっかりとvueのほうに表示させれるので、問題ないでしょう。
このような書き方でvueに画像データを受け渡せているか微妙なのですが、一旦受けわたせている前提で、
考えて、vueの方でrailsのimage_tag的なメソッドを探すってことで
考えられる原因第2
rails vue 画像データ jsonでしらべたらどうやら、
json.array! @drinks, :id ,:name , :price , :explain ,
:image , :region_id , :body_id ,
:acidity_id , :processing_id ,
:likes_count , :user_id
こういった形式では、画像データを送れないっぽいので、そもそも画像データをvueに渡せてない。
ってことでこの線は一旦消える。
受け渡せることができたら、またこの原因に戻ろう。
考えられる原因第3
ってことでrailsの画像データをvueの方に受け渡す処理をかいていこうとおもいます。
https://qiita.com/terufumi1122/items/bdc96617c818dac01b6d
https://qiita.com/ozin/items/5ec81a4b126b8ebf7a96
https://qiita.com/tabakazu/items/5489632c534c56db6a4d
https://qiita.com/youichiro/items/2987cd9b4ab29691eb77
色々ヒットしたので
これかの記事を参考にして頑張る
まずは、https://qiita.com/youichiro/items/2987cd9b4ab29691eb77
これから
微妙に自分がやりたい形式でなかった。jbuilderを使わずやっていたので、自分の理解では飲み込めなかった。
次は、https://qiita.com/terufumi1122/items/bdc96617c818dac01b6d
この方の記事。
まさしく自分がやりたいことがタイトルになっているので、なんかいけそう
その前に、https://qiita.com/tabakazu/items/5489632c534c56db6a4d
こっちを済ませとく必要がある。今さっきやろうとしてた記事にeyecatchメソッドがあって、それを先に定義していかなければならない。。。。
def image=(image)
if image.present?
prefix = image[/(image|application)(\/.*)(?=\;)/]
type = prefix.sub(/(image|application)(\/)/, '')
data = Base64.decode64(image.sub(/data:#{prefix};base64,/, ''))
filename = "#{Time.zone.now.strftime('%Y%m%d%H%M%S%L')}.#{type}"
File.open("#{Rails.root}/tmp/#{filename}", 'wb') do |f|
f.write(data)
end
image.detach if image.attached?
image.attach(io: File.open("#{Rails.root}/tmp/#{filename}"), filename: filename)
FileUtils.rm("#{Rails.root}/tmp/#{filename}")
end
end
うん、意味がわからんので、頑張って一つずつ解説します。
まず、image=(image)、このメソッドの定義の仕方。。。
どっかで見たことあるけど、image(image)との違いがよくわからんくなった。
https://donghai821.hatenadiary.org/entry/20080406/1207479842
def hoge=(fuga)は書き込みオンリーらしい。
このようなメソッドを「要素代入関数」と言うらしい。へぇーー。
https://wa3.i-3-i.info/diff397data.html
エンコードとデコードの違いはこれ。
なぜbase64をつかうの??
かつての電子メールを送るためのプロトコルSMTPでは、ASCIIといわれる7bitで表現される英数字しか送ることができませんでした
したがって、メールを使って画像や音声などのデータをやりとりしたいと思った時に、英数字しか対応していないSMTPでは、それらのデータを送受信することができませんでした
そこで、すべてのデータを英数字で表すMIME(Multipurpose Internet Mail Extensions)という規格が登場し、その中でbase64というデータの変換方法が定められました
これによって、受信側と送信側がMIMEに則ってエンコード・デコードをすることで、メールを通して画像や音声などの送受信が可能になりました
現在では、JSONなどで特殊文字を含まないように画像データをbase64でエンコードしたり、Webページの表示の際にリクエスト数を減らすためにbase64でエンコードした画像をhtmlにそのまま埋め込むなどの用途で用いられています
そこで、たしかに画像データを文字列に置き換えて送受信をしたいから、画像をエンコードする必要があるのかもね。
# Base64形式でうけとったimageデータをエンコードし、
# 一時的にtmp配下に画像ファイルを作成、作成した画像ファイルをアタッチ
# その後画像ファイルを削除
def image=(image)
if image.present?
# もし、imageがあったら?
prefix = image[/(image|application)(\/.*)(?=\;)/]
# ???
type = prefix.sub(/(image|application)(\/)/, '')
# この正規表現にマッチしたものを空文字にする
data = Base64.decode64(image.sub(/data:#{prefix};base64,/, ''))
# 画像のデータをこの文字列にマッチしたものは、空にして,
# 残った文字列をデコード
filename = "#{Time.zone.now.strftime('%Y%m%d%H%M%S%L')}.#{type}"
# 画像のファイルネームを定義
File.open("#{Rails.root}/tmp/#{filename}", 'wb') do |f|
f.write(data)
# ファイルにデータを書き込み
end
image.detach if image.attached?
image.attach(io: File.open("#{Rails.root}/tmp/#{filename}"), filename: filename)
FileUtils.rm("#{Rails.root}/tmp/#{filename}")
end
end
正直この程度しか分からんかった。
なんでこれらのコードを実行する必要があるのかがよくわからんかった。。
後でrailsの画像周りの知識をしっかり勉強しよう。
https://railsguides.jp/active_storage_overview.html
ホントはダメだけど、理解しないまま一旦実装してしまおう。
一旦全体の動き把握して、実装してから理解する。
まさに駆け出しって感じですね。。精進します。。。
https://qiita.com/terufumi1122/items/bdc96617c818dac01b6d
この記事には、
def show
post = Post.find(params[:id]).as_json #JSON形式にしておく
eyecatch = post.eyecatch #eyecatchは添付した画像ファイル
if eyecatch.present?
post['image'] = encode_base64(eyecatch) # 画像ファイルを1.で定義したメソッドでBase64エンコードし、renderするデータに追加する
end
render json: post
end
と書いてある。。。
自分の場合は、
def show
@user = User.find(params[:id])
@drinks = @user.drinks.order('created_at DESC').includes(image_attachment: :blob)
end
何がやっかいかと言うと、
こっちは投稿(drink)を複数取得して、配列だから、
配列一つ一つに対して処理をしていかないといけない。。。
eachとか使えるけど、それでうまくいくのだろうか。。。
配列だと扱いが難しいから、まずは画像一枚一枚を非同期的に表示させていく。
つまり、 @drinks = @user.drinks.order('created_at DESC').includes(image_attachment: :blob)
これだと複数枚画像があるけど、
drinks#showだったら、一枚しか画像がないから、それをうまいこと表示させていきたい
ってことで、drinks#showのSPA化を一旦目指す。
配列データのSPA化は一応できたけど、画像の扱いが今は難しかったから、
一旦単一データのSPA化をしてみたいと思う。
ってことでブランチを一旦削除、、、ピエン
画像が入ってる配列データは俺には早かったっていう
考えられる原因第4に当てはまってしまった!リベンジかますで!!!