From f8bb1b4a5bc2548dd7798f2b334d8e5c653c96af Mon Sep 17 00:00:00 2001 From: Sergio-e <33036058+Sergio-e@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:44:38 -0600 Subject: [PATCH] Back-end profile improvements --- Gemfile | 3 -- app/controllers/profiles_controller.rb | 29 ++++++++++-------- app/models/profile.rb | 31 ++++++++++---------- app/models/user.rb | 22 +++++++------- app/views/main/index.html.erb | 1 + app/views/profiles/edit.html.erb | 29 +++++++++--------- app/views/profiles/show.html.erb | 3 +- db/migrate/20240628210301_create_profiles.rb | 4 ++- db/migrate/20240628211820_create_users.rb | 2 -- db/schema.rb | 6 ++-- db/seeds.rb | 13 ++++++++ spec/factories/profiles.rb | 26 ++++++++-------- spec/factories/users.rb | 14 ++++----- spec/models/profile_spec.rb | 26 ++++++++-------- spec/models/user_spec.rb | 14 ++++----- 15 files changed, 120 insertions(+), 103 deletions(-) diff --git a/Gemfile b/Gemfile index c5e2aa88..3bdde43b 100644 --- a/Gemfile +++ b/Gemfile @@ -21,9 +21,6 @@ gem "tailwindcss-rails", "~> 2.6" gem "stimulus-rails" gem "turbo-rails" -# Authorization -gem "action_policy", "~> 0.7.0" - # Authentication gem "bcrypt", "~> 3.1.20" diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 73bfa55b..d65d099a 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -1,30 +1,35 @@ class ProfilesController < ApplicationController def show - @profile = current_user.profile + @profile = current_profile end def edit - @profile = current_user.profile || Profile.new + @profile = current_profile end def update - if current_user.profile.nil? - current_user.profile = Profile.new(profile_params) - current_user.save! + @profile = current_profile + @profile.assign_attributes(profile_params) + + if @profile.save + redirect_to profile_path, notice: t("controllers.profiles.update.success") else - current_user.profile.update!(profile_params) + # TODO display errors + render :edit, status: :unprocessable_entity end - current_user.update!(notifications_params) - redirect_to profile_path, notice: t("controllers.profiles.update.success") end private - def profile_params - params.permit(:name, :location, :bio, :is_public, :twitter_url, :linkedin_url, :github_url, :image) + def current_profile + current_user.profile || current_user.build_profile end - def notifications_params - params.permit(:in_app_notifications_enabled, :mail_notifications_enabled) + def profile_params + params.require(:profile).permit( + :name, :location, :bio, :is_public, :image, + :twitter_url, :linkedin_url, :github_url, + :in_app_notifications, :mail_notifications + ) end end diff --git a/app/models/profile.rb b/app/models/profile.rb index 7194c3a9..df389ef0 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -2,29 +2,30 @@ # # Table name: profiles # -# id :integer not null, primary key -# bio :string -# github_url :string -# is_public :boolean default(FALSE), not null -# linkedin_url :string -# location :string -# name :string -# profileable_type :string not null -# twitter_url :string -# created_at :datetime not null -# updated_at :datetime not null -# profileable_id :integer not null +# id :integer not null, primary key +# bio :text +# github_url :string +# in_app_notifications :boolean default(TRUE), not null +# is_public :boolean default(FALSE), not null +# linkedin_url :string +# location :string +# mail_notifications :boolean default(TRUE), not null +# name :string +# profileable_type :string not null +# twitter_url :string +# created_at :datetime not null +# updated_at :datetime not null +# profileable_id :integer not null # # Indexes # # index_profiles_on_profileable (profileable_type,profileable_id) # class Profile < ApplicationRecord - belongs_to :profileable, polymorphic: true + has_one_attached :image - has_one :self_ref, class_name: "Profile", foreign_key: :id, inverse_of: :self_ref, dependent: :destroy has_one :user, through: :self_ref, source: :profileable, source_type: "User" has_one :speaker, through: :self_ref, source: :profileable, source_type: "Speaker" - has_one_attached :image + belongs_to :profileable, polymorphic: true end diff --git a/app/models/user.rb b/app/models/user.rb index 8b641a70..72cbddf6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2,14 +2,12 @@ # # Table name: users # -# id :integer not null, primary key -# email :string not null -# in_app_notifications_enabled :boolean default(TRUE), not null -# mail_notifications_enabled :boolean default(TRUE), not null -# password_digest :string not null -# role :string -# created_at :datetime not null -# updated_at :datetime not null +# id :integer not null, primary key +# email :string not null +# password_digest :string not null +# role :string +# created_at :datetime not null +# updated_at :datetime not null # # Indexes # @@ -20,6 +18,10 @@ class User < ApplicationRecord normalizes :email, with: ->(email) { email.strip.downcase } + generates_token_for :password_reset, expires_in: PASSWORD_RESET_EXPIRATION do + password_salt&.last(10) + end + has_secure_password has_one :profile, as: :profileable, dependent: :destroy @@ -30,7 +32,5 @@ class User < ApplicationRecord validates :password_digest, presence: true validates :password, length: {minimum: 8}, if: -> { password.present? } - generates_token_for :password_reset, expires_in: PASSWORD_RESET_EXPIRATION do - password_salt&.last(10) - end + after_create_commit { create_profile! } end diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb index bae11ff6..f2d623dc 100644 --- a/app/views/main/index.html.erb +++ b/app/views/main/index.html.erb @@ -1 +1,2 @@

