<?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: Adrian Valenzuela</title>
    <description>The latest articles on DEV Community by Adrian Valenzuela (@adrianvalenz).</description>
    <link>https://dev.to/adrianvalenz</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%2F517128%2Fcebf665d-6a4b-45c7-8497-75c3e7287a91.jpeg</url>
      <title>DEV Community: Adrian Valenzuela</title>
      <link>https://dev.to/adrianvalenz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adrianvalenz"/>
    <language>en</language>
    <item>
      <title>Custom shell function in .zshrc to search strings</title>
      <dc:creator>Adrian Valenzuela</dc:creator>
      <pubDate>Tue, 29 Mar 2022 05:53:48 +0000</pubDate>
      <link>https://dev.to/adrianvalenz/custom-shell-function-in-zshrc-to-search-strings-14i5</link>
      <guid>https://dev.to/adrianvalenz/custom-shell-function-in-zshrc-to-search-strings-14i5</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seek() {
  if [ "$1" != "" ]
  then
    grep -H -r --exclude-dir=node_modules "$1" * | less
  else
    echo "need to type in a string"
  fi
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use this function when I join an existing project and I need to get familiar with the code base. I got tired of typing in &lt;code&gt;grep -H -r 'string' * | less&lt;/code&gt; so I created this little function to make the process quicker.&lt;/p&gt;

&lt;p&gt;Now we just type in &lt;code&gt;seek custom_method&lt;/code&gt; and a list of files will appear from the project that contain that method or whatever string you passed. I added a flag to exclude &lt;code&gt;node_modules&lt;/code&gt; because usually that's not where you need to look and it could pull up irrelevant files.&lt;/p&gt;

&lt;p&gt;This is helpful when searching file names is not enough. I'm pretty excited about this one. I hope it helps you out!&lt;/p&gt;

</description>
      <category>zsh</category>
      <category>shell</category>
      <category>bash</category>
    </item>
    <item>
      <title>Authentication with Sorcery, RSpec, and Rails 7: Building a simple Rails CMS - Part 1</title>
      <dc:creator>Adrian Valenzuela</dc:creator>
      <pubDate>Sat, 29 Jan 2022 21:49:05 +0000</pubDate>
      <link>https://dev.to/adrianvalenz/authentication-with-sorcery-rspec-and-rails-7-building-a-simple-rails-cms-part-1-505c</link>
      <guid>https://dev.to/adrianvalenz/authentication-with-sorcery-rspec-and-rails-7-building-a-simple-rails-cms-part-1-505c</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://unsplash.com/@gabrielkraus?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Gabriel Kraus&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/sorcery?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We are going to build a little CMS with features including authentication with Sorcery, authorization with Pundit, Users that can create posts and upload images, access a dashboard and manage the navigation menu links and image galleries. We will call it, WizardCMS&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%2Fjw786x41j881mt0a7d2e.jpeg" 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%2Fjw786x41j881mt0a7d2e.jpeg" alt="Hagrid You're a wizard harry meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are using Sorcery because its low-level nature allows us to create a simple authentication flow with out many of the headaches that other popular libraries are giving other developers.&lt;/p&gt;

&lt;p&gt;We have a long road ahead of us, and our passenger coming along for the ride will be our buddy RSpec who knows the way and will make sure we are heading the right direction.&lt;/p&gt;

&lt;p&gt;The format of the articles will be that I write a test, layout the code to make the test pass and make the feature/functionality happen, and do my best to explain what is happening in the code. Often I come across article that doesn't explain enough of what is happening and it leaves me wondering why something was done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To view progress on this project:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/adrianvalenz/wizardcms" rel="noopener noreferrer"&gt;Source code on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wizardcms.herokuapp.com/" rel="noopener noreferrer"&gt;Example app on Heroku&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create new app and install RSpec
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;I might be adding my own CSS through the project but I won’t clutter the tutorial with it. You can style and lay out the HTML how you like really. I hope at least to give you a decent reference as to what code you might want to use to create the app with authentication and the other features listed above. I will also be using version control, but I won’t be adding it to the tutorial as well, I’ll leave that up to you. Typically it is a good idea to just create a new branch when working on a new feature or chunk of code. :)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Create new app &lt;code&gt;rails new app_name&lt;/code&gt; and &lt;a href="https://adrianvalenz.com/blog/setup-rspec-on-fresh-rails-7-project/" rel="noopener noreferrer"&gt;install RSpec&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Sorcery
&lt;/h2&gt;

&lt;p&gt;We'll be installing Sorcery based off this &lt;a href="https://github.com/Sorcery/sorcery/wiki/Simple-Password-Authentication" rel="noopener noreferrer"&gt;tutorial&lt;/a&gt; in their wiki. I'm modifying a little bit since we are creating something different, but also because their tutorial is a bit outdated since it is based off an older version of Rails.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bundle add sorcery
bundle install
rails g sorcery:install
rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we run the migration it will set up a &lt;code&gt;users&lt;/code&gt; table for us with some attributes to store in the database. &lt;/p&gt;

&lt;p&gt;Let's start or restart the server so Rails loads up Sorcery.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails s 
# or ./bin/dev if using js-bundling/css-bundling
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go on and add our first feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  User cannot access dashboard when logged out
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Spec
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/system/user_session_flow_spec.rb

require 'rails_helper'

describe "User session flow", type: :system do
  scenario "redirected from dashboard when logged out" do
    visit "/dashboard"
    expect(page).to have_text("You must log in")
    page_title = find('h1#page-title')
    expect(page_title).to have_content("Login")
    expect(page).to have_no_content('Dashboard')
  end

  scenario "user clicks register account" do
    visit dashboard_path
    expect(page).to have_content("Don't have an account?")
    click_link "register-user"
    page_title = find('h1#page-title')
    expect(page_title).to have_content("Register")
  end
end

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

&lt;/div&gt;



&lt;p&gt;In our first spec file that we will write, I split it into two scenarios because it was getting pretty hefty. You don't want too many things happening in a test because then it becomes difficult to manage. Usually a simple test run where you have a user visit a page, interact with an element, have it make a response and display (or not display) something on a page is enough to find out whether a feature works or not. Here's a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;visit "/about"
expect(page).to have_content("About Our Company")
fill_in "Email"
fill_in "Your message"
click_on "Send message"
expect(page).to have_text("You have sent your message successfully.")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example shows me that the user was able to go to the about page and see the title, interact with the form, and get a response that their message was sent. If this passes it means the app has the elements and functionality in place and it is behaving the way we expect it to.&lt;/p&gt;

