LoginSignup
1
0

viteとimportmapの競合による期待しないHTTPメソッドの挙動の解消について

Posted at

Rails 7 でのログアウト処理問題とその解決策

Railsアプリケーションで以下のようにログアウトリンクを設定している場合、

<%= link_to 'ログアウト', destroy_user_session_path, data: { turbo_method: :delete } %>

次のエラーに直面することがあります。

ActiveRecord::RecordNotFound at /users/sign_out Couldn't find User with 'id'=sign_out

Rails 6 では以下の方法でログアウトリンクを記述していましたが、

<%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>

Rails 7 からは data: { turbo_method: :delete } を使用する必要があります
※そうしないとGETメソッドで予期しないリンク先に遷移しようとします。
しかし、この方法でもエラーが発生することがあります。この記事では、その原因解明と解決策を探求します。

[補足]簡易な応急策としては以下のものがある

<%= button_to 'ログアウト', destroy_user_session_path, method: :delete %>

※HTTPメソッドの送信方法の不具合や予期しない挙動が解消したわけではないことに注意してください。

根本的な問題

プロジェクトの現状は以下の通りです。

config/importmap.rb
pin "application", preload: true
pin "@hotwired/turbo-rails", to:"turbo.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers", preload: true
app/javascript/application.js
import "@hotwired/turbo-rails"
import "controllers/application"
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    ...
    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= vite_client_tag %>
    <%= vite_javascript_tag "entrypoints/application" %>
    <%= javascript_importmap_tags %>
  </head>
  ...
</html>
app/javascript/entrypoints/application.js
console.log('Vite ⚡️ Rails')
console.log('Visit the guide for more information: ', 'https://vite-ruby.netlify.app/guide/rails')
import 'vue2-animate/dist/vue2-animate.min.css';
import { createApp } from 'vue';
import ExampleComponent from '../components/ExampleComponent.vue';

const app = createApp(ExampleComponent);
app.mount('#app');

この構成において、<%= vite_javascript_tag "entrypoints/application" %> をコメントアウトすることで、importmapviteの競合が解消され、ログアウトが可能になりましたが、Vue.jsViteで管理しているため、このアプローチは適切ではありません。
なお、importmapviteの競合でimportmapの設定が有効にならないのはおそらくimportmapの後でvite(app/javascript/entrypoints/application.js)でVueアプリケーションを初期化されているからと思われます(詳細未調査)。

解決策

解決策として、config/importmap.rbapp/javascript/application.jsを削除し、Viteのみを使用する構成に変更します。

  • application.html.erb の更新

    application.html.erb
    <!DOCTYPE html>
    <html>
      <head>
        ...
        <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
        <%= vite_client_tag %>
        <%= vite_javascript_tag "entrypoints/application" %>
      </head>
      ...
    </html>
    
  • entrypoints/application.js の更新

    entrypoints/application.js
    console.log('Vite ⚡️ Rails')
    console.log('Visit the guide for more information: ', 'https://vite-ruby.netlify.app/guide/rails')
    import "@hotwired/turbo-rails"
    import "@hotwired/stimulus"
    import "@hotwired/stimulus-loading"
    import "../controllers/application"
    
    import 'vue2-animate/dist/vue2-animate.min.css';
    import { createApp } from 'vue';
    import ExampleComponent from '../components/ExampleComponent.vue';
    
    const app = createApp(ExampleComponent);
    app.mount('#app');
    

これにより、Viteを使用しつつ、@hotwired/turbo-rails と Stimulus を適切にインポートし、Rails 7のアプリケーションで問題なく動作するようになります。

1
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
1
0