はじめに
「なんで vendor/ 配下に、読み込むべき画像を置くんだよ」という意見、大変ごもっともだと思いますし私もそう思いますが、特例としてお読み下さい……
環境
Railsは5.1.1Rubyは2.4.1
vendor/配下の画像ファイルが読み込まれない
例えば、vendor/assets/images/cat.jpgというようにファイルが配置されていたとします。このとき、以下のようなerbを書いてcat.jpgを表示させようとするとAssetNotPrecompiledエラーになります。どうすべきか。
<%= image_tag 'cat.jpg' %>
結論
以下の二つの内容を書き加える。書き加えたあとはサーバの再起動が必要になる。
1. assetsパスを通す
config/initializers/assets.rbに以下の行を書き加える。
Rails.application.config.assets.paths << Rails.root.join('vendor')
2. プリコンパイルの対象にする
config/initializers/assets.rb(「1.」と同じファイル)に以下の行を書き加える*1。
Rails.application.config.assets.precompile += %w( *.eot *.woff *.ttf *.svg *.otf *.png *.jpg *.jpeg *.gif )
理由(なぜ上記の方法でよいか)
Rails 5 から*2、vendor/が以下のような位置付けになりました。
vendor/配下はデフォルトで assetsパス に含まれないvendor/配下の画像ファイルはデフォルトでプリコンパイルの対象に含まれない
したがって、先ほどの二つの内容を書き加える必要がありました。
補足
assetsパス の確認方法
現在の assets パスを確認するには、Rails のコンソールに入ってからRails.application.config.assets.pathsを入力することで確認できます。
$ rails console Loading development environment (Rails 5.1.1) irb(main):001:0> Rails.application.config.assets.paths => ここに assetsパス が表示される
追加されたプリコンパイルの対象の確認方法
デフォルトのプリコンパイルの対象*3以外に、どんなファイルがプリコンパイルの対象として追加されているかを確認するためには、Rails コンソールでRails.application.config.assets.precompileと叩けばよいです。
$ rails console Loading development environment (Rails 5.1.1) irb(main):001:0> Rails.application.config.assets.precompile => ここに追加のプリコンパイルの対象が表示される
config/initializers/assets.rbを変更したあとは要サーバ再起動
config/initializers/assets.rbの内容を変更した場合、サーバを再起動しないとその内容は反映されません。
どのディレクトリ配下を assetsパス とするか
上記の「1.」の設定ではjoinメソッドの引数にvendorを指定しています。これによりvendor/配下のディレクトリが assetsパス になるのですが、vendor/配下は全て assetsパス となります。
assetsパス の対象を制限したい場合はもっとディレクトリを掘って指定した方がいいでしょう。
プリコンパイルの対象ファイルについて
上記の「2.」の設定では、プリコンパイルの追加の対象となるのは書かれている拡張子のファイルになります。ここを書き換えることで対象を広くあるいは狭くできるので、必要に応じて書き換えればいいでしょう。
そもそもvendor/を使う意味は……
追加する assets は、特に理由がない限りはapp/assets/配下に置けばいいんじゃないでしょうか。
画像ファイルだけならまだしも、JavaScript のファイルやスタイルシートをvendor/配下に置く場合は、プリコンパイルの対象に追加するのが面倒です*4。
app/assetsの中にうまい具合に階層構造を作ってやりくりするのが Rails っぽくて良いし、何より楽なのではないでしょうか。
参考(感謝!)
実は以下の記事にほぼ全て書いてあります。