&lt;p&gt;With this in mind, I hope our spec file is self-explanatory just by reading the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Models
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class User &amp;lt; ApplicationRecord
  authenticates_with_sorcery!

  validates :password, length: { minimum: 3 }, if: -&amp;gt; { new_record? || changes[:crypted_password] }
  validates :password, confirmation: true, if: -&amp;gt; { new_record? || changes[:crypted_password] }
  validates :password_confirmation, presence: true, if: -&amp;gt; { new_record? || changes[:crypted_password] }

  validates :email, uniqueness: true
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our user model file we are declaring that we authenticate a User with the Sorcery gem. Then we lay our a couple validations; these validations are for "virtual attributes" that we will use on our forms. If you noticed when we ran the initial migration there were no &lt;code&gt;password&lt;/code&gt; or &lt;code&gt;password_confirmation&lt;/code&gt; attributes in the users table, but instead a &lt;code&gt;salt&lt;/code&gt; and &lt;code&gt;crypted_password&lt;/code&gt; attributes. The idea is that you don't store passwords in plain text in the database, so this code will take the virtual attributes in the form and encrypt them before storing them in the database. We also validate the uniqueness of &lt;code&gt;email&lt;/code&gt;, which means two different user accounts cannot use the same email to sign up, there can only be one: &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%2F4qot324h3dck0huqtiwk.gif" 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%2F4qot324h3dck0huqtiwk.gif" alt="Highlander gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Routes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# config/routes.rb
get 'register', to: 'user_registrations#new'
get 'login' =&amp;gt; 'user_sessions#new', :as =&amp;gt; :login
get 'dashboard', to: 'dashboard#show'
root "home#show"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Currently we have 4 routes in place, all of which are &lt;code&gt;get&lt;/code&gt; requests where we request some templates with data. Here we are requesting a register page, login page, dashboard page, and homepage. If you are not familiar with MVC frameworks, these routes actually point to a controller action, which in turn returns the template. The actions can return other things like JSON, but for now we'll focus on templates. Rails returns a template file if it has the same name as the action.&lt;/p&gt;

&lt;h3&gt;
  
  
  Controllers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controller/dashboard_controller.rb

class DashboardController &amp;lt; ApplicationController
    def show
    end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our dashboard route points to the dashboard controller and show action. We don't need to write anything in the show action because by default it'll point to the &lt;code&gt;show.html.erb&lt;/code&gt; view.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controllers/application_controller.rb

class ApplicationController &amp;lt; ActionController::Base
  before_action :require_login

  private
  def not_authenticated
    redirect_to login_path, alert: "You must log in"
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code in our application controller will also be called in the controllers we write. The controllers we write extend from the application controller. In other words, for example, when we write &lt;code&gt;class DashboardController &amp;lt; ApplicationController; end&lt;/code&gt; we are saying "run the code in the application controller, and if dashboard controller overrides anything, run that".&lt;/p&gt;

&lt;p&gt;So by adding &lt;code&gt;before_action :require_login&lt;/code&gt; to our application controller, it will also be called in every other controller that extends from it unless we say otherwise. That's how access is restricted to the dashboard page and you need to log in to access it.&lt;/p&gt;

&lt;p&gt;Sorcery also has a method &lt;code&gt;not_authenticated&lt;/code&gt; that also runs when a user attempts to access a restricted page, so we specify where we want the user to be redirected and also specify an alert.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controllers/home_controller.rb

class HomeController &amp;lt; ApplicationController
    skip_before_action :require_login, only: :show
  def show
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the home controller, we add another method called &lt;code&gt;skip_before_action&lt;/code&gt; which basically is "&lt;strong&gt;don't&lt;/strong&gt; run this method before any action" and we specify which method by passing in the &lt;code&gt;:require_login&lt;/code&gt; method, and specify the &lt;code&gt;show&lt;/code&gt; action by passing it as an option. Essentially this code says the user doesn't need to be logged in to access it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controllers/user_sessions_controller.rb

class UserSessionsController &amp;lt; ApplicationController
  skip_before_action :require_login, only: %i[ new ]

  def new
  end
end

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

&lt;/div&gt;



&lt;p&gt;Earlier in our application controller we called a method, the &lt;code&gt;login_path&lt;/code&gt; route. The route points to the &lt;code&gt;user_sessions&lt;/code&gt; controller and it's &lt;code&gt;new&lt;/code&gt; action. We add the &lt;code&gt;skip_before_action :require_login&lt;/code&gt; as well so we can give non-signed users the ability to log in. The &lt;code&gt;new&lt;/code&gt; action will render the &lt;code&gt;new.html.erb&lt;/code&gt; template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controllers/user_registrations_controller.rb

class UserRegistrationsController &amp;lt; ApplicationController
  skip_before_action :require_login, only: :new

  def new
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Views
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/dashboard/show.html.erb
&amp;lt;h1&amp;gt;Dashboard&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/home/show.html.erb
&amp;lt;h1&amp;gt;Homepage&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are starting slow, and only adding the h1 tags with what is the title of the template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/shared/_navbar.html.erb
&amp;lt;nav&amp;gt;
  &amp;lt;section&amp;gt;
    &amp;lt;%= link_to "Home", root_path %&amp;gt;
    &amp;lt;%= link_to "Dashboard", dashboard_path if current_user %&amp;gt;
  &amp;lt;/section&amp;gt;
&amp;lt;/nav&amp;gt;

&amp;lt;aside&amp;gt;
  &amp;lt;% if notice %&amp;gt;&amp;lt;%= notice %&amp;gt;&amp;lt;% end %&amp;gt;
  &amp;lt;% if alert %&amp;gt;&amp;lt;%= alert %&amp;gt;&amp;lt;% end %&amp;gt;
&amp;lt;/aside&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;We're going to use a conditional statement to display the dashboard link when the user is signed in, and we'll have some methods to show us alerts or notices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/layouts/application.html.erb

  &amp;lt;body&amp;gt;
    &amp;lt;%= render 'shared/navbar' %&amp;gt;
    &amp;lt;%= yield %&amp;gt;
  &amp;lt;/body&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Render the &lt;code&gt;_navbar.html.erb&lt;/code&gt; partial in the &lt;code&gt;application.html.erb&lt;/code&gt; template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/user_sessions/new.html.erb

