0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

我々はCoffeeScriptを書く時にもRailsの実行を使いたかったんだよ

Posted at

app/assets/javascripts/foo.js.coffee で Rails の変数を使いたい

諸般の事情から、スクリプトを使って <img> タグの src を特定の条件下でアプリケーション側のアセットに置き換えたい、という事があったんですよ。

大雑把に書くと、つまりこういうのですね。

# app/assets/javascripts/foo.js.coffee
# 今時 jQuery なんて使ってんのかよ、と言われるとまぁ…
$ ->
  $('img.portrait').on 'error', ->
    $(this).attr 'src', '/assets/portrait/no-image.png'

ただ、Railsのアセットって最終的にはフィンガープリント付与される関係で、これだとアセットプリコンパイルされる環境ではそのままだと参照出来ないわけで、Railsの asset_path ヘルパーなりを利用して実際に有効なパスを書かないといけないわけです。

でも、CoffeeScriptって、Railsの変数とか実行結果をそのまま置けないじゃないですか。多分。
※色々調べた結果「ない」と結論付けていますが、実際には全然あるかもしれません

# つまり、こういうのが書きたい
$(this).attr 'src', "#{asset_path('portrait/no-image.png')}"

# けどこれコンパイル結果はこうなるから、全然期待通りじゃないじゃん
#=> $(this).attr('src', `${asset_path('portrait/no-image.png')}`);

なので、Railsの方の実行を踏まえたJavaScriptアセットを記述する時にはCoffeeScriptは使えません。故に、Railsの実行が使えるERBを採用し、結果こうなります。

<%# app/assets/javascripts/foo.js.erb %>
$(function(){
  $('img.portrait').on('error', function(){
    $(this).attr('src', '<%= asset_path("portrait/no-image.png") %>');
  });
});

……ほんの些末な一節を書く、たったそれだけのために。
それだけのために、CoffeeScriptのいい感じの記述が使えない。この世は間違ってる。

じゃあERBも併せて使えばよかったんだよ!

アセットパイプラインの動作って、拡張子を連結させてたら末端から順に処理してくれるらしいじゃないですか。
もしかしたら全然常識の範囲なのかもしれないですが。どうして誰も教えてくれなかったんだ!
「聞かれなかったからさ」

ということで、ERBで当該のパス出力部分だけを実行させた後、改めてCoffeeScriptで評価すると、いい感じに期待結果が得られるというわけです。

# app/assets/javascripts/foo.js.coffee.erb
$ ->
  $('img.portrait').on 'error', ->
    # 本命の portrait/no-image.png の期待通りのパスが文字列として設定される:うれしい
    $(this).attr 'src', '<%= asset_path("portrait/no-image.png") %>'

余談: Slimテンプレートでもやりたいんだけど

まぁSlimテンプレート内で coffee: 文脈からRailsの実行を引用したい場合は知りません。そっちは取り敢えず javascript: 文脈で変数に突っ込むとかで対応するでもいいんじゃないですかね……。

// テンプレートの描画側でスクリプト仕込む系実装
javascript:
  // 最近は let とか使うんだっけ? JavaScriptにわか勢だからあんま詳しくない
  var noImagePath = "#{asset_path('portrait/no-image.png')}";

coffee:
  $ ->
    $('img.portrait').on 'error', ->
      $(this).attr 'src', noImagePath

参考

参考っていうか、なんならRailsガイドにほぼダイレクトに書かれてましたわ!
Railsガイド v6.1 アセットパイプライン #2.3.3 JavaScript/CoffeeScriptとERB

結論:ドキュメントはちゃんと隅々まで読み込みましょう

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?