From 8d6105aed0c36f2e9bc2e1158dae02e432637c29 Mon Sep 17 00:00:00 2001 From: Andres Alvidrez Date: Mon, 15 Jul 2024 16:32:28 -0600 Subject: [PATCH 01/21] Add QR Code generation and sharing --- Gemfile | 3 ++ Gemfile.lock | 6 ++++ app/controllers/application_controller.rb | 8 +++++ app/controllers/profiles_controller.rb | 23 ++++++++++++ app/helpers/profile_helper.rb | 9 +++++ app/javascript/controllers/qr_controller.js | 25 +++++++++++++ app/lib/qr_code_generator.rb | 21 +++++++++++ app/models/profile.rb | 14 ++++++++ app/views/profiles/show.html.erb | 23 ++++++++++++ config/environments/development.rb | 3 ++ config/initializers/inflections.rb | 6 ++-- config/routes.rb | 7 ++++ ...40710213305_add_profile_uuid_to_profile.rb | 6 ++++ db/schema.rb | 4 ++- spec/controllers/profiles_controller_spec.rb | 35 +++++++++++++++++++ spec/factories/profiles.rb | 7 ++++ spec/helpers/profile_helper_spec.rb | 13 +++++++ spec/lib/qr_code_generator_spec.rb | 19 ++++++++++ spec/models/profile_spec.rb | 11 ++++++ 19 files changed, 239 insertions(+), 4 deletions(-) create mode 100644 app/controllers/profiles_controller.rb create mode 100644 app/helpers/profile_helper.rb create mode 100644 app/javascript/controllers/qr_controller.js create mode 100644 app/lib/qr_code_generator.rb create mode 100644 app/views/profiles/show.html.erb create mode 100644 db/migrate/20240710213305_add_profile_uuid_to_profile.rb create mode 100644 spec/controllers/profiles_controller_spec.rb create mode 100644 spec/helpers/profile_helper_spec.rb create mode 100644 spec/lib/qr_code_generator_spec.rb diff --git a/Gemfile b/Gemfile index 0d5e9e97..c9ee127a 100644 --- a/Gemfile +++ b/Gemfile @@ -27,6 +27,9 @@ gem "action_policy", "~> 0.7.0" # Authentication gem "bcrypt", "~> 3.1.20" +# QR code +gem "rqrcode", "~> 2.0" + # Other gem "bootsnap", require: false gem "inline_svg" diff --git a/Gemfile.lock b/Gemfile.lock index 727505a6..fd0a49fa 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -128,6 +128,7 @@ GEM regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) childprocess (5.0.0) + chunky_png (1.4.0) coderay (1.1.3) coercible (1.0.0) descendants_tracker (~> 0.0.1) @@ -353,6 +354,10 @@ GEM rexml (3.3.2) strscan rouge (4.3.0) + rqrcode (2.2.0) + chunky_png (~> 1.0) + rqrcode_core (~> 1.0) + rqrcode_core (1.2.0) rspec (3.13.0) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) @@ -526,6 +531,7 @@ DEPENDENCIES rack-mini-profiler rails (~> 7.1.3, >= 7.1.3.4) rails-controller-testing + rqrcode (~> 2.0) rspec-instafail rspec-rails rspec-retry diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 361611fe..4a8b7d96 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,3 +1,11 @@ class ApplicationController < ActionController::Base include Authentication + + rescue_from ActiveRecord::RecordNotFound, with: :record_not_found + + private + + def record_not_found + render file: Rails.public_path.join("404.html").to_s, status: :not_found, layout: false + end end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb new file mode 100644 index 00000000..2f405fc1 --- /dev/null +++ b/app/controllers/profiles_controller.rb @@ -0,0 +1,23 @@ +class ProfilesController < ApplicationController + include ProfileHelper + + before_action :set_profile, only: [:show, :qr_code] + + def show + end + + def qr_code + send_data( + qr_code_png(@profile), + filename: "#{@profile.name}.png", + type: "image/png", + disposition: "attachment" + ) + end + + private + + def set_profile + @profile = Profile.public_profiles.find_by!(uuid: params[:uuid]) + end +end diff --git a/app/helpers/profile_helper.rb b/app/helpers/profile_helper.rb new file mode 100644 index 00000000..bd57eabe --- /dev/null +++ b/app/helpers/profile_helper.rb @@ -0,0 +1,9 @@ +module ProfileHelper + def qr_code_svg(profile) + QRCodeGenerator.new(profile_url(profile.uuid)).as_svg(module_size: 4) + end + + def qr_code_png(profile) + QRCodeGenerator.new(profile_url(profile.uuid)).as_png(size: 240) + end +end diff --git a/app/javascript/controllers/qr_controller.js b/app/javascript/controllers/qr_controller.js new file mode 100644 index 00000000..9892808d --- /dev/null +++ b/app/javascript/controllers/qr_controller.js @@ -0,0 +1,25 @@ +import { Controller } from '@hotwired/stimulus' + +export default class extends Controller { + static targets = ['button'] + + async share () { + const button = this.buttonTarget + + if (navigator.share) { + try { + const file = await fetch(button.dataset.url) + .then((response) => response.blob()) + .then((blob) => new File([blob], 'qr.png', { type: 'image/png' })) + + await navigator.share({ + files: [file], title: 'QR Code' + }) + } catch (err) { + window.open(button.dataset.url) + } + } else { + window.open(button.dataset.url) + } + } +} diff --git a/app/lib/qr_code_generator.rb b/app/lib/qr_code_generator.rb new file mode 100644 index 00000000..58f908d7 --- /dev/null +++ b/app/lib/qr_code_generator.rb @@ -0,0 +1,21 @@ +class QRCodeGenerator + def initialize(url) + @url = url + end + + def as_svg(options = {}) + qr.as_svg(options) + end + + def as_png(options = {}) + qr.as_png(options) + end + + private + + attr_reader :url + + def qr + @_qr ||= RQRCode::QRCode.new(url) + end +end diff --git a/app/models/profile.rb b/app/models/profile.rb index 4ef54974..b9025311 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -11,6 +11,7 @@ # name :string # profileable_type :string not null # twitter_url :string +# uuid :string # created_at :datetime not null # updated_at :datetime not null # profileable_id :integer not null @@ -18,6 +19,7 @@ # Indexes # # index_profiles_on_profileable (profileable_type,profileable_id) +# index_profiles_on_uuid (uuid) UNIQUE # class Profile < ApplicationRecord belongs_to :profileable, polymorphic: true @@ -25,4 +27,16 @@ class Profile < ApplicationRecord 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" + + validates :uuid, uniqueness: true + + before_create :set_uuid + + scope :public_profiles, -> { where(is_public: true) } + + private + + def set_uuid + self.uuid = SecureRandom.uuid + end end diff --git a/app/views/profiles/show.html.erb b/app/views/profiles/show.html.erb new file mode 100644 index 00000000..59b7d299 --- /dev/null +++ b/app/views/profiles/show.html.erb @@ -0,0 +1,23 @@ +