&amp;lt;h1 id="page-title"&amp;gt;Login&amp;lt;/h1&amp;gt;

&amp;lt;div&amp;gt;
  &amp;lt;p&amp;gt;Don't have an account? &amp;lt;%= link_to "Register", register_path, id: "register-user" %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;I like the idea of using Capybara to click on the &lt;code&gt;id&lt;/code&gt; of an element versus the content of the HTML because I might want to replace "Login" with an SVG icon and add the attribute &lt;code&gt;title="login"&lt;/code&gt; (Note the title attribute is good practice for accessibility so it's something that is highly recommended to be added).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/user_registrations/new.html.erb
&amp;lt;h1 id="page-title"&amp;gt;Register&amp;lt;/h1&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;And lastly the &lt;code&gt;user_registrations/new.html.erb&lt;/code&gt; template.&lt;/p&gt;

&lt;p&gt;After having all these files in place, the test should pass. Awesome, but we are far from done. Let's look at our next feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  User registers account
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Spec
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require 'rails_helper'

describe "User registers account", type: :system do
  scenario "user registers and sees dashboard" do
    visit login_path
    click_link 'register-user'

    email = Faker::Internet.email
    password = Faker::Internet.password
    fill_in "Email", with: email
    fill_in "Password", with: password
    fill_in "Password confirmation", with: password
    click_on "submit-register-user"

    expect(page).to have_text("You have registered successfully")

    page_title = find('h1#page-title')
    expect(page_title).to have_content("Dashboard")
    expect(page).to have_content(email)
  end
end


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

&lt;/div&gt;



&lt;p&gt;This test is pretty fun. Here we use the &lt;code&gt;Faker&lt;/code&gt; gem to create a fake user on the fly. From what I understand it is different from using the &lt;code&gt;FactoryBot&lt;/code&gt; gem method (with user assignment) &lt;code&gt;user = create :user&lt;/code&gt; because the latter will imply that there already exists a user in the database, the former helps us simulate the creation of a new user when filling out the new user registration form.&lt;/p&gt;

&lt;h3&gt;
  
  
  Routes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  get 'register', to: 'user_registrations#new'
  post 'register/user', to: 'user_registrations#create'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We only need to set up two routes for this test, one to get the form, the other to post the form action. When the user clicks submit it will run the code shown below on the &lt;code&gt;create&lt;/code&gt; action to create the user.&lt;/p&gt;

&lt;h3&gt;
  
  
  Controllers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controllers/user_registrations_controller.rb

class UserRegistrationsController &amp;lt; ApplicationController
  skip_before_action :require_login, only: %i[ new create ]

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      auto_login(@user)
      redirect_to dashboard_path, notice: "You successfully registered"
    else
      flash.now[:alert] = "Registration failed"
      render :new
    end
  end

  private
  def user_params
      params.require(:user).permit(:email, :password, :password_confirmation)
  end
end

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

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Fun fact: The &lt;code&gt;%i&lt;/code&gt; is for creating an output of non-interpolated array of symbols. Here's a &lt;a href="http://ruby.zigzo.com/2014/08/21/rubys-notation/" rel="noopener noreferrer"&gt;cool blog post&lt;/a&gt; with some references.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When someone is filling out the registration form to create a new user account, the &lt;code&gt;@user&lt;/code&gt; instance variable will load the &lt;code&gt;new&lt;/code&gt; method on the &lt;code&gt;User&lt;/code&gt; class. (&lt;code&gt;@user = User.new&lt;/code&gt;). Then in the form we will fill in the attributes &lt;code&gt;:email, :password, :password_confirmation&lt;/code&gt; so when we click submit it will take the attributes and use that to create a new user. The attributes are permitted (whitelisted) and required to be present during the &lt;code&gt;create&lt;/code&gt; action and we pass them via the &lt;code&gt;user_params&lt;/code&gt; private method. Private methods can only be accessed by other methods if they are within the same class.&lt;/p&gt;

&lt;p&gt;What I really like about this particular &lt;code&gt;create&lt;/code&gt; action that we wrote is that we got to use Sorcery's &lt;code&gt;auto_login()&lt;/code&gt; method. We pass in the user that was just created and automatically log them in after registering so we can direct them to the dashboard. Clean and simple. From there they can log out and log in as they please, after we create that functionality of course.&lt;/p&gt;

&lt;h3&gt;
  
  
  Views
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/user_registrations/new.html.erb

&amp;lt;h1 id="page-title"&amp;gt;Register&amp;lt;/h1&amp;gt;

&amp;lt;%= form_with(model: @user, url: register_user_path, method: :post) do |form| %&amp;gt;

  &amp;lt;div&amp;gt;
    &amp;lt;%= form.label :email %&amp;gt;
    &amp;lt;%= form.text_field :email %&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;div&amp;gt;
    &amp;lt;%= form.label :password %&amp;gt;
    &amp;lt;%= form.password_field :password %&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;div&amp;gt;
    &amp;lt;%= form.label :password_confirmation %&amp;gt;
    &amp;lt;%= form.password_field :password_confirmation %&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;div&amp;gt;
    &amp;lt;%= form.submit "Create Account", id: "submit-register-user" %&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;% end %&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;This form specifies and loads up the model, the url for the form action which points to our &lt;code&gt;user_registrations#create&lt;/code&gt; action, and we get explicit about our form submitting a POST method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/dashboard/show.html.erb
&amp;lt;h1 id="page-title"&amp;gt;Dashboard&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we add the &lt;code&gt;id&lt;/code&gt; to the h1 tag for the Dashboard because our new test now calls for it. Considering the possibility that Capybara might get "confused" and see the "Dashboard" link in our nav and "Dashboard" title in our page, we add the &lt;code&gt;id&lt;/code&gt; to make sure it finds the one we want it to find.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/shared/_navbar.html.erb
&amp;lt;nav&amp;gt;
  &amp;lt;section&amp;gt;
    &amp;lt;%= link_to "Home", root_path %&amp;gt;
    &amp;lt;%= link_to "Dashboard", dashboard_path if current_user %&amp;gt;
  &amp;lt;/section&amp;gt;
  &amp;lt;section&amp;gt;
    &amp;lt;% if current_user %&amp;gt;
      You are logged in as: &amp;lt;%= current_user.email %&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;/section&amp;gt;