Homepage

+<%= link_to "Profile", profile_path %> diff --git a/app/views/profiles/edit.html.erb b/app/views/profiles/edit.html.erb index f9fb0fd9..5e2dd7dd 100644 --- a/app/views/profiles/edit.html.erb +++ b/app/views/profiles/edit.html.erb @@ -1,7 +1,7 @@

Set up your account

- <%= form_with url: profile_path, class: "flex flex-col items-center", method: :put do |form| %> + <%= form_with url: profile_path, scope: :profile, class: "flex flex-col items-center", method: :put do |form| %> <%= form.label :image, data: {controller: "image-previewer", }, class: "overflow-hidden relative font-bold text-white text-base w-32 h-32 bg-white cursor-pointer rounded-full flex flex-col items-center justify-center" do %> <%= form.file_field :image, data: {image_previewer_target: "input"}, class: "text-white border-2 border-white bg-transparent rounded-sm hidden mb-6 focus:outline-none focus:outline-0 focus:ring-0 focus:border-2 focus:border-white active:border-2 active:border-white" %> <% if @profile.image.present? %> @@ -12,30 +12,31 @@ <%= image_tag "", data: {image_previewer_target: "image"}, class: "hidden absolute" %> <% end %> -
- <%= form.label :bio, class: "font-bold text-white text-base" %> - <%= form.text_area :bio, value: @profile.bio,class: "w-full text-white border-2 border-white bg-transparent rounded-sm mb-6 focus:outline-none focus:outline-0 focus:ring-0 focus:border-2 focus:border-white active:border-2 active:border-white" %> +
<%= form.label :name, class: "font-bold text-white text-base" %> - <%= form.text_field :name, value: @profile.name, class: "w-full text-white border-2 border-white bg-transparent rounded-sm mb-6 focus:outline-none focus:outline-0 focus:ring-0 focus:border-2 focus:border-white active:border-2 active:border-white" %> + <%= form.text_field :name, class: "w-full text-white border-2 border-white bg-transparent rounded-sm mb-6 focus:outline-none focus:outline-0 focus:ring-0 focus:border-2 focus:border-white active:border-2 active:border-white" %> + + <%= form.label :bio, class: "font-bold text-white text-base" %> + <%= form.text_area :bio, class: "w-full text-white border-2 border-white bg-transparent rounded-sm mb-6 focus:outline-none focus:outline-0 focus:ring-0 focus:border-2 focus:border-white active:border-2 active:border-white" %> <%= form.label :location, class: "font-bold text-white text-base" %> - <%= form.text_field :location, value: @profile.location, class: "w-full text-white border-2 border-white bg-transparent rounded-sm mb-6 focus:outline-none focus:outline-0 focus:ring-0 focus:border-2 focus:border-white active:border-2 active:border-white" %> + <%= form.text_field :location, class: "w-full text-white border-2 border-white bg-transparent rounded-sm mb-6 focus:outline-none focus:outline-0 focus:ring-0 focus:border-2 focus:border-white active:border-2 active:border-white" %> <%= form.label :github_url, class: "font-bold text-white text-base" %> - <%= form.text_field :github_url, value: @profile.github_url, class: "w-full text-white border-2 border-white bg-transparent rounded-sm mb-6 focus:outline-none focus:outline-0 focus:ring-0 focus:border-2 focus:border-white active:border-2 active:border-white" %> + <%= form.text_field :github_url, class: "w-full text-white border-2 border-white bg-transparent rounded-sm mb-6 focus:outline-none focus:outline-0 focus:ring-0 focus:border-2 focus:border-white active:border-2 active:border-white" %> <%= form.label :linkedin_url, class: "font-bold text-white text-base" %> - <%= form.text_field :linkedin_url, value: @profile.linkedin_url, class: "w-full text-white border-2 border-white bg-transparent rounded-sm mb-6 focus:outline-none focus:outline-0 focus:ring-0 focus:border-2 focus:border-white active:border-2 active:border-white" %> + <%= form.text_field :linkedin_url, class: "w-full text-white border-2 border-white bg-transparent rounded-sm mb-6 focus:outline-none focus:outline-0 focus:ring-0 focus:border-2 focus:border-white active:border-2 active:border-white" %> <%= form.label :twitter_url, class: "font-bold text-white text-base" %> - <%= form.text_field :twitter_url, value: @profile.twitter_url, class: "w-full text-white border-2 border-white bg-transparent rounded-sm mb-6 focus:outline-none focus:outline-0 focus:ring-0 focus:border-2 focus:border-white active:border-2 active:border-white" %> + <%= form.text_field :twitter_url, class: "w-full text-white border-2 border-white bg-transparent rounded-sm mb-6 focus:outline-none focus:outline-0 focus:ring-0 focus:border-2 focus:border-white active:border-2 active:border-white" %>