Profile

+ +

My QR Code

+ +<%= render inline: qr_code_svg(@profile) %> +
+ + +<%= link_to 'Save QR Code', qr_code_profile_path(@profile.uuid), method: :get %> +
+
+ + +
+ +
+
+ + +

Scan a code

+ diff --git a/config/environments/development.rb b/config/environments/development.rb index c5d02975..3c7038f5 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -82,4 +82,7 @@ # Raise error when a before_action's only/except options reference missing actions config.action_controller.raise_on_missing_callback_actions = true + + # Allow ngrok hosts + config.hosts << /[a-z0-9.\-]+\.ngrok\.io/ end diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 3860f659..435cf643 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -11,6 +11,6 @@ # end # These inflection rules are supported but not enabled by default: -# ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.acronym "RESTful" -# end +ActiveSupport::Inflector.inflections(:en) do |inflect| + inflect.acronym "QR" +end diff --git a/config/routes.rb b/config/routes.rb index 972ff602..137374a6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,7 +9,14 @@ resource :registration, only: [:new, :create] resource :session, only: [:new, :create, :destroy] resource :password, only: [:edit, :update] + resource :password_reset, only: [:new, :create, :edit, :update] do get :post_submit + end + resource :password_reset, only: [:new, :create, :edit, :update] + resources :profiles, only: [:show, :edit, :update], param: :uuid do + member do + get :qr_code + end end end diff --git a/db/migrate/20240710213305_add_profile_uuid_to_profile.rb b/db/migrate/20240710213305_add_profile_uuid_to_profile.rb new file mode 100644 index 00000000..40f2d070 --- /dev/null +++ b/db/migrate/20240710213305_add_profile_uuid_to_profile.rb @@ -0,0 +1,6 @@ +class AddProfileUuidToProfile < ActiveRecord::Migration[7.1] + def change + add_column :profiles, :uuid, :string + add_index :profiles, :uuid, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index d7c97655..df2d13e1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_06_28_211903) do +ActiveRecord::Schema[7.1].define(version: 2024_07_10_213305) do create_table "conferences", force: :cascade do |t| t.string "name", null: false t.datetime "created_at", null: false @@ -81,7 +81,9 @@ t.integer "profileable_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "uuid" t.index ["profileable_type", "profileable_id"], name: "index_profiles_on_profileable" + t.index ["uuid"], name: "index_profiles_on_uuid", unique: true end create_table "speakers", force: :cascade do |t| diff --git a/spec/controllers/profiles_controller_spec.rb b/spec/controllers/profiles_controller_spec.rb new file mode 100644 index 00000000..9ee040b6 --- /dev/null +++ b/spec/controllers/profiles_controller_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe ProfilesController, type: :controller do + let(:profile) { create(:profile, :with_user, :public) } + + before do + sign_in(profile.user) + end + + describe "GET #show" do + it "returns a success response" do + get :show, params: {uuid: profile.uuid} + expect(response).to have_http_status(:success) + end + + context "when the profile is not public" do + let(:profile) { create(:profile, :with_user, is_public: false) } + + it "returns a not found response" do + get :show, params: {uuid: profile.uuid} + expect(response).to have_http_status(:not_found) + end + end + end + + describe "GET #qr_code" do + it "returns a PNG" do + get :qr_code, params: {uuid: profile.uuid} + expect(response.headers["Content-Type"]).to eq("image/png") + expect(response.headers["Content-Disposition"]).to include("#{profile.name}.png") + end + end +end diff --git a/spec/factories/profiles.rb b/spec/factories/profiles.rb index 4d36ec19..d1eb1f59 100644 --- a/spec/factories/profiles.rb +++ b/spec/factories/profiles.rb @@ -11,6 +11,7 @@ # name :string # profileable_type :string not null # twitter_url :string +# uuid :string # created_at :datetime not null # updated_at :datetime not null # profileable_id :integer not null @@ -18,6 +19,7 @@ # Indexes # # index_profiles_on_profileable (profileable_type,profileable_id) +# index_profiles_on_uuid (uuid) UNIQUE # FactoryBot.define do factory :profile do @@ -28,9 +30,14 @@ github_url { "https://github.com" } linkedin_url { "https://linkedin.com" } twitter_url { "https://twitter.com" } + uuid { SecureRandom.uuid } trait :with_user do association :profileable, factory: :user end + + trait :public do + is_public { true } + end end end diff --git a/spec/helpers/profile_helper_spec.rb b/spec/helpers/profile_helper_spec.rb new file mode 100644 index 00000000..02748574 --- /dev/null +++ b/spec/helpers/profile_helper_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe ProfileHelper, type: :helper do + describe "#qr_code_svg" do + let(:profile) { create(:profile, :with_user) } + + it "generates a QR code SVG" do + expect(helper.qr_code_svg(profile)).to include(" Date: Sun, 21 Jul 2024 19:00:17 -0600 Subject: [PATCH 02/21] Restful QR Code route and refactor --- app/lib/qr_code_generator.rb | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 app/lib/qr_code_generator.rb diff --git a/app/lib/qr_code_generator.rb b/app/lib/qr_code_generator.rb deleted file mode 100644 index 58f908d7..00000000 --- a/app/lib/qr_code_generator.rb +++ /dev/null @@ -1,21 +0,0 @@ -class QRCodeGenerator - def initialize(url) - @url = url - end - - def as_svg(options = {}) - qr.as_svg(options) - end - - def as_png(options = {}) - qr.as_png(options) - end - - private - - attr_reader :url - - def qr - @_qr ||= RQRCode::QRCode.new(url) - end -end From f4b99bba1447ffb086258be485a1d4231f0f6724 Mon Sep 17 00:00:00 2001 From: Andres Alvidrez Date: Sun, 21 Jul 2024 19:00:29 -0600 Subject: [PATCH 03/21] Restful QR Code route and refactor --- app/controllers/profiles_controller.rb | 13 +------------ app/controllers/qr_codes_controller.rb | 20 ++++++++++++++++++++ app/helpers/profile_helper.rb | 4 ++-- app/models/profile.rb | 6 +++--- app/views/profiles/show.html.erb | 4 ++-- config/routes.rb | 4 +--- 6 files changed, 29 insertions(+), 22 deletions(-) create mode 100644 app/controllers/qr_codes_controller.rb diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 2f405fc1..73243071 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -1,20 +1,9 @@ class ProfilesController < ApplicationController - include ProfileHelper - - before_action :set_profile, only: [:show, :qr_code] + before_action :set_profile def show end - def qr_code - send_data( - qr_code_png(@profile), - filename: "#{@profile.name}.png", - type: "image/png", - disposition: "attachment" - ) - end - private def set_profile diff --git a/app/controllers/qr_codes_controller.rb b/app/controllers/qr_codes_controller.rb new file mode 100644 index 00000000..e29f89db --- /dev/null +++ b/app/controllers/qr_codes_controller.rb @@ -0,0 +1,20 @@ +class QRCodesController < ApplicationController + include ProfileHelper + + before_action :set_profile + + def show + send_data( + qr_code_png(@profile), + filename: "#{@profile.name}.png", + type: "image/png", + disposition: "attachment" + ) + end + + private + + def set_profile + @profile = Profile.public_profiles.find_by!(uuid: params[:profile_uuid]) + end +end diff --git a/app/helpers/profile_helper.rb b/app/helpers/profile_helper.rb index bd57eabe..924f904e 100644 --- a/app/helpers/profile_helper.rb +++ b/app/helpers/profile_helper.rb @@ -1,9 +1,9 @@ module ProfileHelper def qr_code_svg(profile) - QRCodeGenerator.new(profile_url(profile.uuid)).as_svg(module_size: 4) + RQRCode::QRCode.new(profile_url(profile.uuid)).as_svg(module_size: 4) end def qr_code_png(profile) - QRCodeGenerator.new(profile_url(profile.uuid)).as_png(size: 240) + RQRCode::QRCode.new(profile_url(profile.uuid)).as_png(size: 240) end end diff --git a/app/models/profile.rb b/app/models/profile.rb index b9025311..1170ce68 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -28,15 +28,15 @@ class Profile < ApplicationRecord has_one :user, through: :self_ref, source: :profileable, source_type: "User" has_one :speaker, through: :self_ref, source: :profileable, source_type: "Speaker" - validates :uuid, uniqueness: true + validates :uuid, uniqueness: true, presence: true - before_create :set_uuid + before_validation :set_uuid scope :public_profiles, -> { where(is_public: true) } private def set_uuid - self.uuid = SecureRandom.uuid + self.uuid ||= SecureRandom.uuid end end diff --git a/app/views/profiles/show.html.erb b/app/views/profiles/show.html.erb index 59b7d299..3feb6a4e 100644 --- a/app/views/profiles/show.html.erb +++ b/app/views/profiles/show.html.erb @@ -6,13 +6,13 @@
-<%= link_to 'Save QR Code', qr_code_profile_path(@profile.uuid), method: :get %> +<%= link_to 'Save QR Code', profile_qr_code_path(@profile.uuid), method: :get %>