&amp;lt;/nav&amp;gt;

&amp;lt;aside&amp;gt;
  &amp;lt;% if notice %&amp;gt;&amp;lt;%= notice %&amp;gt;&amp;lt;% end %&amp;gt;
  &amp;lt;% if alert %&amp;gt;&amp;lt;%= alert %&amp;gt;&amp;lt;% end %&amp;gt;
&amp;lt;/aside&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Let's up the navbar partial to show the email of the user signed in. Here's how our current navbar looks like, we'll tidy it up later on.&lt;/p&gt;

&lt;p&gt;That should be good for that feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  User signs in to dashboard
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Spec
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/system/user_sign_in_spec.rb

require 'rails_helper'

describe "User login flow", type: :system do
  scenario "user goes to log in page" do
    visit root_path
    click_on "sign-in-link"

    page_title = find("h1#page-title")
    expect(page_title).to have_content("Login")
  end

  scenario "user fills out form and signs in" do
    user = create :user

    visit login_path

    fill_in "Email", with: user.email
    fill_in "Password", with: "secret"
    click_on "sign-in-button"

    expect(page).to have_content(user.email)
    expect(page).to have_text('You have logged in successfully')
  end
end

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

&lt;/div&gt;



&lt;p&gt;Now we are going to make sure an existing user can log in and we'll use &lt;code&gt;FactoryBot&lt;/code&gt; to test that. While running the test it'll create a new user with predefined attributes which you can refer below in the section titled "Factory".&lt;/p&gt;

&lt;p&gt;The first test will make sure the user can click to the login page. Super simple, all we have to do is create the link, but we'll refactor the navbar partial a bit as you'll see in the "Views" section below.&lt;/p&gt;

&lt;p&gt;Our second test will have an existing user go to the login page, fill out the form and sign in and see their email displayed on the page and a successful login message.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/factories/user.rb

FactoryBot.define do
  factory :user do
    sequence(:email) { |i| "user#{i}@example.com" }
    password { "secret" }
    password_confirmation { "secret" }

    salt { salt = "asdasdastr4325234324sdfds" }
    crypted_password { Sorcery::CryptoProviders::BCrypt.encrypt("secret", salt) }
  end
end

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

&lt;/div&gt;



&lt;p&gt;I'm hoping when we created the User model with Sorcery that it created this factory for you, also refer to my &lt;a href="https://dev.to/adrianvalenz/setup-rspec-on-a-fresh-rails-7-project-5gp"&gt;RSpec setup in Rails 7&lt;/a&gt; if you haven't seen it yet.&lt;/p&gt;

&lt;p&gt;Let's make our user factory look like the code above.&lt;/p&gt;

&lt;h3&gt;
  
  
  Routes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# config/routes.rb

post 'login' =&amp;gt; "user_sessions#create"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This route will point to the create action in the &lt;code&gt;user_sessions_controller&lt;/code&gt; to create a session for the user. The code to make it happen will be in the following controller section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Controllers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controllers/user_sessions_controller.rb

class UserSessionsController &amp;lt; ApplicationController
  skip_before_action :require_login, only: %i[ new create ]

  def new
  end

  def create
    @user = login(params[:email], params[:password])

    if @user
      redirect_back_or_to(dashboard_path, notice: "You have logged in successfully")
    else
      flash.now[:alert] = "Log in failed"
      render :new
    end
  end
end

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

&lt;/div&gt;



&lt;p&gt;Sorcery gives us a &lt;code&gt;login&lt;/code&gt; method where we can pass in our params from the form and it logs us in, if the params exist, or in other words &lt;code&gt;if @user = true&lt;/code&gt; then it will redirect you to the dashboard or the page you tried to access before being prompted for your login credentials. If the login failed, it will render the login form again and let you know it failed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Views
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/shared/_navbar.html.erb
&amp;lt;nav&amp;gt;
  &amp;lt;section&amp;gt;
    &amp;lt;%= link_to "Home", root_path %&amp;gt;
  &amp;lt;/section&amp;gt;
  &amp;lt;section&amp;gt;
    &amp;lt;% if current_user %&amp;gt;
      &amp;lt;%= link_to "Dashboard", dashboard_path %&amp;gt;
      You are logged in as: &amp;lt;%= current_user.email %&amp;gt;
    &amp;lt;% else %&amp;gt;
      &amp;lt;%= link_to "Login", login_path, id: 'sign-in-link' %&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;/section&amp;gt;
&amp;lt;/nav&amp;gt;

&amp;lt;aside&amp;gt;
  &amp;lt;% if notice %&amp;gt;&amp;lt;%= notice %&amp;gt;&amp;lt;% end %&amp;gt;
  &amp;lt;% if alert %&amp;gt;&amp;lt;%= alert %&amp;gt;&amp;lt;% end %&amp;gt;
&amp;lt;/aside&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;We moved the login and log out links into the same conditional statement as the dashboard link because they all pertain to each other.&lt;/p&gt;

&lt;p&gt;Run the test and it will pass! On to the next feature!&lt;/p&gt;

&lt;h2&gt;
  
  
  User signs out
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Spec
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/system/user_sign_out_spec.rb

require 'rails_helper'

describe "User signs out", type: :system do
  before do
    user = create :user

    visit login_path

    fill_in "Email", with: user.email
    fill_in "Password", with: "secret"
    click_on "sign-in-button"

    expect(page).to have_content(user.email)
    expect(page).to have_text('You have logged in successfully')
  end

  scenario "user signs out from dashboard and get taken to homepage" do
    visit dashboard_path
    expect(page).to have_current_path(dashboard_path)
    click_on 'sign-out-link'
    expect(page).to have_text("You have logged out")
    expect(page).to have_current_path(root_path)
  end
end

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

&lt;/div&gt;



&lt;p&gt;Now we are going to write a test where we have the user sign out from the dashboard and gets redirected back to the home page. It is implied that the user is already signed in, so we need to reflect that in the test. The &lt;code&gt;before do&lt;/code&gt; statement will allow us to set up a user before running the tests that we want to pass.&lt;/p&gt;

&lt;h3&gt;
  
  
  Routes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# config/routes.rb
delete 'logout', to: 'user_sessions#destroy', as: :logout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the route we'll use to perform the destroy action on a user's session so they can log out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Controllers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controllers/user_sessions_controller.rb

