From 9fac43f46d057a8d69c45c15b245e152aca2aa84 Mon Sep 17 00:00:00 2001 From: songtianlun Date: Tue, 31 Dec 2024 16:34:52 +0800 Subject: [PATCH] feat: add user registration functionality - Implement user creation in UsersController - Add user registration form in new.html.erb - Create error messages partial for form validation - Add gravatar helper for user profile - Update routes to include resources for users - Introduce integration tests for signup validation This commit establishes the foundation for user registration, allowing users to sign up with their details and providing feedback on form errors. It enhances the user experience by integrating visual elements like gravatars and error messages. --- app/assets/stylesheets/application.scss | 3 +- app/assets/stylesheets/custom.scss | 93 ++++++++++++++++++++++- app/controllers/users_controller.rb | 24 ++++++ app/helpers/users_helper.rb | 5 ++ app/views/layouts/application.html.erb | 9 ++- app/views/shared/_error_messages.html.erb | 12 +++ app/views/users/new.html.erb | 23 +++++- app/views/users/show.html.erb | 12 +++ config/routes.rb | 15 ++-- test/integration/users_signup_test.rb | 29 +++++++ 10 files changed, 212 insertions(+), 13 deletions(-) create mode 100644 app/views/shared/_error_messages.html.erb create mode 100644 app/views/users/show.html.erb create mode 100644 test/integration/users_signup_test.rb diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 7142317..41dcaa3 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -13,6 +13,5 @@ *= require_self */ -@import "bootstrap-sprockets"; -@import "bootstrap"; + diff --git a/app/assets/stylesheets/custom.scss b/app/assets/stylesheets/custom.scss index ef00b8b..a8516db 100644 --- a/app/assets/stylesheets/custom.scss +++ b/app/assets/stylesheets/custom.scss @@ -1,3 +1,7 @@ +@import "bootstrap-sprockets"; +@import "bootstrap"; + + /* color */ $light-gray: #777; @@ -60,9 +64,9 @@ p { } } -img { - display: none; -} +//img { +// display: none; +//} /* footer */ footer { @@ -89,3 +93,86 @@ footer { } } +/* mixins, variables, etc. */ +$gray-medium-light: #eaeaea; + +@mixin box_sizing { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +/* miscellaneous */ +.debug_dump { + clear: both; + float: left; + width: 100%; + margin-top: 45px; + @include box-sizing; +} + +/* sidebar */ +aside { + section.user_info { + margin-top: 20px; + } + section { + padding: 10px 0; + margin-top: 20px; + &:first-child { + border: 0; + padding-top: 0; + } + span{ + display: block; + margin-bottom: 3px; + line-height: 1; + } + h1 { + font-size: 1.4em; + text-align: left; + letter-spacing: -1px; + margin-bottom: 3px; + margin-top: 0; + } + } +} + +.gravatar { + float: left; + margin-right: 10px; +} + +.gravatar_edit { + margin-top: 15px; +} + +/* forms */ +input, textarea, select, .uneditable-input { + border: 1px solid #bbb; + width: 100%; + margin-bottom: 15px; + @include box_sizing; +} + +input { + height: auto !important; +} + +/* forms */ + +#error_explanation { + color: red; + ul { + color: red; + margin: 0 0 30px 0; + } +} + +.field_with_errors { + @extend .has-error; + .form-control { + color: $state-danger-text; + } +} + diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 2ec9ecc..367fdd3 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,4 +1,28 @@ class UsersController < ApplicationController + def show + @user = User.find(params[:id]) + # debugger + end def new + @user = User.new + # debugger + end + + def create + @user = User.new(user_params) + if @user.save + flash[:success] = "Welcome to the Sample App!" + redirect_to @user + # redirect_to user_url(@user) + else + render 'new' + end + end + + private + + def user_params + params.require(:user).permit(:name, :email, :password, + :password_confirmation) end end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 2310a24..513ce46 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -1,2 +1,7 @@ module UsersHelper + def gravatar_for(user, size: 80) + gravatar_id = Digest::MD5.hexdigest(user.email.downcase) + gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}" + image_tag(gravatar_url, alt: user.name, class: "gravatar") + end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 6d1dfe5..300c47b 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,5 +1,5 @@ - + <%= full_title(yield(:title)) %> @@ -10,8 +10,15 @@ <%= render 'layouts/header' %>
+ <% flash.each do |message_type, message| %> + <%= content_tag(:div, message, class: "alert alert-#{message_type}") %> + + <% end %> <%= yield %> <%= render 'layouts/footer' %> + <%#= debug(params) if Rails.env.development? %> + <%= debug(params.to_yaml) if Rails.env.development? %> + <%= debug(Time.now) if Rails.env.development? %>
diff --git a/app/views/shared/_error_messages.html.erb b/app/views/shared/_error_messages.html.erb new file mode 100644 index 0000000..634c203 --- /dev/null +++ b/app/views/shared/_error_messages.html.erb @@ -0,0 +1,12 @@ +<% if @user.errors.any? %> +
+
+ The form contains <%= pluralize(@user.errors.count, "error") %>. +
+ +
+<% end %> \ No newline at end of file diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb index 9c841e8..94fdcfd 100644 --- a/app/views/users/new.html.erb +++ b/app/views/users/new.html.erb @@ -1,3 +1,24 @@ <% provide(:title, 'Sign up') %>