-
diff --git a/config/routes.rb b/config/routes.rb index 137374a6..88a402b8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -15,8 +15,6 @@ end resource :password_reset, only: [:new, :create, :edit, :update] resources :profiles, only: [:show, :edit, :update], param: :uuid do - member do - get :qr_code - end + resource :qr_code, only: [:show] end end From a095ea07cac2f1581a8a923e036f42b447aec0a0 Mon Sep 17 00:00:00 2001 From: Andres Alvidrez Date: Mon, 22 Jul 2024 13:40:06 -0600 Subject: [PATCH 04/21] Fix QRCodesController spec and add spec for UUID validation --- app/models/profile.rb | 4 +++- spec/controllers/profiles_controller_spec.rb | 8 -------- spec/controllers/qr_codes_controller_spec.rb | 19 +++++++++++++++++++ spec/lib/qr_code_generator_spec.rb | 19 ------------------- spec/models/profile_spec.rb | 16 ++++++++++++++++ 5 files changed, 38 insertions(+), 28 deletions(-) create mode 100644 spec/controllers/qr_codes_controller_spec.rb delete mode 100644 spec/lib/qr_code_generator_spec.rb diff --git a/app/models/profile.rb b/app/models/profile.rb index 1170ce68..bf677edb 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -22,13 +22,15 @@ # index_profiles_on_uuid (uuid) UNIQUE # class Profile < ApplicationRecord + UUID_REGEX = /[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}/ + belongs_to :profileable, polymorphic: true 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" - validates :uuid, uniqueness: true, presence: true + validates :uuid, uniqueness: true, presence: true, format: {with: UUID_REGEX} before_validation :set_uuid diff --git a/spec/controllers/profiles_controller_spec.rb b/spec/controllers/profiles_controller_spec.rb index 9ee040b6..8acc8a79 100644 --- a/spec/controllers/profiles_controller_spec.rb +++ b/spec/controllers/profiles_controller_spec.rb @@ -24,12 +24,4 @@ end end end - - describe "GET #qr_code" do - it "returns a PNG" do - get :qr_code, params: {uuid: profile.uuid} - expect(response.headers["Content-Type"]).to eq("image/png") - expect(response.headers["Content-Disposition"]).to include("#{profile.name}.png") - end - end end diff --git a/spec/controllers/qr_codes_controller_spec.rb b/spec/controllers/qr_codes_controller_spec.rb new file mode 100644 index 00000000..5eac4c40 --- /dev/null +++ b/spec/controllers/qr_codes_controller_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe QRCodesController, type: :controller do + let(:profile) { create(:profile, :with_user, :public) } + + before do + sign_in(profile.user) + end + + describe "GET #show" do + it "returns a PNG" do + get :show, params: {profile_uuid: profile.uuid} + expect(response.headers["Content-Type"]).to eq("image/png") + expect(response.headers["Content-Disposition"]).to include("#{profile.name}.png") + end + end +end diff --git a/spec/lib/qr_code_generator_spec.rb b/spec/lib/qr_code_generator_spec.rb deleted file mode 100644 index d1f6dc86..00000000 --- a/spec/lib/qr_code_generator_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -require "rails_helper" - -RSpec.describe QRCodeGenerator do - let(:qr_code_generator) { described_class.new(Faker::Internet.url) } - - describe "#as_svg" do - it "returns an SVG" do - expect(qr_code_generator.as_svg).to include(" Date: Mon, 22 Jul 2024 15:51:10 -0600 Subject: [PATCH 05/21] rubocop --- app/models/profile.rb | 4 ++-- config/routes.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/profile.rb b/app/models/profile.rb index bf677edb..927d525d 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -22,7 +22,7 @@ # index_profiles_on_uuid (uuid) UNIQUE # class Profile < ApplicationRecord - UUID_REGEX = /[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}/ + UUID_REGEX = /\A[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\z/ belongs_to :profileable, polymorphic: true @@ -30,7 +30,7 @@ class Profile < ApplicationRecord has_one :user, through: :self_ref, source: :profileable, source_type: "User" has_one :speaker, through: :self_ref, source: :profileable, source_type: "Speaker" - validates :uuid, uniqueness: true, presence: true, format: {with: UUID_REGEX} + validates :uuid, uniqueness: true, format: {with: UUID_REGEX} before_validation :set_uuid diff --git a/config/routes.rb b/config/routes.rb index 88a402b8..9b60c7dd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -12,7 +12,7 @@ resource :password_reset, only: [:new, :create, :edit, :update] do get :post_submit - end + end resource :password_reset, only: [:new, :create, :edit, :update] resources :profiles, only: [:show, :edit, :update], param: :uuid do resource :qr_code, only: [:show] From 4a1c369e71bbf15febb2f3649497b974b541ab65 Mon Sep 17 00:00:00 2001 From: Andres Alvidrez Date: Tue, 23 Jul 2024 15:09:28 -0600 Subject: [PATCH 06/21] Refactor helper to decorator --- Gemfile | 1 + Gemfile.lock | 15 +++++++++++++++ app/controllers/profiles_controller.rb | 1 + app/controllers/qr_codes_controller.rb | 8 ++++---- app/decorators/profile_decorator.rb | 17 +++++++++++++++++ app/helpers/profile_helper.rb | 9 --------- app/models/profile.rb | 4 +--- app/views/profiles/show.html.erb | 4 ++-- config/environments/development.rb | 2 ++ config/environments/test.rb | 2 ++ config/routes.rb | 2 +- spec/controllers/qr_codes_controller_spec.rb | 2 +- spec/decorators/profile_decorator_spec.rb | 17 +++++++++++++++++ spec/helpers/profile_helper_spec.rb | 13 ------------- spec/models/profile_spec.rb | 16 ---------------- 15 files changed, 64 insertions(+), 49 deletions(-) create mode 100644 app/decorators/profile_decorator.rb delete mode 100644 app/helpers/profile_helper.rb create mode 100644 spec/decorators/profile_decorator_spec.rb delete mode 100644 spec/helpers/profile_helper_spec.rb diff --git a/Gemfile b/Gemfile index c9ee127a..8633bb1a 100644 --- a/Gemfile +++ b/Gemfile @@ -36,6 +36,7 @@ gem "inline_svg" gem "puma", ">= 5.0" gem "tzinfo-data", platforms: %i[windows jruby] gem "validates_timeliness", "~> 7.0.0.beta1" +gem "draper" group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem diff --git a/Gemfile.lock b/Gemfile.lock index fd0a49fa..5bfa709c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -57,6 +57,10 @@ GEM globalid (>= 0.3.6) activemodel (7.1.3.4) activesupport (= 7.1.3.4) + activemodel-serializers-xml (1.0.2) + activemodel (> 5.x) + activesupport (> 5.x) + builder (~> 3.1) activerecord (7.1.3.4) activemodel (= 7.1.3.4) activesupport (= 7.1.3.4) @@ -150,6 +154,13 @@ GEM diff-lcs (1.5.1) docile (1.4.0) dotenv (3.1.2) + draper (4.0.2) + actionpack (>= 5.0) + activemodel (>= 5.0) + activemodel-serializers-xml (>= 1.0) + activesupport (>= 5.0) + request_store (>= 1.0) + ruby2_keywords drb (2.2.1) dry-configurable (1.2.0) dry-core (~> 1.0, < 2) @@ -351,6 +362,8 @@ GEM regexp_parser (2.9.2) reline (0.5.9) io-console (~> 0.5) + request_store (1.7.0) + rack (>= 1.4) rexml (3.3.2) strscan rouge (4.3.0) @@ -413,6 +426,7 @@ GEM rubocop-rspec (~> 3, >= 3.0.1) ruby-next-core (1.0.3) ruby-progressbar (1.13.0) + ruby2_keywords (0.0.5) ruby_parser (3.21.0) racc (~> 1.5) sexp_processor (~> 4.16) @@ -517,6 +531,7 @@ DEPENDENCIES database_consistency debug dotenv + draper erb_lint factory_bot_rails faker diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 73243071..5b9f57ed 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -2,6 +2,7 @@ class ProfilesController < ApplicationController before_action :set_profile def show + @profile = @profile.decorate end private diff --git a/app/controllers/qr_codes_controller.rb b/app/controllers/qr_codes_controller.rb index e29f89db..e6250099 100644 --- a/app/controllers/qr_codes_controller.rb +++ b/app/controllers/qr_codes_controller.rb @@ -1,12 +1,12 @@ class QRCodesController < ApplicationController - include ProfileHelper - before_action :set_profile def show + @profile = @profile.decorate + send_data( - qr_code_png(@profile), - filename: "#{@profile.name}.png", + @profile.png_qr_code(size: 240), + filename: "qr.png", type: "image/png", disposition: "attachment" ) diff --git a/app/decorators/profile_decorator.rb b/app/decorators/profile_decorator.rb new file mode 100644 index 00000000..5282dc6a --- /dev/null +++ b/app/decorators/profile_decorator.rb @@ -0,0 +1,17 @@ +class ProfileDecorator < Draper::Decorator + delegate_all + + def svg_qr_code(options = {}) + RQRCode::QRCode.new(profile_url).as_svg(options) + end + + def png_qr_code(options = {}) + RQRCode::QRCode.new(profile_url).as_png(options) + end + + private + + def profile_url + Rails.application.routes.url_helpers.profile_url(object.uuid) + end +end diff --git a/app/helpers/profile_helper.rb b/app/helpers/profile_helper.rb deleted file mode 100644 index 924f904e..00000000 --- a/app/helpers/profile_helper.rb +++ /dev/null @@ -1,9 +0,0 @@ -module ProfileHelper - def qr_code_svg(profile) - RQRCode::QRCode.new(profile_url(profile.uuid)).as_svg(module_size: 4) - end - - def qr_code_png(profile) - RQRCode::QRCode.new(profile_url(profile.uuid)).as_png(size: 240) - end -end diff --git a/app/models/profile.rb b/app/models/profile.rb index 927d525d..1170ce68 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -22,15 +22,13 @@ # index_profiles_on_uuid (uuid) UNIQUE # class Profile < ApplicationRecord - UUID_REGEX = /\A[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\z/ - belongs_to :profileable, polymorphic: true 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" - validates :uuid, uniqueness: true, format: {with: UUID_REGEX} + validates :uuid, uniqueness: true, presence: true before_validation :set_uuid diff --git a/app/views/profiles/show.html.erb b/app/views/profiles/show.html.erb index 3feb6a4e..f3db253c 100644 --- a/app/views/profiles/show.html.erb +++ b/app/views/profiles/show.html.erb @@ -2,7 +2,7 @@