class UserSessionsController &amp;lt; ApplicationController
  skip_before_action :require_login, only: %i[ new create ]

  def new
  end

  def create
    @user = login(params[:email], params[:password])

    if @user
      redirect_back_or_to(dashboard_path, notice: "You have logged in successfully")
    else
      flash.now[:alert] = "Log in failed"
      render :new
    end
  end

  def destroy
    logout
    redirect_to root_path, status: :see_other, notice: "You have logged out"
  end
end

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Views
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/shared/_navbar.html.erb

&amp;lt;nav&amp;gt;
  &amp;lt;section&amp;gt;
    &amp;lt;%= link_to "Home", root_path %&amp;gt;
  &amp;lt;/section&amp;gt;
  &amp;lt;section&amp;gt;
    &amp;lt;% if current_user %&amp;gt;
      &amp;lt;%= link_to "Dashboard", dashboard_path %&amp;gt;
      You are logged in as: &amp;lt;%= current_user.email %&amp;gt;
      &amp;lt;%= link_to "Logout", :logout, id: 'sign-out-link', data: { "turbo-method": :delete } %&amp;gt;
    &amp;lt;% else %&amp;gt;
      &amp;lt;%= link_to "Login", login_path, id: 'sign-in-link' %&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;/section&amp;gt;
&amp;lt;/nav&amp;gt;

&amp;lt;aside&amp;gt;
  &amp;lt;% if notice %&amp;gt;&amp;lt;%= notice %&amp;gt;&amp;lt;% end %&amp;gt;
  &amp;lt;% if alert %&amp;gt;&amp;lt;%= alert %&amp;gt;&amp;lt;% end %&amp;gt;
&amp;lt;/aside&amp;gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fun facts
&lt;/h3&gt;

&lt;p&gt;So I want to point out a couple things going on here that may look different in comparison to older versions of Rails.&lt;/p&gt;

&lt;p&gt;I'll focus on these lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# in the route
delete 'logout', to: 'user_sessions#destroy', as: :logout

# in the controller
redirect_to root_path, status: :see_other, notice: "You have logged out"

# in the view
&amp;lt;%= link_to "Logout", :logout, id: 'sign-out-link', data: { "turbo-method": :delete } %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What you see in the route is how Rails has always laid out their resources. Rails convention is that you map an HTTP verb to a controller action which in turn also maps to a CRUD operation in the database.&lt;/p&gt;

&lt;p&gt;Prior to Rails 7, when you would want to log out or destroy a resource (a post or image), you would write &lt;code&gt;&amp;lt;%= link_to "Sign out", destroy_user_session_path, method: :delete %&amp;gt;&lt;/code&gt;. The &lt;code&gt;method: :delete&lt;/code&gt; part relied on an old library, &lt;a href="https://github.com/rails/rails-ujs/tree/master" rel="noopener noreferrer"&gt;rails-ujs&lt;/a&gt; and it helped make NON-Get requests from hyperlinks. Now with Turbo, the solution is to add &lt;code&gt;data: { "turbo-method": :delete }&lt;/code&gt; so you don't get an error saying the &lt;code&gt;link_to&lt;/code&gt; helper was looking for a &lt;code&gt;GET&lt;/code&gt; resource. However, Turbo is not handling the redirect as we expect it, or at all, we need to explicitly say we want a 303 redirect so we add &lt;code&gt;status: :see_other&lt;/code&gt; as an option in our &lt;code&gt;destroy&lt;/code&gt; action.&lt;/p&gt;

&lt;p&gt;Being able to control the behavior of my authentication flow with a few controllers and helpers due to the low-level nature of Sorcery really makes the app feel light-weight and I don't feel like I am overriding a ton of code that often comes with another authentication solution.&lt;/p&gt;

&lt;p&gt;Run the test and it will pass. Next we are going to refactor some duplicate code and abstract it into a helper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refactor and create a test helper method in spec
&lt;/h2&gt;

&lt;p&gt;In our last feature we added a test where we log in the user in order for them to perform the function to log out. This was the second implementation that we made where we had to have a user signed in to perform some interactions with the web. &lt;/p&gt;

&lt;p&gt;I can already foresee that we are going to need to log in the user multiple throughout the development of the app, and rewriting the same code repeatedly is not a good use of our time. If it was a couple use cases then maybe that's ok, but if you find repetition through out your app, you might want to abstract that code into a helper method that you can call through out the app.&lt;/p&gt;

&lt;p&gt;We are going to modify two spec files: &lt;code&gt;user_sign_in_spec.rb&lt;/code&gt; and &lt;code&gt;user_sign_out_spec.rb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is the part of the code we will abstract into a test helper method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    visit login_path
    fill_in "Email", with: user.email
    fill_in "Password", with: "secret"
    click_on "sign-in-button"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: While there are many ways you can log in a user, currently this is how our app works. We only have one login portal. If we need to update the helper method or create a new one to test a new method of logging in (for example through a social media account) then we would write the code to make it happen.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We'll be creating a new file and modifying the &lt;code&gt;spec/rails_helper.rb&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;spec/support/sorcery_test_helper.rb&lt;/code&gt; and add the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/support/sorcery_test_helpers_rails.rb

module Sorcery
  module TestHelpers
    module Rails
      def sign_in(user)
        visit login_path
        fill_in "Email", with: user.email
        fill_in "Password", with: "secret"
        click_on "sign-in-button"
      end
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Require this file in the &lt;code&gt;rails_helper.rb&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/rails_helper.rb

# Add additional requires below this line. Rails is not loaded until this point!
require_relative 'support/factory_bot'
require_relative 'support/chrome'
require_relative 'support/sorcery_test_helpers_rails'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And include the modules in RSpec's configuration in the same file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/rails_helper.rb
RSpec.configure do |config|
  config.include Sorcery::TestHelpers::Rails
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now change the spec files to look like this with the new test helper method&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/system/user_sign_in_spec.rb
require 'rails_helper'

describe "User login flow", type: :system do
    ... 

  scenario "user fills out form and signs in" do
    user = create :user
    sign_in(user)

    expect(page).to have_content(user.email)
    expect(page).to have_text('You have logged in successfully')
  end
end

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/system/user_sign_out_spec.rb

require 'rails_helper'