Sign up

-

This will be a signup page for new users.

+ +
+
+ <%= form_with(model: @user, local: true) do |f| %> + <%= render 'shared/error_messages' %> + + <%= f.label :name %> + <%= f.text_field :name, class: 'form-control' %> + + <%= f.label :email %> + <%= f.email_field :email, class: 'form-control' %> + + <%= f.label :password %> + <%= f.password_field :password, class: 'form-control' %> + + <%= f.label :password_confirmation, "Confirmation" %> + <%= f.password_field :password_confirmation, class: 'form-control' %> + + <%= f.submit "Create my account", class: "btn, btn-primary" %> + <% end %> +
+
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb new file mode 100644 index 0000000..f5e278c --- /dev/null +++ b/app/views/users/show.html.erb @@ -0,0 +1,12 @@ +<%provide(:title, @user.name) %> + +
+ +
diff --git a/config/routes.rb b/config/routes.rb index 6f6cf03..c8ac7c6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,16 +1,19 @@ Rails.application.routes.draw do - get "users/new" - get "static_pages/home" - get "static_pages/help" - get "static_pages/about" - get "static_pages/contact" + # get "users/new" + # get "static_pages/home" + # get "static_pages/help" + # get "static_pages/about" + # get "static_pages/contact" + + root "static_pages#home" get '/help', to: 'static_pages#help' get '/about', to: 'static_pages#about' get '/contact', to: 'static_pages#contact' get '/signup', to: 'users#new' - root "static_pages#home" + resources :users + # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. diff --git a/test/integration/users_signup_test.rb b/test/integration/users_signup_test.rb new file mode 100644 index 0000000..f18a70b --- /dev/null +++ b/test/integration/users_signup_test.rb @@ -0,0 +1,29 @@ +require "test_helper" + +class UsersSignupTest < ActionDispatch::IntegrationTest + test "invalid signup information" do + get signup_path + assert_no_difference 'User.count' do + post users_path, params: { user: { name: "", + email: "user@invalid", + password: "foo", + password_confirmation: "bar" } } + end + assert_template 'users/new' + assert_select 'div#error_explanation' + assert_select 'div.alert-danger' + end + + test "valid signup information" do + get signup_path + assert_difference 'User.count', 1 do + post users_path, params: { user: {name: "Example User", + email: "user@example.com", + password: "password", + password_confirmation: "password" } } + end + follow_redirect! + assert_template 'users/show' + assert_not flash.notice + end +end