回答編集履歴
3
解説をさらに補足
test
CHANGED
@@ -52,13 +52,13 @@
|
|
52
52
|
|
53
53
|
よくある使い方はRails Guideなんかに書いてあるやつですね。
|
54
54
|
|
55
|
-
https://railsguides.jp/active_storage_overview.html#file-io-objects%E3%82%92%E3%82%A2%E3%82%BF%E3%83%83%E3%83%81%E3%81%99%E3%82%8B
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
例えばすでに保存済みのUserモデルのインスタンス、@userに対して @user.image.attach みたいな使い方を行えます。
|
60
|
-
|
61
|
-
実際に試した2個目のやり方はこれをやろうとしたんだと思いますが、Drinkモデルのimageは必須になっており、後から画像だけ追加というやり方は今回は使えません。
|
55
|
+
[https://railsguides.jp/active_storage_overview.html#file-io-objects%E3%82%92%E3%82%A2%E3%82%BF%E3%83%83%E3%83%81%E3%81%99%E3%82%8B](https://railsguides.jp/active_storage_overview.html#file-io-objects%E3%82%92%E3%82%A2%E3%82%BF%E3%83%83%E3%83%81%E3%81%99%E3%82%8B)
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
例えばすでに保存済みの User モデルのインスタンス、@user に対して @user.image.attach みたいな使い方を行えます。
|
60
|
+
|
61
|
+
実際に試した2個目のやり方はこれをやろうとしたんだと思いますが、Drink モデルの image は必須になっており、後から画像だけ追加というやり方は今回は使えません。
|
62
62
|
|
63
63
|
|
64
64
|
|
@@ -70,9 +70,9 @@
|
|
70
70
|
|
71
71
|
|
72
72
|
|
73
|
-
ActiveStorageは active_storage_blobs と active_storage_attachments の二つのテーブルで機能を実現しています。
|
73
|
+
ActiveStorageは `active_storage_blobs` と `active_storage_attachments` の二つのテーブルで機能を実現しています。
|
74
|
-
|
74
|
+
|
75
|
-
これはつまり ActiveStorage::Blob と ActiveStorage::Attachment の二つのモデルで構成されていて、今回はその ActiveStorage::Blob を必要としているエラーだと解釈しました。
|
75
|
+
これはつまり `ActiveStorage::Blob` と `ActiveStorage::Attachment` の二つのモデルで構成されていて、今回はその `ActiveStorage::Blob` を必要としているエラーだと解釈しました。
|
76
76
|
|
77
77
|
上の attach メソッドも、中身を見てみると blob を生成しているんですよね。
|
78
78
|
|
@@ -110,13 +110,61 @@
|
|
110
110
|
|
111
111
|
|
112
112
|
|
113
|
-
create_blob_from がその blob を生成している部分。
|
114
|
-
|
115
|
-
この
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
113
|
+
`create_blob_from` がその blob を生成している部分。
|
114
|
+
|
115
|
+
この中身をさらに追ってみると
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
```
|
120
|
+
|
121
|
+
def create_blob_from(attachable)
|
122
|
+
|
123
|
+
case attachable
|
124
|
+
|
125
|
+
when ActiveStorage::Blob
|
126
|
+
|
127
|
+
attachable
|
128
|
+
|
129
|
+
when ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile
|
130
|
+
|
131
|
+
ActiveStorage::Blob.create_after_upload! \
|
132
|
+
|
133
|
+
io: attachable.open,
|
134
|
+
|
135
|
+
filename: attachable.original_filename,
|
136
|
+
|
137
|
+
content_type: attachable.content_type
|
138
|
+
|
139
|
+
when Hash
|
140
|
+
|
141
|
+
ActiveStorage::Blob.create_after_upload!(attachable)
|
142
|
+
|
143
|
+
when String
|
144
|
+
|
145
|
+
ActiveStorage::Blob.find_signed(attachable)
|
146
|
+
|
147
|
+
else
|
148
|
+
|
149
|
+
nil
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
```
|
156
|
+
|
157
|
+
こんな感じ。
|
158
|
+
|
159
|
+
|
160
|
+
|
161
|
+
このメソッドは残念ながら private メソッドなのでそのまま呼べないんですが、多分 public メソッドで blob を作成するものがあるだろうなと探したのが [https://edgeapi.rubyonrails.org/classes/ActiveStorage/Blob.html#method-c-create_and_upload-21](https://edgeapi.rubyonrails.org/classes/ActiveStorage/Blob.html#method-c-create_and_upload-21) って訳です。
|
162
|
+
|
163
|
+
上のコード内でも出てきてますね。
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
> Creates a new blob instance and then uploads the contents of the given io to the service. The blob instance is going to be saved before the upload begins to prevent the upload clobbering another due to key collisions. When providing a content type, pass identify: false to bypass automatic content type inference.
|
120
168
|
|
121
169
|
|
122
170
|
|
@@ -124,7 +172,9 @@
|
|
124
172
|
|
125
173
|
|
126
174
|
|
127
|
-
実際にこれを使っている実例を探してみたものの見つけられなかったので、残念ながらサンプル的なものは提供できなかったのですが。
|
175
|
+
実際にこれを使っている実例を探してみたものの見つけられなかったので、残念ながらサンプル的なものは提供できなかったのですが。 `attach` メソッド内部でも使われていることと同じことをやる以上、非常に公式な使い方なのでまあ大丈夫だろうなと思いました。
|
176
|
+
|
177
|
+
|
128
178
|
|
129
179
|
私はそれほど ActiveStorage 使っていないので少々調べるのに時間がかかりましたが、慣れている人ならもっとスムーズに調べられるかもしれません。
|
130
180
|
|
@@ -136,7 +186,7 @@
|
|
136
186
|
|
137
187
|
* 使おうとしている機能やライブラリ(ここでは ActiveStorage)の動作の概要を理解する
|
138
188
|
|
139
|
-
* RailsGuideなどで紹介されている一般的な利用法で呼び出すメソッドが、Railsやgem内部でどう動いているかを調べる
|
189
|
+
* RailsGuideなどで紹介されている一般的な利用法で呼び出すメソッドが、Railsやgem内部でどう動いているかを調べる(この場合は `attach` メソッド)
|
140
190
|
|
141
191
|
|
142
192
|
|
2
解決に至る思考プロセスを解説
test
CHANGED
@@ -37,3 +37,115 @@
|
|
37
37
|
|
38
38
|
|
39
39
|
Rails.root.joinはなくても動く気はしますけれど。
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
--
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
こうすればうまくいくかな?と考えるに至ったプロセスを説明します。
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
よくある使い方はRails Guideなんかに書いてあるやつですね。
|
54
|
+
|
55
|
+
https://railsguides.jp/active_storage_overview.html#file-io-objects%E3%82%92%E3%82%A2%E3%82%BF%E3%83%83%E3%83%81%E3%81%99%E3%82%8B
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
例えばすでに保存済みのUserモデルのインスタンス、@userに対して @user.image.attach みたいな使い方を行えます。
|
60
|
+
|
61
|
+
実際に試した2個目のやり方はこれをやろうとしたんだと思いますが、Drinkモデルのimageは必須になっており、後から画像だけ追加というやり方は今回は使えません。
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
で、 `ArgumentError: Could not find or build blob: expected attachable,` というエラーメッセージです。
|
66
|
+
|
67
|
+
日本語に訳すと「ファイルが見つからないか、またはblobの作成に失敗しました」みたいな感じです。
|
68
|
+
|
69
|
+
なので、blobデータを必要としているように見えます。
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
ActiveStorageは active_storage_blobs と active_storage_attachments の二つのテーブルで機能を実現しています。
|
74
|
+
|
75
|
+
これはつまり ActiveStorage::Blob と ActiveStorage::Attachment の二つのモデルで構成されていて、今回はその ActiveStorage::Blob を必要としているエラーだと解釈しました。
|
76
|
+
|
77
|
+
上の attach メソッドも、中身を見てみると blob を生成しているんですよね。
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
```
|
82
|
+
|
83
|
+
def attach(attachable)
|
84
|
+
|
85
|
+
blob_was = blob if attached?
|
86
|
+
|
87
|
+
blob = create_blob_from(attachable)
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
unless blob == blob_was
|
92
|
+
|
93
|
+
transaction do
|
94
|
+
|
95
|
+
detach
|
96
|
+
|
97
|
+
write_attachment build_attachment(blob: blob)
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
blob_was.purge_later if blob_was && dependent == :purge_later
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
```
|
110
|
+
|
111
|
+
|
112
|
+
|
113
|
+
create_blob_from がその blob を生成している部分。
|
114
|
+
|
115
|
+
このメソッドは残念ながら private メソッドなのでそのまま呼べないんですが、多分 public メソッドで blob を作成するものがあるだろうなと探したのが https://edgeapi.rubyonrails.org/classes/ActiveStorage/Blob.html#method-c-create_and_upload-21 って訳です。
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
>Creates a new blob instance and then uploads the contents of the given io to the service. The blob instance is going to be saved before the upload begins to prevent the upload clobbering another due to key collisions. When providing a content type, pass identify: false to bypass automatic content type inference.
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
って説明を読む限りもそういう目的で使う感じですしね。
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
実際にこれを使っている実例を探してみたものの見つけられなかったので、残念ながらサンプル的なものは提供できなかったのですが。
|
128
|
+
|
129
|
+
私はそれほど ActiveStorage 使っていないので少々調べるのに時間がかかりましたが、慣れている人ならもっとスムーズに調べられるかもしれません。
|
130
|
+
|
131
|
+
コツとしては
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
* エラーメッセージを読む(言語やフレームワークがうまくいかない理由を教えてくれているので、一番のヒント)
|
136
|
+
|
137
|
+
* 使おうとしている機能やライブラリ(ここでは ActiveStorage)の動作の概要を理解する
|
138
|
+
|
139
|
+
* RailsGuideなどで紹介されている一般的な利用法で呼び出すメソッドが、Railsやgem内部でどう動いているかを調べる
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
というところかなと思います。
|
144
|
+
|
145
|
+
でも、これを解決できるのは個人的な感覚では中級者以上で、ちょっと難しいかな、という気はします。
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
実際にはそこまで調べずに解決できないかなーと、seed 側でこの手の問題を解決した情報がないかとか探してみたんですが、まあたいていはあとから attach する RailsGuide のパターンでやっている例ばかりでした。
|
150
|
+
|
151
|
+
そのものズバリの例をどこかで見つけられると上の三つのステップなんていらないんですが、まあそういつも楽できるとは限りません。
|
1
回答の間違いを修正
test
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
一番最初のパターンで、
|
1
|
+
~~一番最初のパターンで、~~
|
2
2
|
|
3
3
|
|
4
4
|
|
@@ -10,4 +10,30 @@
|
|
10
10
|
|
11
11
|
|
12
12
|
|
13
|
-
とやってもうまくいかないでしょうか。
|
13
|
+
~~とやってもうまくいかないでしょうか。
|
14
|
+
|
15
|
+
~~
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
完全に読み違えていました。
|
20
|
+
|
21
|
+
Drinkのimageが必須になっているのでこれが任意にできるのなら簡単なんですけれど。
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
手元で試せないのでうまくいくか未確認ですが、[ActiveStorage::Blob.create_and_upload! ](https://edgeapi.rubyonrails.org/classes/ActiveStorage/Blob.html#method-c-create_and_upload-21)を使ってみるとどうなるでしょうか。
|
26
|
+
|
27
|
+
最初のパターンでこう書きます。
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
```
|
32
|
+
|
33
|
+
iamge: ActiveStorage::Blob.create_and_upload!(io: File.open(Rails.root.join("app/assets/images/houseblend.jpeg"))
|
34
|
+
|
35
|
+
```
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
Rails.root.joinはなくても動く気はしますけれど。
|