describe "User signs out", type: :system do
  before do
    user = create :user
    sign_in(user)
  end

  scenario "user signs out from dashboard and get taken to homepage" do
    visit dashboard_path
    expect(page).to have_current_path(dashboard_path)
    click_on 'sign-out-link'
    expect(page).to have_text("You have logged out")
    expect(page).to have_current_path(root_path)
  end
end

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

&lt;/div&gt;



&lt;p&gt;We will omit the expectation of seeing the email and success message in our &lt;code&gt;user_sign_out_spec&lt;/code&gt; since we already know it works from our &lt;code&gt;user_sign_in_spec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Run the test and it should pass!&lt;/p&gt;

&lt;p&gt;This article covered some basic authentication features with Sorcery and I think we are at a good point to get familiar with this functionality. Next article we will be creating a reset/forgot password feature, so until if you try out this code don't forget your credentials! &lt;/p&gt;

&lt;p&gt;While other authentication gems do a lot out of the box for you, it tends to do it a very specific way, and often you override things to make it work with your app. With Sorcery, we only add what we need and it is low-level enough to customized how users sign in and out with your app, but high-level enough where you don't have to stress too much about security.&lt;/p&gt;

&lt;p&gt;I emailed the current maintainer and he plans to add some new features for Sorcery: "JWT support, WebAuthn integration, and updating the OAuth integration to use Omniauth are the major features slated for v1". &lt;/p&gt;

&lt;p&gt;So that's pretty exciting. Please consider sponsoring the project on &lt;a href="https://github.com/sponsors/athix" rel="noopener noreferrer"&gt;Github&lt;/a&gt; at only $5 to show that there is a need for another great authentication solution for the future of Rails.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>rspec</category>
      <category>authentication</category>
    </item>
    <item>
      <title>Custom authentication flow with Sorcery gem, RSpec, and Rails 7 - Pt. 1</title>
      <dc:creator>Adrian Valenzuela</dc:creator>
      <pubDate>Tue, 11 Jan 2022 00:38:42 +0000</pubDate>
      <link>https://dev.to/adrianvalenz/custom-authentication-flow-with-sorcery-gem-rspec-and-rails-7-pt-1-hc1</link>
      <guid>https://dev.to/adrianvalenz/custom-authentication-flow-with-sorcery-gem-rspec-and-rails-7-pt-1-hc1</guid>
      <description>&lt;p&gt;&lt;a href="http://adrianvalenz.com/blog/custom-authentication-flow-with-sorcery-gem-rspec-and-rails-7-part-1/"&gt;Originally posted here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;UPDATE: I rearranged the order of some of the code snippets to make it easier to scan and find. At the end of the article I go into a bit more detail about what is going on in the snippets, but if any of you have any questions please feel free to ask.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/bhs1FVkTBXw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;We're going to install Sorcery, a low-level authentication gem to help you create a custom authentication flow for your app&lt;/p&gt;

&lt;p&gt;I'm picking up where I left off in a post where I install RSpec onto a fresh Rails 7 app. If you want to start there so we are on the same page please feel free: &lt;a href="https://dev.to/adrianvalenz/setup-rspec-on-a-fresh-rails-7-project-5gp"&gt;Install RSpec on Rails 7&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout -b sorcery-sign-up-feature
bundle add sorcery
bundle install
rails g sorcery:install
rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we write any code let's just write a simple spec to serve as our guide so we know what to focus on energy on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spec
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/system/sign_up_spec.rb

require 'rails_helper'

describe "User signs up", type: :system do
  let(:email) { Faker::Internet.email }
  let(:password) { Faker::Internet.password(min_length: 8) }

  before do
    visit root_path
  end

  scenario "register user account" do
    click_on "Register"
    fill_in "Email", with: email
    fill_in "Password", with: password
    fill_in "Password confirmation", with: password
    click_button "Sign up"

    expect(page).to have_content("Dashboard")
    expect(page).to have_content(email)
    expect(page).to have_no_content("Register")
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm just going to give you all the code you need to pass that test!&lt;/p&gt;

&lt;h2&gt;
  
  
  Routes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# config/routes.rb

Rails.application.routes.draw do
  get 'dashboard', to: 'dashboard#show'
  get 'register', to: 'user_registration#new'
  resources :user_registrations, only: :create
  root 'home#show'
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Controllers
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controllers/home_controller.rb

class HomeController &amp;lt; ApplicationController
  def show
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controllers/dashboard_controller.rb

class DashboardController &amp;lt; ApplicationController
  def show
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controllers/user_registrations_controller.rb

class UserRegistrationsController &amp;lt; ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      auto_login(@user)
      redirect_to dashboard_path, notice: "You have registered successfully."
    else
      render :new
    end
  end

  private
  def user_params
    params.require(:user).permit(:email, :password, :password_confirmation)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Views
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/home/show.html.erb

&amp;lt;h1&amp;gt;Homepage&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/dashboard/show.html.erb

&amp;lt;h1&amp;gt;Dashboard&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/shared/_navbar.html.erb

&amp;lt;% if current_user %&amp;gt;
  &amp;lt;%= current_user.email %&amp;gt;
&amp;lt;% else %&amp;gt;
  &amp;lt;%= link_to "Register", register_path %&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/layout/application.html.erb

&amp;lt;%= render "shared/navbar" %&amp;gt;

&amp;lt;% if notice %&amp;gt;&amp;lt;%= notice %&amp;gt;&amp;lt;% end %&amp;gt;
&amp;lt;% if alert %&amp;gt;&amp;lt;%= alert %&amp;gt;&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/views/user_registrations/new.html.erb

&amp;lt;h1&amp;gt;Register an account&amp;lt;/h1&amp;gt;

&amp;lt;%= form_with(model: @user, url: user_registration_path, method: :post) do |form| %&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;%= form.label :email %&amp;gt;
    &amp;lt;%= form.text_field :email %&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;div&amp;gt;
    &amp;lt;%= form.label :password %&amp;gt;
    &amp;lt;%= form.password_field :password %&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;div&amp;gt;
    &amp;lt;%= form.label :password_confirmation %&amp;gt;
    &amp;lt;%= form.password_field :password_confirmation %&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;div&amp;gt;
    &amp;lt;%= form.submit "Sign up" %&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Models
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/model/user.rb

