Skip to content

Lesson 3 — Sign up

The authentication generator handles sign in and password reset but not sign up. A simple RegistrationsController covers this.

Views::Registrations::New

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# app/views/registrations/new.rb
class Views::Registrations::New < Views::Base
  prop :user, ::User

  def page_title = "Create your account"

  def around_template
    render Views::Layouts::AuthLayout.new(title: page_title) do
      view_template
    end
  end
  
  def view_template
    div(class: "flex items-center justify-center min-h-screen px-4") do
      div(class: "w-full max-w-md") do
        div(class: "bg-surface rounded-lg border border-border p-8 shadow-sm") do
          h1(class: "text-xl font-bold text-text mb-6") do
            plain "Create your account"
          end

          form_with(model: @user, url: registration_path,
                    class: "space-y-4") do |f|
            TextInput(
              form:        f,
              field:       :name,
              label:       "Your name",
              value:       @user.name.to_s,
              placeholder: "Alice Smith",
              error:       @user.errors[:name].first
            )

            TextInput(
              form:        f,
              field:       :email_address,
              label:       "Email address",
              type:        "email",
              value:       @user.email_address.to_s,
              placeholder: "you@example.com",
              error:       @user.errors[:email_address].first
            )

            TextInput(
              form:        f,
              field:       :password,
              label:       "Password",
              type:        "password",
              error:       @user.errors[:password].first
            )

            TextInput(
              form:        f,
              field:       :password_confirmation,
              label:       "Confirm password",
              type:        "password"
            )

            Button(label: "Create account", type: "submit")
          end

          div(class: "mt-6 text-center text-sm text-text-muted") do
            plain "Already have an account? "
            a(href: new_session_path,
              class: "text-primary hover:text-primary-hover") do
              plain "Sign in"
            end
          end
        end
      end
    end
  end
end

RegistrationsController

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# app/controllers/registrations_controller.rb
class RegistrationsController < ApplicationController
  allow_unauthenticated_access

  def new
    render Views::Registrations::New.new(user: User.new)
  end

  def create
    user = User.new(registration_params)
    if user.save
      start_new_session_for(user)
      redirect_to boards_path, notice: "Welcome to KanbanFlow!"
    else
      render Views::Registrations::New.new(user: user),
             status: :unprocessable_entity
    end
  end

  private

  def registration_params
    params.expect(user: [:name, :email_address, :password,
                         :password_confirmation])
  end
end

Routes

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# config/routes.rb
Rails.application.routes.draw do
  if Rails.env.development?
    mount Lookbook::Engine, at: "/lookbook"
  end

   # Auth — must allow unauthenticated access
  resource :session
  resources :passwords, param: :token
  resource  :registration, only: [:new, :create]

  # Position endpoints before shallow resources
  namespace :cards   do resource :positions, only: [:update] end
  namespace :columns do resource :positions, only: [:update] end

  resources :boards do
    resources :columns, shallow: true,
                        only: [:create, :update, :destroy] do
      resources :cards, shallow: true,
                        only: [:create, :update, :destroy]
    end
  end

  mount ActionCable.server => "/cable"
  root "boards#index"
end