My QR Code

-<%= render inline: qr_code_svg(@profile) %> +<%= render inline: @profile.svg_qr_code(module_size: 4) %>
@@ -12,7 +12,7 @@
-
diff --git a/config/environments/development.rb b/config/environments/development.rb index 3c7038f5..4456214e 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -33,6 +33,8 @@ config.cache_store = :null_store end + Rails.application.routes.default_url_options[:host] = "localhost:3000" + # Store uploaded files on the local file system (see config/storage.yml for options). config.active_storage.service = :local diff --git a/config/environments/test.rb b/config/environments/test.rb index 3fb3f577..3db62bc4 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -34,6 +34,8 @@ # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false + Rails.application.routes.default_url_options[:host] = "localhost:3000" + # Store uploaded files on the local file system in a temporary directory. config.active_storage.service = :test diff --git a/config/routes.rb b/config/routes.rb index 9b60c7dd..a8bd9b18 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -13,7 +13,7 @@ resource :password_reset, only: [:new, :create, :edit, :update] do get :post_submit end - resource :password_reset, only: [:new, :create, :edit, :update] + resources :profiles, only: [:show, :edit, :update], param: :uuid do resource :qr_code, only: [:show] end diff --git a/spec/controllers/qr_codes_controller_spec.rb b/spec/controllers/qr_codes_controller_spec.rb index 5eac4c40..fd25315c 100644 --- a/spec/controllers/qr_codes_controller_spec.rb +++ b/spec/controllers/qr_codes_controller_spec.rb @@ -13,7 +13,7 @@ it "returns a PNG" do get :show, params: {profile_uuid: profile.uuid} expect(response.headers["Content-Type"]).to eq("image/png") - expect(response.headers["Content-Disposition"]).to include("#{profile.name}.png") + expect(response.headers["Content-Disposition"]).to include("qr.png") end end end diff --git a/spec/decorators/profile_decorator_spec.rb b/spec/decorators/profile_decorator_spec.rb new file mode 100644 index 00000000..60e4d014 --- /dev/null +++ b/spec/decorators/profile_decorator_spec.rb @@ -0,0 +1,17 @@ +require "rails_helper" + +RSpec.describe ProfileDecorator do + let(:profile) { create(:profile, :with_user) } + + describe "#svg_qr_code" do + it "generates a QR code SVG" do + expect(profile.svg_qr_code).to include(" Date: Tue, 23 Jul 2024 16:21:44 -0600 Subject: [PATCH 07/21] Fix Linter --- Gemfile | 2 +- spec/decorators/profile_decorator_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index 8633bb1a..0906e399 100644 --- a/Gemfile +++ b/Gemfile @@ -32,11 +32,11 @@ gem "rqrcode", "~> 2.0" # Other gem "bootsnap", require: false +gem "draper" gem "inline_svg" gem "puma", ">= 5.0" gem "tzinfo-data", platforms: %i[windows jruby] gem "validates_timeliness", "~> 7.0.0.beta1" -gem "draper" group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem diff --git a/spec/decorators/profile_decorator_spec.rb b/spec/decorators/profile_decorator_spec.rb index 60e4d014..50169e37 100644 --- a/spec/decorators/profile_decorator_spec.rb +++ b/spec/decorators/profile_decorator_spec.rb @@ -1,7 +1,7 @@ require "rails_helper" RSpec.describe ProfileDecorator do - let(:profile) { create(:profile, :with_user) } + let(:profile) { create(:profile, :with_user).decorate } describe "#svg_qr_code" do it "generates a QR code SVG" do From dafab436d52b408022e955a9efc3fd19c0e41afa Mon Sep 17 00:00:00 2001 From: Andres Alvidrez Date: Tue, 23 Jul 2024 16:42:03 -0600 Subject: [PATCH 08/21] Fix rubycritic --- app/models/profile.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/profile.rb b/app/models/profile.rb index 1170ce68..89793ad7 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -28,7 +28,7 @@ class Profile < ApplicationRecord has_one :user, through: :self_ref, source: :profileable, source_type: "User" has_one :speaker, through: :self_ref, source: :profileable, source_type: "Speaker" - validates :uuid, uniqueness: true, presence: true + validates :uuid, uniqueness: true before_validation :set_uuid From 982b049d5e55486d3d0568c9604760ae134b08ce Mon Sep 17 00:00:00 2001 From: Jose Fernando Davila Date: Wed, 24 Jul 2024 16:30:50 -0600 Subject: [PATCH 09/21] add profile uuid presence true validation --- .database_consistency.todo.yml | 3 +++ app/models/profile.rb | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.database_consistency.todo.yml b/.database_consistency.todo.yml index 4fcdc664..3436b2d2 100644 --- a/.database_consistency.todo.yml +++ b/.database_consistency.todo.yml @@ -3,3 +3,6 @@ Profile: self_ref: MissingIndexChecker: enabled: false + uuid: + ColumnPresenceChecker: + enabled: false \ No newline at end of file diff --git a/app/models/profile.rb b/app/models/profile.rb index 89793ad7..1170ce68 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -28,7 +28,7 @@ class Profile < ApplicationRecord has_one :user, through: :self_ref, source: :profileable, source_type: "User" has_one :speaker, through: :self_ref, source: :profileable, source_type: "Speaker" - validates :uuid, uniqueness: true + validates :uuid, uniqueness: true, presence: true before_validation :set_uuid From 9c9bf78edcdb60aa369140b9fb9e7a7a299fdad5 Mon Sep 17 00:00:00 2001 From: Jose Fernando Davila Date: Wed, 24 Jul 2024 16:35:45 -0600 Subject: [PATCH 10/21] remove duplicated gem --- Gemfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Gemfile b/Gemfile index b476fb30..d6586267 100644 --- a/Gemfile +++ b/Gemfile @@ -27,8 +27,6 @@ gem "action_policy", "~> 0.7.0" # Authentication gem "bcrypt", "~> 3.1.20" -# QR code -gem "rqrcode", "~> 2.0" # Admin gem "avo", ">= 3.2.1" From 2982977c8c6ce8ecce27cbafd3935111925054e5 Mon Sep 17 00:00:00 2001 From: Jose Fernando Davila Date: Wed, 24 Jul 2024 17:07:29 -0600 Subject: [PATCH 11/21] improvements --- app/javascript/controllers/qr_controller.js | 31 +++++++++++---------- app/views/profiles/show.html.erb | 2 +- config/routes.rb | 1 - 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/app/javascript/controllers/qr_controller.js b/app/javascript/controllers/qr_controller.js index 9892808d..e65a0795 100644 --- a/app/javascript/controllers/qr_controller.js +++ b/app/javascript/controllers/qr_controller.js @@ -3,23 +3,24 @@ import { Controller } from '@hotwired/stimulus' export default class extends Controller { static targets = ['button'] - async share () { - const button = this.buttonTarget + async share(event) { + const url = event.params.url; - if (navigator.share) { - try { - const file = await fetch(button.dataset.url) - .then((response) => response.blob()) - .then((blob) => new File([blob], 'qr.png', { type: 'image/png' })) + if (!navigator.share) { + window.open(url); + return; + } + + try { + const blob = (await fetch(url)).blob(); + const file = new File([blob], 'qr.png', { type: 'image/png' }); - await navigator.share({ - files: [file], title: 'QR Code' - }) - } catch (err) { - window.open(button.dataset.url) - } - } else { - window.open(button.dataset.url) + await navigator.share({ + files: [file], + title: 'QR Code' + }); + } catch (err) { + window.open(url); } } } diff --git a/app/views/profiles/show.html.erb b/app/views/profiles/show.html.erb index f3db253c..fce9ef22 100644 --- a/app/views/profiles/show.html.erb +++ b/app/views/profiles/show.html.erb @@ -12,7 +12,7 @@
-
diff --git a/config/routes.rb b/config/routes.rb index b20e221c..e45b9aca 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,7 +10,6 @@ resource :registration, only: [:new, :create] resource :session, only: [:new, :create, :destroy] resource :password, only: [:edit, :update] - resource :password_reset, only: [:new, :create, :edit, :update] do get :post_submit end From 857d8c9f6d4289ba56a2b36410955cbac1b32ad8 Mon Sep 17 00:00:00 2001 From: Andres Alvidrez Date: Thu, 25 Jul 2024 11:17:19 -0600 Subject: [PATCH 12/21] Remove QR code donwload and share option --- app/controllers/qr_codes_controller.rb | 20 ---------------- app/decorators/profile_decorator.rb | 4 ---- app/javascript/controllers/qr_controller.js | 25 -------------------- app/views/profiles/show.html.erb | 17 ------------- config/routes.rb | 4 +--- spec/controllers/qr_codes_controller_spec.rb | 19 --------------- spec/decorators/profile_decorator_spec.rb | 6 ----- 7 files changed, 1 insertion(+), 94 deletions(-) delete mode 100644 app/controllers/qr_codes_controller.rb delete mode 100644 app/javascript/controllers/qr_controller.js delete mode 100644 spec/controllers/qr_codes_controller_spec.rb diff --git a/app/controllers/qr_codes_controller.rb b/app/controllers/qr_codes_controller.rb deleted file mode 100644 index e6250099..00000000 --- a/app/controllers/qr_codes_controller.rb +++ /dev/null @@ -1,20 +0,0 @@ -class QRCodesController < ApplicationController - before_action :set_profile - - def show - @profile = @profile.decorate - - send_data( - @profile.png_qr_code(size: 240), - filename: "qr.png", - type: "image/png", - disposition: "attachment" - ) - end - - private - - def set_profile - @profile = Profile.public_profiles.find_by!(uuid: params[:profile_uuid]) - end -end diff --git a/app/decorators/profile_decorator.rb b/app/decorators/profile_decorator.rb index 5282dc6a..b40b701b 100644 --- a/app/decorators/profile_decorator.rb +++ b/app/decorators/profile_decorator.rb @@ -5,10 +5,6 @@ def svg_qr_code(options = {}) RQRCode::QRCode.new(profile_url).as_svg(options) end - def png_qr_code(options = {}) - RQRCode::QRCode.new(profile_url).as_png(options) - end - private def profile_url diff --git a/app/javascript/controllers/qr_controller.js b/app/javascript/controllers/qr_controller.js deleted file mode 100644 index 9892808d..00000000 --- a/app/javascript/controllers/qr_controller.js +++ /dev/null @@ -1,25 +0,0 @@ -import { Controller } from '@hotwired/stimulus' - -export default class extends Controller { - static targets = ['button'] - - async share () { - const button = this.buttonTarget - - if (navigator.share) { - try { - const file = await fetch(button.dataset.url) - .then((response) => response.blob()) - .then((blob) => new File([blob], 'qr.png', { type: 'image/png' })) - - await navigator.share({ - files: [file], title: 'QR Code' - }) - } catch (err) { - window.open(button.dataset.url) - } - } else { - window.open(button.dataset.url) - } - } -} diff --git a/app/views/profiles/show.html.erb b/app/views/profiles/show.html.erb index f3db253c..4b221530 100644 --- a/app/views/profiles/show.html.erb +++ b/app/views/profiles/show.html.erb @@ -4,20 +4,3 @@ <%= render inline: @profile.svg_qr_code(module_size: 4) %>
- - -<%= link_to 'Save QR Code', profile_qr_code_path(@profile.uuid), method: :get %> -
-
- - -
- -
-
- - -