class User &amp;lt; ApplicationRecord
  authenticates_with_sorcery!

  validates :password, length: { minimum: 3 }, if: -&amp;gt; { new_record? || changes[:crypted_password] }
  validates :password, confirmation: true, if: -&amp;gt; { new_record? || changes[:crypted_password] }
  validates :password_confirmation, presence: true, if: -&amp;gt; { new_record? || changes[:crypted_password] }

  validates :email, uniqueness: true
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's finish up&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git status
git add -A
git commit -m "add sorcery sign up and auto login flow"
git checkout main
git merge sorcery-sign-up-feature
git branch -D sorcery-sign-up-feature
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Continue reading for my ramblings
&lt;/h2&gt;

&lt;p&gt;By the way I just wanted to point out that sweet &lt;code&gt;auto_login&lt;/code&gt; helper method Sorcery &lt;br&gt;
has to automatically log in your user. We slipped it into the create action to create&lt;br&gt;
a nice seamless way to log in a user. Sorcery has the option for user activation via a&lt;br&gt;
confirmation link as well if you wish to incorporate that.&lt;/p&gt;

&lt;p&gt;Next time we will create a way to sign out and actually hide pages from users not signed in. &lt;br&gt;
Right now you can see the dashboard page whether you are logged in or not but in our next &lt;br&gt;
test we'll focus on that. We'll also add a way to sign out, delete users, sign in, and show form errors. &lt;br&gt;
The form we made only works for registering accounts, not signing in existing ones. &lt;br&gt;
If you try using the form again you'll see in the server console that it doesn't let &lt;br&gt;
you move forward with the action because we set a validates uniqueness on email attributes.&lt;/p&gt;

&lt;p&gt;Speaking of attributes, you might have noticed the migration file Sorcery generated only had 3 &lt;br&gt;
attributes: email, salt, and crypted_password. If you are unsure about how we were able to fill in&lt;br&gt;
password and password_confirmation through the form then you might not be alone. This was done with&lt;br&gt;
something called "virtual attributes". The form attributes had values but they were not persisted into &lt;br&gt;
the database, the password the user wrote was encrypted and that was stored into the database. You never&lt;br&gt;
want to store plain passwords in a database. No-no.&lt;/p&gt;

&lt;p&gt;Hope you enjoyed the tutorial! This is the great thing about Sorcery, &lt;br&gt;
you are in control of your authentication flow and can add or remove as much or little as you like.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>rspec</category>
      <category>authentication</category>
      <category>sorcery</category>
    </item>
    <item>
      <title>Setup RSpec on a fresh Rails 7 project</title>
      <dc:creator>Adrian Valenzuela</dc:creator>
      <pubDate>Thu, 06 Jan 2022 22:13:32 +0000</pubDate>
      <link>https://dev.to/adrianvalenz/setup-rspec-on-a-fresh-rails-7-project-5gp</link>
      <guid>https://dev.to/adrianvalenz/setup-rspec-on-a-fresh-rails-7-project-5gp</guid>
      <description>&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@jonathanbean?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Jonathan Bean&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/blacksmith?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Installing RSpec, FactoryBot, Faker gems and configuring for testing environment. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Using Ruby 3.0.1 + Rails 7.0.0 at the time of writing this article&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's get right to it...&lt;/p&gt;

&lt;h2&gt;
  
  
  Start a fresh project
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails new projectname -d postgresql
cd projectname
git add -A
git commit -m "initial commit"

rails db:create
rails s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install gems
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout -b rspec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Gemfile add...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;group :development, :test do
  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
  gem "debug", platforms: %i[ mri mingw x64_mingw ]
  gem "rspec-rails"
  gem "factory_bot_rails"
  gem "faker"
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Back in terminal/command line...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bundle install
rails g rspec:install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure gems
&lt;/h2&gt;

&lt;p&gt;Create 'support' directory in 'spec' directory and create two files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spec/support/factory_bot.rb
spec/support/chrome.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then one file in the spec directory for factories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spec/factories.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure FactoryBot&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/support/factory_bot.rb

RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure driver&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/support/chrome.rb

RSpec.configure do |config|
  config.before(:each, type: :system) do
    if ENV["SHOW_BROWSER"] == "true"
      driven_by :selenium_chrome
    else
      driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400]
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Require support files in &lt;code&gt;rails_helper.rb&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/rails_helper.rb

require_relative 'support/factory_bot'
require_relative 'support/chrome'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you generate a User model (or any model) RSpec will generate a factory for you in your &lt;code&gt;factories.rb&lt;/code&gt; file.&lt;br&gt;
You can modify it to look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# spec/factories.rb

FactoryBot.define do
  factory(:user) do
    email { Faker::Internet.email }
    password { Faker::Internet.password }
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  it "should run a test" do...
&lt;/h2&gt;

&lt;p&gt;Run &lt;code&gt;rspec&lt;/code&gt; command in the terminal and you should see it run and output some green text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-&amp;gt; rspec
No examples found.

Finished in 0.00038 seconds (files took 0.94577 seconds to load)
0 examples, 0 failures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Finish up
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add -A
git commit -m "add rspec"
git checkout main
git merge rspec
git branch -D rspec
git push # assuming you have a repo online somewhere
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>rails</category>
      <category>rspec</category>
      <category>testing</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Time Based Greeting With React And Bridgetown</title>
      <dc:creator>Adrian Valenzuela</dc:creator>
      <pubDate>Wed, 10 Nov 2021 16:16:39 +0000</pubDate>
      <link>https://dev.to/adrianvalenz/time-based-greeting-with-react-and-bridgetown-4b42</link>
      <guid>https://dev.to/adrianvalenz/time-based-greeting-with-react-and-bridgetown-4b42</guid>
      <description>&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@elena_kuchko?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Elena Kuchko&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/fremont-bridge?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;React is a library that I have been wanting to implement into my Bridgetown site&lt;br&gt;
for quite some time now. Today we're going to configure React into Bridgetown,&lt;br&gt;
and optionally use a component to render a greeting to the users based &lt;br&gt;
on &lt;em&gt;their&lt;/em&gt; time of day.&lt;/p&gt;