Discoverability

<%= form.label :is_public, "Public profile", class: "grow font-medium text-slate-900 text-base cursor-pointer mr-2" %>
@@ -44,16 +45,16 @@

Notifications

- <%= form.label :mail_notifications_enabled, "Mail Notifications", class: "grow font-medium text-slate-900 text-base cursor-pointer mr-2" %> + <%= form.label :mail_notifications, "Mail", class: "grow font-medium text-slate-900 text-base cursor-pointer mr-2" %>
- <%= form.label :in_app_notifications_enabled, "In app Notifications", class: "grow font-medium text-slate-900 text-base cursor-pointer mr-2" %> + <%= form.label :in_app_notifications, "In app", class: "grow font-medium text-slate-900 text-base cursor-pointer mr-2" %>
diff --git a/app/views/profiles/show.html.erb b/app/views/profiles/show.html.erb index b7d5e507..e038008c 100644 --- a/app/views/profiles/show.html.erb +++ b/app/views/profiles/show.html.erb @@ -1,4 +1,3 @@ -
@@ -30,6 +29,6 @@
- <%= link_to 'EDIT PROFILE', edit_profile_path, class: "w-full bg-white text-red-500 font-bold rounded-sm p-4 rounded-lg grow flex flex-row items-center justify-center" %> + <%= link_to 'EDIT PROFILE', edit_profile_path, class: "w-full bg-white text-red-500 font-bold rounded-sm p-4 rounded-lg grow flex flex-row items-center justify-center" %>
diff --git a/db/migrate/20240628210301_create_profiles.rb b/db/migrate/20240628210301_create_profiles.rb index c444d827..04052223 100644 --- a/db/migrate/20240628210301_create_profiles.rb +++ b/db/migrate/20240628210301_create_profiles.rb @@ -2,11 +2,13 @@ class CreateProfiles < ActiveRecord::Migration[7.1] def change create_table :profiles do |t| t.string :name - t.string :bio + t.text :bio t.string :location t.string :github_url t.string :linkedin_url t.string :twitter_url + t.boolean :mail_notifications, default: true, null: false + t.boolean :in_app_notifications, default: true, null: false t.boolean :is_public, default: false, null: false t.references :profileable, polymorphic: true, null: false diff --git a/db/migrate/20240628211820_create_users.rb b/db/migrate/20240628211820_create_users.rb index be93835d..4b835b5d 100644 --- a/db/migrate/20240628211820_create_users.rb +++ b/db/migrate/20240628211820_create_users.rb @@ -3,8 +3,6 @@ def change create_table :users do |t| t.string :email, null: false t.string :role - t.boolean :mail_notifications_enabled, default: true, null: false - t.boolean :in_app_notifications_enabled, default: true, null: false t.string :password_digest, null: false t.timestamps diff --git a/db/schema.rb b/db/schema.rb index 38d4510c..81791c27 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -99,11 +99,13 @@ create_table "profiles", force: :cascade do |t| t.string "name" - t.string "bio" + t.text "bio" t.string "location" t.string "github_url" t.string "linkedin_url" t.string "twitter_url" + t.boolean "mail_notifications", default: true, null: false + t.boolean "in_app_notifications", default: true, null: false t.boolean "is_public", default: false, null: false t.string "profileable_type", null: false t.integer "profileable_id", null: false @@ -127,8 +129,6 @@ create_table "users", force: :cascade do |t| t.string "email", null: false t.string "role" - t.boolean "mail_notifications_enabled", default: true, null: false - t.boolean "in_app_notifications_enabled", default: true, null: false t.string "password_digest", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false diff --git a/db/seeds.rb b/db/seeds.rb index 16de4ebb..e8a88a2c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -2,6 +2,19 @@ # Users user = User.create!(email: "dev@example.com", password: "foobar2024", password_confirmation: "foobar2024") +User.create!(email: "dev+1@example.com", password: "foobar2024", password_confirmation: "foobar2024") + +# Profiles +user.create_profile!( + name: "John Doe", + bio: "I'm a Ruby on Rails developer.", + is_public: true, + mail_notifications: true, + in_app_notifications: true, + github_url: "https://github.com/TelosLabs", + twitter_url: "https://x.com/teloslabs", + linkedin_url: "https://www.linkedin.com/company/telos-labs" +) # Tags Tag.create!(name: "Hotwire") diff --git a/spec/factories/profiles.rb b/spec/factories/profiles.rb index 4d36ec19..c7eb1602 100644 --- a/spec/factories/profiles.rb +++ b/spec/factories/profiles.rb @@ -2,18 +2,20 @@ # # Table name: profiles # -# id :integer not null, primary key -# bio :string -# github_url :string -# is_public :boolean default(FALSE), not null -# linkedin_url :string -# location :string -# name :string -# profileable_type :string not null -# twitter_url :string -# created_at :datetime not null -# updated_at :datetime not null -# profileable_id :integer not null +# id :integer not null, primary key +# bio :text +# github_url :string +# in_app_notifications :boolean default(TRUE), not null +# is_public :boolean default(FALSE), not null +# linkedin_url :string +# location :string +# mail_notifications :boolean default(TRUE), not null +# name :string +# profileable_type :string not null +# twitter_url :string +# created_at :datetime not null +# updated_at :datetime not null +# profileable_id :integer not null # # Indexes # diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 7f25f9e4..2d1d1d0a 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -2,14 +2,12 @@ # # Table name: users # -# id :integer not null, primary key -# email :string not null -# in_app_notifications_enabled :boolean default(TRUE), not null -# mail_notifications_enabled :boolean default(TRUE), not null -# password_digest :string not null -# role :string -# created_at :datetime not null -# updated_at :datetime not null +# id :integer not null, primary key +# email :string not null +# password_digest :string not null +# role :string +# created_at :datetime not null +# updated_at :datetime not null # # Indexes # diff --git a/spec/models/profile_spec.rb b/spec/models/profile_spec.rb index fe96c6cd..b8feb2fe 100644 --- a/spec/models/profile_spec.rb +++ b/spec/models/profile_spec.rb @@ -2,18 +2,20 @@ # # Table name: profiles # -# id :integer not null, primary key -# bio :string -# github_url :string -# is_public :boolean default(FALSE), not null -# linkedin_url :string -# location :string -# name :string -# profileable_type :string not null -# twitter_url :string -# created_at :datetime not null -# updated_at :datetime not null -# profileable_id :integer not null +# id :integer not null, primary key +# bio :text +# github_url :string +# in_app_notifications :boolean default(TRUE), not null +# is_public :boolean default(FALSE), not null +# linkedin_url :string +# location :string +# mail_notifications :boolean default(TRUE), not null +# name :string +# profileable_type :string not null +# twitter_url :string +# created_at :datetime not null +# updated_at :datetime not null +# profileable_id :integer not null # # Indexes # diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index db4430e7..3a217047 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -2,14 +2,12 @@ # # Table name: users # -# id :integer not null, primary key -# email :string not null -# in_app_notifications_enabled :boolean default(TRUE), not null -# mail_notifications_enabled :boolean default(TRUE), not null -# password_digest :string not null -# role :string -# created_at :datetime not null -# updated_at :datetime not null +# id :integer not null, primary key +# email :string not null +# password_digest :string not null +# role :string +# created_at :datetime not null +# updated_at :datetime not null # # Indexes #