<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Junichi Ito</title>
    <description>The latest articles on DEV Community by Junichi Ito (@jnchito).</description>
    <link>https://dev.to/jnchito</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F108081%2F0518c1e4-9e8f-4cb1-82fe-a8ae27d1fe91.jpg</url>
      <title>DEV Community: Junichi Ito</title>
      <link>https://dev.to/jnchito</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jnchito"/>
    <language>en</language>
    <item>
      <title>[DON'T READ] How to customize Devise for Rails 7.0 and Turbo</title>
      <dc:creator>Junichi Ito</dc:creator>
      <pubDate>Wed, 04 Jan 2023 13:06:50 +0000</pubDate>
      <link>https://dev.to/jnchito/how-to-customize-devise-for-rails-70-and-turbo-ih</link>
      <guid>https://dev.to/jnchito/how-to-customize-devise-for-rails-70-and-turbo-ih</guid>
      <description>&lt;p&gt;🔔 NOTE: &lt;a href="https://github.com/heartcombo/devise/releases/tag/v4.9.0" rel="noopener noreferrer"&gt;Devise 4.9.0 has been released&lt;/a&gt;. Please consider upgrading Devise instead of reading this post.  &lt;/p&gt;




&lt;p&gt;As of Devise 4.8.1, they say "&lt;a href="https://github.com/heartcombo/devise/blob/main/CHANGELOG.md#481---2021-12-16" rel="noopener noreferrer"&gt;Turbo integration is not fully supported by Devise yet.&lt;/a&gt;" So you need to customize Devise settings for it. This post describes how to do it.&lt;/p&gt;

&lt;p&gt;I tested against the following environments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ruby on Rails 7.0.4&lt;/li&gt;
&lt;li&gt;Devise 4.8.1&lt;/li&gt;
&lt;li&gt;turbo-rails 1.3.2&lt;/li&gt;
&lt;li&gt;Ruby 3.2.0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And my post is a little modified from these articles (They helped me a lot!):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gorails.com/episodes/devise-hotwire-turbo" rel="noopener noreferrer"&gt;https://gorails.com/episodes/devise-hotwire-turbo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://gorails.com/forum/how-to-use-devise-with-hotwire-turbo-js-discussion#forum_post_17983" rel="noopener noreferrer"&gt;https://gorails.com/forum/how-to-use-devise-with-hotwire-turbo-js-discussion#forum_post_17983&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can refer them to understand technical details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preconditions
&lt;/h2&gt;

&lt;p&gt;You already install Devise to your Rails app according to &lt;a href="https://github.com/heartcombo/devise/tree/v4.8.1" rel="noopener noreferrer"&gt;Devise's README&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to customize
&lt;/h2&gt;

&lt;p&gt;Add the following code to &lt;code&gt;app/controllers/turbo_devise_controller.rb&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TurboDeviseController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Responder&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Responder&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_turbo_stream&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@default_response&lt;/span&gt;
        &lt;span class="vi"&gt;@default_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;formats: :html&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;formats: :html&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;ActionView&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MissingTemplate&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;get?&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
      &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;has_errors?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;default_action&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;respond_to?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:error_rendering_options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="c1"&gt;# For responders 3.1.0 or higher&lt;/span&gt;
          &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="n"&gt;error_rendering_options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;formats: :html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :unprocessable_entity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="n"&gt;rendering_options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;formats: :html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :unprocessable_entity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="n"&gt;navigation_behavior&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;responder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Responder&lt;/span&gt;
  &lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="ss"&gt;:html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:turbo_stream&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then, open &lt;code&gt;config/initializers/devise.rb&lt;/code&gt; and define TurboFailureApp class:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TurboFailureApp&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Devise&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;FailureApp&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;respond&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request_format&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:turbo_stream&lt;/span&gt;
      &lt;span class="n"&gt;redirect&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="k"&gt;super&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="n"&gt;skip_format?&lt;/span&gt; &lt;span class="n"&gt;is_navigational_format?&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Assuming you have not yet modified this file, each configuration option below&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Plus, apply the following change to &lt;code&gt;config/initializers/devise.rb&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="gd"&gt;-  # config.parent_controller = 'DeviseController'
&lt;/span&gt;&lt;span class="gi"&gt;+  config.parent_controller = 'TurboDeviseController'
&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="gd"&gt;-  # config.navigational_formats = ['*/*', :html]
&lt;/span&gt;&lt;span class="gi"&gt;+  config.navigational_formats = ['*/*', :html, :turbo_stream]
&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="gd"&gt;-  # config.warden do |manager|
-  #   manager.intercept_401 = false
-  #   manager.default_strategies(scope: :user).unshift :some_external_strategy
-  # end
&lt;/span&gt;&lt;span class="gi"&gt;+  config.warden do |manager|
+    manager.failure_app = TurboFailureApp
+  end
&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Your sign-out link needs to replace &lt;code&gt;method: :delete&lt;/code&gt; to &lt;code&gt;data: { turbo_method: :delete }&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="gd"&gt;-&amp;lt;%= link_to 'Sign out', destroy_user_session_path, method: :delete %&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+&amp;lt;%= link_to 'Sign out', destroy_user_session_path, data: { turbo_method: :delete } %&amp;gt;
&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you have "Cancel my account" button in &lt;code&gt;app/views/devise/registrations/edit.html.erb&lt;/code&gt;, you need to use &lt;code&gt;turbo_confirm&lt;/code&gt; instead of &lt;code&gt;confirm&lt;/code&gt; to pop-up confirmation dialog. Please run &lt;code&gt;rails generate devise:views&lt;/code&gt; to generate customizable Devise views:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="gd"&gt;-&amp;lt;%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+&amp;lt;%= button_to "Cancel my account", registration_path(resource_name), data: { turbo_confirm: "Are you sure?" }, method: :delete %&amp;gt;
&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That's all! Now you are ready to use Devise with Rails 7.0 and Turbo!&lt;/p&gt;

&lt;p&gt;You can download and run my codes from here:&lt;br&gt;
&lt;a href="https://github.com/JunichiIto/devise-rails-7-sandbox" rel="noopener noreferrer"&gt;https://github.com/JunichiIto/devise-rails-7-sandbox&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmm4jtd7ja964yg74nexg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmm4jtd7ja964yg74nexg.png" alt="Sign in"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3l3zinn7rsxbi7p04wkv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3l3zinn7rsxbi7p04wkv.png" alt="Signed in"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fud4j0u518i3gchy730mr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fud4j0u518i3gchy730mr.png" alt="Signed out"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing them
&lt;/h2&gt;

&lt;p&gt;Here are my codes to test Devise's behavior.&lt;/p&gt;

&lt;p&gt;You can see whole codes here:&lt;br&gt;
&lt;a href="https://github.com/JunichiIto/devise-rails-7-sandbox/tree/main/test/system" rel="noopener noreferrer"&gt;https://github.com/JunichiIto/devise-rails-7-sandbox/tree/main/test/system&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Sign up
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'application_system_test_case'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SignUpTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationSystemTestCase&lt;/span&gt;
  &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s1"&gt;'sign up'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;visit&lt;/span&gt; &lt;span class="n"&gt;root_path&lt;/span&gt;
    &lt;span class="n"&gt;assert_css&lt;/span&gt; &lt;span class="s1"&gt;'h2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;text: &lt;/span&gt;&lt;span class="s1"&gt;'Log in'&lt;/span&gt;
    &lt;span class="n"&gt;click_link&lt;/span&gt; &lt;span class="s1"&gt;'Sign up'&lt;/span&gt;

    &lt;span class="c1"&gt;# test validation errors&lt;/span&gt;
    &lt;span class="n"&gt;click_button&lt;/span&gt; &lt;span class="s1"&gt;'Sign up'&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'2 errors prohibited this user from being saved'&lt;/span&gt;

    &lt;span class="n"&gt;fill_in&lt;/span&gt; &lt;span class="s1"&gt;'Email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="s1"&gt;'bob@example.com'&lt;/span&gt;
    &lt;span class="n"&gt;fill_in&lt;/span&gt; &lt;span class="s1"&gt;'Password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;
    &lt;span class="n"&gt;fill_in&lt;/span&gt; &lt;span class="s1"&gt;'Password confirmation'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;
    &lt;span class="n"&gt;click_button&lt;/span&gt; &lt;span class="s1"&gt;'Sign up'&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'Welcome! You have signed up successfully.'&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'Account: bob@example.com'&lt;/span&gt;
    &lt;span class="n"&gt;assert_css&lt;/span&gt; &lt;span class="s1"&gt;'h1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;text: &lt;/span&gt;&lt;span class="s1"&gt;'Welcome!'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Sign in and sign out
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'application_system_test_case'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SignInOutTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationSystemTestCase&lt;/span&gt;
  &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s1"&gt;'sign in and sign out'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;visit&lt;/span&gt; &lt;span class="n"&gt;root_path&lt;/span&gt;
    &lt;span class="n"&gt;assert_css&lt;/span&gt; &lt;span class="s1"&gt;'h2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;text: &lt;/span&gt;&lt;span class="s1"&gt;'Log in'&lt;/span&gt;

    &lt;span class="c1"&gt;# test validation errors&lt;/span&gt;
    &lt;span class="n"&gt;fill_in&lt;/span&gt; &lt;span class="s1"&gt;'Email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="s1"&gt;'bob@example.com'&lt;/span&gt;
    &lt;span class="n"&gt;fill_in&lt;/span&gt; &lt;span class="s1"&gt;'Password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="s1"&gt;'foobar'&lt;/span&gt;
    &lt;span class="n"&gt;click_button&lt;/span&gt; &lt;span class="s1"&gt;'Log in'&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'Invalid Email or password.'&lt;/span&gt;

    &lt;span class="n"&gt;fill_in&lt;/span&gt; &lt;span class="s1"&gt;'Email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="s1"&gt;'alice@example.com'&lt;/span&gt;
    &lt;span class="n"&gt;fill_in&lt;/span&gt; &lt;span class="s1"&gt;'Password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;
    &lt;span class="n"&gt;click_button&lt;/span&gt; &lt;span class="s1"&gt;'Log in'&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'Signed in successfully.'&lt;/span&gt;
    &lt;span class="n"&gt;assert_css&lt;/span&gt; &lt;span class="s1"&gt;'h1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;text: &lt;/span&gt;&lt;span class="s1"&gt;'Welcome!'&lt;/span&gt;

    &lt;span class="n"&gt;click_link&lt;/span&gt; &lt;span class="s1"&gt;'Sign out'&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'Signed out successfully.'&lt;/span&gt;
    &lt;span class="n"&gt;assert_css&lt;/span&gt; &lt;span class="s1"&gt;'h2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;text: &lt;/span&gt;&lt;span class="s1"&gt;'Log in'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Edit account
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'application_system_test_case'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EditAccountTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationSystemTestCase&lt;/span&gt;
  &lt;span class="n"&gt;setup&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;sign_in_as_alice&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s1"&gt;'edit account'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;click_link&lt;/span&gt; &lt;span class="s1"&gt;'Edit account'&lt;/span&gt;

    &lt;span class="c1"&gt;# test validation errors&lt;/span&gt;
    &lt;span class="n"&gt;fill_in&lt;/span&gt; &lt;span class="s1"&gt;'Email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
    &lt;span class="n"&gt;click_button&lt;/span&gt; &lt;span class="s1"&gt;'Update'&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'2 errors prohibited this user from being saved'&lt;/span&gt;

    &lt;span class="n"&gt;fill_in&lt;/span&gt; &lt;span class="s1"&gt;'Email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="s1"&gt;'bob@example.com'&lt;/span&gt;
    &lt;span class="n"&gt;fill_in&lt;/span&gt; &lt;span class="s1"&gt;'Current password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;
    &lt;span class="n"&gt;click_button&lt;/span&gt; &lt;span class="s1"&gt;'Update'&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'Your account has been updated successfully.'&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'Account: bob@example.com'&lt;/span&gt;
    &lt;span class="n"&gt;assert_css&lt;/span&gt; &lt;span class="s1"&gt;'h1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;text: &lt;/span&gt;&lt;span class="s1"&gt;'Welcome!'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Reset password
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'application_system_test_case'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ResetPasswordTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationSystemTestCase&lt;/span&gt;
  &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s1"&gt;'reset password'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;visit&lt;/span&gt; &lt;span class="n"&gt;root_path&lt;/span&gt;
    &lt;span class="n"&gt;assert_css&lt;/span&gt; &lt;span class="s1"&gt;'h2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;text: &lt;/span&gt;&lt;span class="s1"&gt;'Log in'&lt;/span&gt;
    &lt;span class="n"&gt;click_link&lt;/span&gt; &lt;span class="s1"&gt;'Forgot your password?'&lt;/span&gt;

    &lt;span class="c1"&gt;# test validation errors&lt;/span&gt;
    &lt;span class="n"&gt;click_button&lt;/span&gt; &lt;span class="s1"&gt;'Send me reset password instructions'&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'1 error prohibited this user from being saved'&lt;/span&gt;

    &lt;span class="n"&gt;fill_in&lt;/span&gt; &lt;span class="s1"&gt;'Email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="s1"&gt;'alice@example.com'&lt;/span&gt;
    &lt;span class="n"&gt;click_button&lt;/span&gt; &lt;span class="s1"&gt;'Send me reset password instructions'&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'You will receive an email with instructions on how to reset your password in a few minutes.'&lt;/span&gt;
    &lt;span class="n"&gt;assert_css&lt;/span&gt; &lt;span class="s1"&gt;'h2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;text: &lt;/span&gt;&lt;span class="s1"&gt;'Log in'&lt;/span&gt;

    &lt;span class="n"&gt;mail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActionMailer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deliveries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encoded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;%r{http://example.com/(?&amp;lt;path&amp;gt;[-&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="sr"&gt;_?/=]+)}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;visit&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:path&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;assert_css&lt;/span&gt; &lt;span class="s1"&gt;'h2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;text: &lt;/span&gt;&lt;span class="s1"&gt;'Change your password'&lt;/span&gt;

    &lt;span class="c1"&gt;# test validation errors&lt;/span&gt;
    &lt;span class="n"&gt;click_button&lt;/span&gt; &lt;span class="s1"&gt;'Change my password'&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'1 error prohibited this user from being saved'&lt;/span&gt;

    &lt;span class="n"&gt;fill_in&lt;/span&gt; &lt;span class="s1"&gt;'New password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="s1"&gt;'pass1234'&lt;/span&gt;
    &lt;span class="n"&gt;fill_in&lt;/span&gt; &lt;span class="s1"&gt;'Confirm new password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="s1"&gt;'pass1234'&lt;/span&gt;
    &lt;span class="n"&gt;click_button&lt;/span&gt; &lt;span class="s1"&gt;'Change my password'&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'Your password has been changed successfully.'&lt;/span&gt;
    &lt;span class="n"&gt;assert_css&lt;/span&gt; &lt;span class="s1"&gt;'h1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;text: &lt;/span&gt;&lt;span class="s1"&gt;'Welcome!'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Cancel account
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'application_system_test_case'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CancelAccountTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationSystemTestCase&lt;/span&gt;
  &lt;span class="n"&gt;setup&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;sign_in_as_alice&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s1"&gt;'cancel account'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;click_link&lt;/span&gt; &lt;span class="s1"&gt;'Edit account'&lt;/span&gt;
    &lt;span class="n"&gt;accept_alert&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;click_button&lt;/span&gt; &lt;span class="s1"&gt;'Cancel my account'&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;assert_text&lt;/span&gt; &lt;span class="s1"&gt;'Bye! Your account has been successfully cancelled. We hope to see you again soon.'&lt;/span&gt;
    &lt;span class="n"&gt;assert_css&lt;/span&gt; &lt;span class="s1"&gt;'h2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;text: &lt;/span&gt;&lt;span class="s1"&gt;'Log in'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  If you're using OmniAuth
&lt;/h2&gt;

&lt;p&gt;If you're using OmniAuth to sign-in, you need to use &lt;code&gt;button_to&lt;/code&gt; instead of &lt;code&gt;link_to&lt;/code&gt;, and disable Turbo by &lt;code&gt;data: { turbo: false }&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="gd"&gt;-&amp;lt;%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), method: :post %&amp;gt;&amp;lt;br /&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+&amp;lt;%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false } %&amp;gt;&amp;lt;br /&amp;gt;
&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Please don't forget to use &lt;a href="https://rubygems.org/gems/omniauth-rails_csrf_protection/" rel="noopener noreferrer"&gt;omniauth-rails_csrf_protection&lt;/a&gt; gem for OmniAuth 2.0 or higher. This requirement is not related to Turbo, though.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Introducing rails-template-inspector: Open your view files by clicking browser elements</title>
      <dc:creator>Junichi Ito</dc:creator>
      <pubDate>Tue, 12 Jul 2022 03:02:51 +0000</pubDate>
      <link>https://dev.to/jnchito/introducing-rails-template-inspector-open-your-view-files-by-clicking-browser-elements-4190</link>
      <guid>https://dev.to/jnchito/introducing-rails-template-inspector-open-your-view-files-by-clicking-browser-elements-4190</guid>
      <description>&lt;p&gt;&lt;em&gt;(This post was originally written by &lt;a class="mentioned-user" href="https://dev.to/aki77"&gt;@aki77&lt;/a&gt; in Japanese. &lt;a class="mentioned-user" href="https://dev.to/aki77"&gt;@aki77&lt;/a&gt; is a co-worker of mine. You can read the original post &lt;a href="https://zenn.dev/aki77/articles/49633196b7a35a"&gt;here.&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm pleased to announce the release of &lt;a href="https://zenn.dev/aki77/articles/49633196b7a35a"&gt;rails-template-inspector&lt;/a&gt; which is a JS package for Rails applications. You can do the following things by using it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can confirm in which template the element is written by mouse hover.&lt;/li&gt;
&lt;li&gt;You can open template files in your local editor by clicking elements.&lt;/li&gt;
&lt;li&gt;No Bundler, no npm. You can just use it via CDN because it's provided in vanilla JS.&lt;/li&gt;
&lt;li&gt;Unlike &lt;a href="https://github.com/brentd/xray-rails"&gt;xray-rails&lt;/a&gt;, it supports the latest Rails environment. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AXjEYzRv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y88y353i2dilk07tp7j6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AXjEYzRv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y88y353i2dilk07tp7j6.gif" alt="Animated screenshot" width="880" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use
&lt;/h2&gt;

&lt;p&gt;Set the following value to &lt;code&gt;true&lt;/code&gt; in &lt;code&gt;config/environments/development.rb&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;action_view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;annotate_rendered_view_with_filenames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Add the &lt;code&gt;&amp;lt;% if Rails.env.development? %&amp;gt;&lt;/code&gt; block in your &lt;br&gt;
 layout file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;development?&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.skypack.dev/@aki77/rails-template-inspector"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;rails-inspector&lt;/span&gt; &lt;span class="na"&gt;url-prefix=&lt;/span&gt;&lt;span class="s"&gt;"vscode://file"&lt;/span&gt; &lt;span class="na"&gt;root=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="na"&gt;combo-key=&lt;/span&gt;&lt;span class="s"&gt;"command-shift-v"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rails-inspector&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This package uses custom URL scheme to open view files in editors, so please change &lt;code&gt;url-prefix&lt;/code&gt; attribute in &lt;code&gt;&amp;lt;rails-inspector&amp;gt;&lt;/code&gt; element per your favorite editor. Here are examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visual Studio Code: &lt;code&gt;vscode://file&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;RubyMine: &lt;code&gt;x-mine://open?file=&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;MacVIM: &lt;code&gt;mvim://open?url=file://&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Emacs: &lt;code&gt;emacs://open?url=file://&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  How to work
&lt;/h2&gt;

&lt;p&gt;By enabling &lt;code&gt;config.action_view.annotate_rendered_view_with_filenames&lt;/code&gt;, this package can search HTML comments generated by Rails. It also uses &lt;a href="https://lit.dev/"&gt;Lit&lt;/a&gt; to implement custom &lt;code&gt;&amp;lt;rails-inspector&amp;gt;&lt;/code&gt; elements.&lt;/p&gt;

&lt;p&gt;I hope you enjoy &lt;a href="https://github.com/aki77/rails-template-inspector"&gt;rails-template-inspector&lt;/a&gt;!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/aki77"&gt;
        aki77
      &lt;/a&gt; / &lt;a href="https://github.com/aki77/rails-template-inspector"&gt;
        rails-template-inspector
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
&amp;lt;rails-inspector&amp;gt;&lt;/h1&gt;
&lt;p&gt;This custom element allows users to jump to local IDE code directly from browser element by just a simple click. It supports Rails templates.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/6f04297ebf006a7c1e73905e169048cb8b52f3da9659c90cd3ff2aa82acfc5ea/68747470733a2f2f692e6779617a6f2e636f6d2f62383537636237386537343930626465666562623839616266626163386139302e676966"&gt;&lt;img src="https://camo.githubusercontent.com/6f04297ebf006a7c1e73905e169048cb8b52f3da9659c90cd3ff2aa82acfc5ea/68747470733a2f2f692e6779617a6f2e636f6d2f62383537636237386537343930626465666562623839616266626163386139302e676966" alt="Demo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Usage&lt;/h2&gt;
&lt;p&gt;In config/environments/development.rb:&lt;/p&gt;
&lt;div class="highlight highlight-source-ruby notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-en"&gt;config&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;action_view&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;annotate_rendered_view_with_filenames&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-c1"&gt;true&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;In app/views/layouts/application.html.haml:&lt;/p&gt;
&lt;div class="highlight highlight-text-html-erb notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c1"&gt;&amp;lt;!DOCTYPE html&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;html&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;head&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="pl-c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="pl-ent"&gt;head&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;body&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="pl-k"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="pl-k"&gt;yield&lt;/span&gt; &lt;span class="pl-k"&gt;%&amp;gt;&lt;/span&gt;

&lt;span class="pl-k"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="pl-k"&gt;if&lt;/span&gt; &lt;span class="pl-v"&gt;Rails&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;env&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;development?&lt;/span&gt; &lt;span class="pl-k"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;script&lt;/span&gt; &lt;span class="pl-c1"&gt;type&lt;/span&gt;="&lt;span class="pl-s"&gt;module&lt;/span&gt;" &lt;span class="pl-c1"&gt;src&lt;/span&gt;="&lt;span class="pl-s"&gt;https://cdn.skypack.dev/&lt;a class="mentioned-user" href="https://dev.to/aki77"&gt;@aki77&lt;/a&gt;/rails-template-inspector@^0.3.0&lt;/span&gt;"&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="pl-ent"&gt;script&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;rails-inspector&lt;/span&gt; &lt;span class="pl-c1"&gt;url-prefix&lt;/span&gt;="&lt;span class="pl-s"&gt;vscode://file&lt;/span&gt;" &lt;span class="pl-c1"&gt;root&lt;/span&gt;="&lt;span class="pl-k"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="pl-v"&gt;Rails&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;root&lt;/span&gt; &lt;span class="pl-k"&gt;%&amp;gt;&lt;/span&gt;" &lt;span class="pl-c1"&gt;combo-key&lt;/span&gt;="&lt;span class="pl-s"&gt;command-shift-v&lt;/span&gt;"&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="pl-ent"&gt;rails-inspector&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="pl-k"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="pl-k"&gt;end&lt;/span&gt; &lt;span class="pl-k"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="pl-ent"&gt;body&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="pl-ent"&gt;html&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
Attributes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;url-prefix&lt;/code&gt;: Custom URL Scheme for editor. (default: &lt;code&gt;vscode://file&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;Examples
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Visual Studio Code&lt;/strong&gt;: &lt;code&gt;vscode://file&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RubyMine&lt;/strong&gt;: &lt;code&gt;x-mine://open?file=&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MacVIM&lt;/strong&gt;: &lt;code&gt;mvim://open?url=file://&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Emacs&lt;/strong&gt;: &lt;code&gt;emacs://open?url=file://&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;combo-key&lt;/code&gt;: Key to toggle inspector. (default: &lt;code&gt;meta-shift-v&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;any number of modifiers…&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/aki77/rails-template-inspector"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>ruby</category>
      <category>rails</category>
      <category>railstemplateinspector</category>
    </item>
  </channel>
</rss>