&lt;p&gt;I'll be separating this tutorial into two sections. First section we'll get&lt;br&gt;
React running, second section we will add the fun little greeting script.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;At the time of writing this, I am running Bridgetown version 0.21.4.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Part 1: Configure React
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Overview of steps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install the packages via Yarn&lt;/li&gt;
&lt;li&gt;Update the webpack.config.js&lt;/li&gt;
&lt;li&gt;Create your component&lt;/li&gt;
&lt;li&gt;Ensure DOM is loaded before mounting component&lt;/li&gt;
&lt;li&gt;Add container to layout&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  1. Install the packages via Yarn
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;yarn add -D react react-dom&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Run this at the root of your project where the package.json file is located. The&lt;br&gt;
"-D" flag installs them as dev dependencies.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Update the webpack.config.js
&lt;/h3&gt;

&lt;p&gt;Place this code...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var esbuildLoader = config.module.rules.find(rule =&amp;gt; rule.use &amp;amp;&amp;amp; rule.use.loader == "esbuild-loader")
if (esbuildLoader) {
  esbuildLoader.use.options.loader = "jsx"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var config = require("./config/webpack.defaults.js")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and before this...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Don't&lt;/strong&gt; edit the "webpack.defaults.js" file because it can potentially be&lt;br&gt;
overriden when you upgrade Bridgetown to a newer version.&lt;/p&gt;

&lt;p&gt;The snippet looks through the module rules in the default config for a loader&lt;br&gt;
called "esbuild-loader" and if it is there then we have the loader use JSX.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Create your component
&lt;/h3&gt;

&lt;p&gt;Create a folder "components" in your javascript directory. Here you will keep&lt;br&gt;
all of your React compononents that will be imported into index.js.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;./frontend/javascript/components&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create a file called &lt;code&gt;HelloWorld.js&lt;/code&gt; and add the following code...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# in ./frontend/javascript/components/HelloWorld.js

import React from "react"
import ReactDOM from "react-dom"

export const HelloWorld = () =&amp;gt; {
  const hello = "Hello"

  return &amp;lt;p&amp;gt;{hello} World!&amp;lt;/p&amp;gt;
}

export const renderInDOM = () =&amp;gt; {
  console.log("about to render!")
  ReactDOM.render(&amp;lt;HelloWorld /&amp;gt;, document.querySelector("#root"))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Ensure DOM is loaded before mounting component
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# This snippet goes in your `./frontend/javascript/index.js`

import { renderInDOM } from "./components/HelloWorld"

window.addEventListener("DOMContentLoaded", () =&amp;gt; {
  renderInDOM()
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we are importing the &lt;code&gt;renderInDOM&lt;/code&gt; function from the component file and&lt;br&gt;
using an event listener to make sure the DOM is loaded so we have somewhere to&lt;br&gt;
render the component.&lt;/p&gt;

&lt;p&gt;Note: Thank you &lt;a href="https://twitter.com/jaredcwhite"&gt;@jaredcwhite&lt;/a&gt; for helping me&lt;br&gt;
with the webpack.config.js and import DOM snippet to make this happen!&lt;/p&gt;
&lt;h3&gt;
  
  
  Add your div to your layout
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div id="root"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Think about where you want to render your component. It could be in your layouts&lt;br&gt;
or pages, where ever you like. I put mine in my index page. &lt;/p&gt;

&lt;p&gt;There you have it! You should have a "Hello World!" rendering where you &lt;br&gt;
placed your div tag with the id of "root".&lt;/p&gt;
&lt;h2&gt;
  
  
  Part 2: Render a greeting based on time of day
&lt;/h2&gt;

&lt;p&gt;The following is is an example of a custom greeting that changes a string based&lt;br&gt;
on the time of day.&lt;/p&gt;
&lt;h3&gt;
  
  
  Overview of steps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create component for greeting users&lt;/li&gt;
&lt;li&gt;Import into index.js&lt;/li&gt;
&lt;li&gt;Apply html tag to template&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  1. Create component for greeting users
&lt;/h3&gt;

&lt;p&gt;Let's make another component called &lt;code&gt;Greeting.js&lt;/code&gt;. Place the following&lt;br&gt;
code inside of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# In ./frontend/javascript/components/Greeting.js

import React from "react"
import ReactDOM from "react-dom"

export const Greeting = () =&amp;gt; {
    var myDate = new Date();
    var hours= myDate.getHours();
    var greet;

    if (hours &amp;lt; 12)
        greet =  "morning";
    else if (hours &amp;gt;= 12 &amp;amp;&amp;amp; hours &amp;lt;= 17)
        greet = "afternoon";
    else if (hours &amp;gt;= 17 &amp;amp;&amp;amp; hours &amp;lt;= 24)
        greet = "evening";

    return &amp;lt;span&amp;gt;Good {greet}!&amp;lt;/span&amp;gt;
}

export const renderGreeting = () =&amp;gt; {
    console.log("dynamic Greeting is rendering!")
    ReactDOM.render(&amp;lt;Greeting /&amp;gt;, document.querySelector("#greeting"))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript is perfect for this feature because it looks for the time of day&lt;br&gt;
based on the browser the user is viewing it on because it is client side&lt;br&gt;
scripting. If we used server side scripting then the time of day based on the&lt;br&gt;
server may not match up with the user viewing it in real time.&lt;/p&gt;

&lt;p&gt;So we make a new instance of the date, get the hours, and using if/else&lt;br&gt;
statements we determine which greeting to render based on the hour of the day.&lt;br&gt;
Then we return it via some JSX and Kablam! You have a customize time-based&lt;br&gt;
greeting.&lt;/p&gt;

&lt;p&gt;I really like how many of the new JavaScript frameworks encapusalate scripts&lt;br&gt;
into components for specific use-cases. Another awesome library that does this&lt;br&gt;
is &lt;a href="https://stimulus.hotwired.dev/"&gt;StimulusJS&lt;/a&gt;, but let's finish up and &lt;br&gt;
put the rest of the pieces together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Import into index.js
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# In ./frontend/javascript/index.js

import { renderGreeting } from "./components/Greeting"

window.addEventListener("DOMContentLoaded", () =&amp;gt; {
  renderGreeting()
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just like last time we import the function from the component and wait/listen&lt;br&gt;
for the DOM to finish loading the content so we have somewhere to render the&lt;br&gt;
greeting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Apply html tag to template
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div id="greeting"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where we want the greeting to appear depends on where we place the tag, so drop&lt;br&gt;
your tag where ever your heart desires my friend.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post originally appeared at &lt;a href="https://adrianvalenz.com"&gt;https://adrianvalenz.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bridgetown</category>
      <category>javascript</category>
      <category>react</category>
      <category>ruby</category>
    </item>
  </channel>
</rss>