Scan a code

- diff --git a/config/routes.rb b/config/routes.rb index a8bd9b18..2185dd82 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -14,7 +14,5 @@ get :post_submit end - resources :profiles, only: [:show, :edit, :update], param: :uuid do - resource :qr_code, only: [:show] - end + resources :profiles, only: [:show, :edit, :update], param: :uuid end diff --git a/spec/controllers/qr_codes_controller_spec.rb b/spec/controllers/qr_codes_controller_spec.rb deleted file mode 100644 index fd25315c..00000000 --- a/spec/controllers/qr_codes_controller_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -require "rails_helper" - -RSpec.describe QRCodesController, type: :controller do - let(:profile) { create(:profile, :with_user, :public) } - - before do - sign_in(profile.user) - end - - describe "GET #show" do - it "returns a PNG" do - get :show, params: {profile_uuid: profile.uuid} - expect(response.headers["Content-Type"]).to eq("image/png") - expect(response.headers["Content-Disposition"]).to include("qr.png") - end - end -end diff --git a/spec/decorators/profile_decorator_spec.rb b/spec/decorators/profile_decorator_spec.rb index 50169e37..cb285cf2 100644 --- a/spec/decorators/profile_decorator_spec.rb +++ b/spec/decorators/profile_decorator_spec.rb @@ -8,10 +8,4 @@ expect(profile.svg_qr_code).to include(" Date: Mon, 29 Jul 2024 09:57:48 -0600 Subject: [PATCH 13/21] Update profiles_controller.rb --- app/controllers/profiles_controller.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 3676c1a0..2e2778e0 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -5,10 +5,6 @@ def show @profile = @profile.decorate end - def new - @profile = current_user.build_profile - end - def edit @profile = current_profile end From b5590100c3303787cf1caf124371c13c92248345 Mon Sep 17 00:00:00 2001 From: Andres Alvidrez Date: Mon, 29 Jul 2024 10:00:08 -0600 Subject: [PATCH 14/21] Update profiles_controller.rb --- app/controllers/profiles_controller.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 2e2778e0..8de4d05a 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -9,16 +9,6 @@ def edit @profile = current_profile end - def create - @profile = current_user.build_profile(profile_params) - - if @profile.save - redirect_to profile_path, notice: t("controllers.profiles.create.success") - else - render :new, status: :unprocessable_entity - end - end - def update @profile = current_profile @profile.assign_attributes(profile_params) From f275e131ae9339818a5af3ca55145c629f94940d Mon Sep 17 00:00:00 2001 From: Andres Alvidrez Date: Mon, 29 Jul 2024 11:03:10 -0600 Subject: [PATCH 15/21] remove 404 redirect --- app/controllers/application_controller.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4a8b7d96..361611fe 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,11 +1,3 @@ class ApplicationController < ActionController::Base include Authentication - - rescue_from ActiveRecord::RecordNotFound, with: :record_not_found - - private - - def record_not_found - render file: Rails.public_path.join("404.html").to_s, status: :not_found, layout: false - end end From 400ec805731065d3872499acf5419d0840e2b434 Mon Sep 17 00:00:00 2001 From: Andres Alvidrez Date: Mon, 29 Jul 2024 21:23:42 -0600 Subject: [PATCH 16/21] fix routes and specs --- app/controllers/profiles_controller.rb | 7 ++++- config/routes.rb | 4 +-- spec/controllers/profiles_controller_spec.rb | 32 ++++++++++++++------ spec/factories/profiles.rb | 2 +- spec/factories/users.rb | 4 ++- 5 files changed, 33 insertions(+), 16 deletions(-) diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 8de4d05a..94de343e 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -24,7 +24,12 @@ def update private def set_profile - @profile = Profile.public_profiles.find_by!(uuid: params[:uuid]) + @profile = + if params[:uuid] == current_profile.uuid + current_profile + else + Profile.public_profiles.find_by!(uuid: params[:uuid]) + end end def current_profile diff --git a/config/routes.rb b/config/routes.rb index 28feacf6..0fbfbbce 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,10 +10,8 @@ resource :registration, only: [:new, :create] resource :session, only: [:new, :create, :destroy] resource :password, only: [:edit, :update] - resource :profile, only: [:edit, :update, :show] + resource :profile, only: [:show, :edit, :update], param: :uuid resource :password_reset, only: [:new, :create, :edit, :update] do get :post_submit end - - resources :profiles, only: [:show, :edit, :update], param: :uuid end diff --git a/spec/controllers/profiles_controller_spec.rb b/spec/controllers/profiles_controller_spec.rb index 8acc8a79..205f44d9 100644 --- a/spec/controllers/profiles_controller_spec.rb +++ b/spec/controllers/profiles_controller_spec.rb @@ -3,24 +3,36 @@ require "rails_helper" RSpec.describe ProfilesController, type: :controller do - let(:profile) { create(:profile, :with_user, :public) } + let(:user) { create(:user, :with_profile) } + let(:profile) { user.profile } + let(:other_profile) { create(:profile, :with_user) } before do - sign_in(profile.user) + sign_in(user) end describe "GET #show" do - it "returns a success response" do - get :show, params: {uuid: profile.uuid} - expect(response).to have_http_status(:success) + context "when the profile is yourself" do + it "returns a success response" do + get :show, params: {uuid: profile.uuid} + expect(response).to have_http_status(:success) + end end - context "when the profile is not public" do - let(:profile) { create(:profile, :with_user, is_public: false) } + context "when the profile is public" do + before do + other_profile.update!(is_public: true) + end - it "returns a not found response" do - get :show, params: {uuid: profile.uuid} - expect(response).to have_http_status(:not_found) + it "returns a success response" do + get :show, params: {uuid: other_profile.uuid} + expect(response).to have_http_status(:success) + end + end + + context "when the profile is not public" do + it "raises a RecordNotFound error" do + expect { get :show, params: {uuid: other_profile.uuid} }.to raise_error(ActiveRecord::RecordNotFound) end end end diff --git a/spec/factories/profiles.rb b/spec/factories/profiles.rb index 63706a66..0be3ae40 100644 --- a/spec/factories/profiles.rb +++ b/spec/factories/profiles.rb @@ -35,7 +35,7 @@ uuid { SecureRandom.uuid } trait :with_user do - association :profileable, factory: :user + profileable { create(:user) } end trait :public do diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 2d1d1d0a..862f9c36 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -19,7 +19,9 @@ password { "password2024" } trait :with_profile do - profile + after(:create) do |user| + create(:profile, profileable: user) + end end end end From 673e8cff0885597904a6894f6ecea7988c617a7c Mon Sep 17 00:00:00 2001 From: Andres Alvidrez Date: Mon, 29 Jul 2024 21:27:49 -0600 Subject: [PATCH 17/21] linter --- app/views/layouts/_flash_message.html.erb | 2 +- app/views/layouts/application.html.erb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/layouts/_flash_message.html.erb b/app/views/layouts/_flash_message.html.erb index dfdca38d..4496e81e 100644 --- a/app/views/layouts/_flash_message.html.erb +++ b/app/views/layouts/_flash_message.html.erb @@ -2,4 +2,4 @@
<%= message %>
- \ No newline at end of file + diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 55186fe5..d6d9c069 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -24,7 +24,7 @@ <% end %> <% flash.each do |type, message| %> <% if message.present? && message.is_a?(String) %> - <%= render partial: "layouts/flash_message", locals: { message: message }%> + <%= render partial: "layouts/flash_message", locals: { message: message } %> <% end %> <% end %> <%= yield %> From b83bbcafc366a97411d0eaaf80660cf9b5ee0cea Mon Sep 17 00:00:00 2001 From: Andres Alvidrez Date: Tue, 30 Jul 2024 11:04:06 -0600 Subject: [PATCH 18/21] Update routes.rb --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 0fbfbbce..1ffcddd5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,8 +10,8 @@ resource :registration, only: [:new, :create] resource :session, only: [:new, :create, :destroy] resource :password, only: [:edit, :update] - resource :profile, only: [:show, :edit, :update], param: :uuid resource :password_reset, only: [:new, :create, :edit, :update] do get :post_submit end + resources :profile, only: [:show, :edit, :update], param: :uuid end From 655a259e02ab766649fe8b04562502852bd4c5c7 Mon Sep 17 00:00:00 2001 From: Andres Alvidrez Date: Tue, 30 Jul 2024 11:11:45 -0600 Subject: [PATCH 19/21] Update routes.rb --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 1ffcddd5..d61cf920 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -13,5 +13,5 @@ resource :password_reset, only: [:new, :create, :edit, :update] do get :post_submit end - resources :profile, only: [:show, :edit, :update], param: :uuid + resource :profile, only: [:show, :edit, :update], param: :uuid end From 97926dc7a827239a9c4377e9eecad55eaba9250b Mon Sep 17 00:00:00 2001 From: Andres Alvidrez Date: Tue, 30 Jul 2024 11:22:19 -0600 Subject: [PATCH 20/21] Refactor profiles routes --- app/controllers/profiles_controller.rb | 2 +- app/models/user.rb | 2 ++ app/views/layouts/_bottom_navbar.html.erb | 4 ++-- app/views/main/index.html.erb | 2 +- config/routes.rb | 3 ++- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 94de343e..7df05e4c 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -15,7 +15,7 @@ def update if @profile.save remove_profile_image_if_requested - redirect_to profile_path, notice: t("controllers.profiles.update.success") + redirect_to profile_path(@profile.uuid), notice: t("controllers.profiles.update.success") else render :edit, status: :unprocessable_entity end diff --git a/app/models/user.rb b/app/models/user.rb index 13b65e45..5e81d33b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -36,6 +36,8 @@ class User < ApplicationRecord after_create_commit { create_profile! } + delegate :uuid, to: :profile, allow_nil: true + def self.ransackable_attributes(_auth_object = nil) %w[email] end diff --git a/app/views/layouts/_bottom_navbar.html.erb b/app/views/layouts/_bottom_navbar.html.erb index c8272f81..b9ee1cb6 100644 --- a/app/views/layouts/_bottom_navbar.html.erb +++ b/app/views/layouts/_bottom_navbar.html.erb @@ -7,8 +7,8 @@ <%= inline_svg_tag "clock.svg", class: nav_icon_class_for([root_path]) %> My Schedule - - <%= inline_svg_tag "avatar_no_fill.svg", class: nav_icon_class_for([profile_path, edit_profile_path]) %> + + <%= inline_svg_tag "avatar_no_fill.svg", class: nav_icon_class_for([profile_path(current_user.uuid), edit_profile_path]) %> Profile diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb index f2d623dc..1c27d579 100644 --- a/app/views/main/index.html.erb +++ b/app/views/main/index.html.erb @@ -1,2 +1,2 @@

Homepage

-<%= link_to "Profile", profile_path %> +<%= link_to "Profile", profile_path(current_user.uuid) %> diff --git a/config/routes.rb b/config/routes.rb index 1ffcddd5..71ad11f7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -13,5 +13,6 @@ resource :password_reset, only: [:new, :create, :edit, :update] do get :post_submit end - resources :profile, only: [:show, :edit, :update], param: :uuid + resources :profiles, only: [:show], param: :uuid + resource :profile, only: [:edit, :update] end From aa4d4737ae3c729c5a4bfc4e9b077069ed4fb328 Mon Sep 17 00:00:00 2001 From: LuigiR0jas Date: Tue, 30 Jul 2024 15:09:27 -0600 Subject: [PATCH 21/21] Standard js fix --- config/tailwind.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/tailwind.config.js b/config/tailwind.config.js index d55ac0b6..249f911a 100644 --- a/config/tailwind.config.js +++ b/config/tailwind.config.js @@ -10,7 +10,7 @@ module.exports = { theme: { extend: { boxShadow: { - 'simple': '0px 0px 25px 0px rgba(0, 0, 0, 0.50)' + simple: '0px 0px 25px 0px rgba(0, 0, 0, 0.50)' }, fontFamily: { sans: ['Roboto', ...defaultTheme.fontFamily.sans] @@ -31,7 +31,7 @@ module.exports = { blue: '#0A4E6B', 'green-dark': '#62C554', 'green-light': '#D8F1D4' - }, + } } }, plugins: [