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 %>
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/app/views/profiles/show.html.erb b/app/views/profiles/show.html.erb
index feacac86..30b54193 100644
--- a/app/views/profiles/show.html.erb
+++ b/app/views/profiles/show.html.erb
@@ -55,6 +55,7 @@
+ <%= render inline: @profile.svg_qr_code(module_size: 4) %>
<%= link_to 'Edit Profile', edit_profile_path, class: "text-red font-bold rounded-sm underline italic text-lg" %>
diff --git a/config/environments/development.rb b/config/environments/development.rb
index c5d02975..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
@@ -82,4 +84,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/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/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 ce6e82a3..71ad11f7 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -10,8 +10,9 @@
resource :registration, only: [:new, :create]
resource :session, only: [:new, :create, :destroy]
resource :password, only: [:edit, :update]
- resource :profile, only: [:edit, :update, :show]
resource :password_reset, only: [:new, :create, :edit, :update] do
get :post_submit
end
+ resources :profiles, only: [:show], param: :uuid
+ resource :profile, only: [:edit, :update]
end
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: [
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 42eee9a4..3790f247 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -111,7 +111,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..205f44d9
--- /dev/null
+++ b/spec/controllers/profiles_controller_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require "rails_helper"
+
+RSpec.describe ProfilesController, type: :controller do
+ let(:user) { create(:user, :with_profile) }
+ let(:profile) { user.profile }
+ let(:other_profile) { create(:profile, :with_user) }
+
+ before do
+ sign_in(user)
+ end
+
+ describe "GET #show" do
+ 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 public" do
+ before do
+ other_profile.update!(is_public: true)
+ end
+
+ 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
+end
diff --git a/spec/decorators/profile_decorator_spec.rb b/spec/decorators/profile_decorator_spec.rb
new file mode 100644
index 00000000..cb285cf2
--- /dev/null
+++ b/spec/decorators/profile_decorator_spec.rb
@@ -0,0 +1,11 @@
+require "rails_helper"
+
+RSpec.describe ProfileDecorator do
+ let(:profile) { create(:profile, :with_user).decorate }
+
+ describe "#svg_qr_code" do
+ it "generates a QR code SVG" do
+ expect(profile.svg_qr_code).to include("