Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add QR Code generation and sharing #50

Merged
merged 28 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8d6105a
Add QR Code generation and sharing
andresag4 Jul 15, 2024
b37f5c7
Restful QR Code route and refactor
andresag4 Jul 22, 2024
f4b99bb
Restful QR Code route and refactor
andresag4 Jul 22, 2024
a095ea0
Fix QRCodesController spec and add spec for UUID validation
andresag4 Jul 22, 2024
ff10a35
rubocop
andresag4 Jul 22, 2024
4a1c369
Refactor helper to decorator
andresag4 Jul 23, 2024
704adaf
Fix Linter
andresag4 Jul 23, 2024
dafab43
Fix rubycritic
andresag4 Jul 23, 2024
982b049
add profile uuid presence true validation
davilajose23 Jul 24, 2024
10a1f31
Merge branch 'main' into 22-qr-code-generation
davilajose23 Jul 24, 2024
9c9bf78
remove duplicated gem
davilajose23 Jul 24, 2024
2982977
improvements
davilajose23 Jul 24, 2024
857d8c9
Remove QR code donwload and share option
andresag4 Jul 25, 2024
44259b9
Merge branch '22-qr-code-generation' of github.com:TelosLabs/rails-wo…
andresag4 Jul 25, 2024
0520637
Merge branch 'main' into 22-qr-code-generation
andresag4 Jul 26, 2024
45ba119
Update profiles_controller.rb
andresag4 Jul 29, 2024
b559010
Update profiles_controller.rb
andresag4 Jul 29, 2024
f275e13
remove 404 redirect
andresag4 Jul 29, 2024
7cf70f4
Merge branch 'main' into 22-qr-code-generation
LuigiR0jas Jul 30, 2024
f5e7ae8
Merge branch 'main' into 22-qr-code-generation
LuigiR0jas Jul 30, 2024
400ec80
fix routes and specs
andresag4 Jul 30, 2024
fbaea2c
Merge branch '22-qr-code-generation' of github.com:TelosLabs/rails-wo…
andresag4 Jul 30, 2024
673e8cf
linter
andresag4 Jul 30, 2024
b83bbca
Update routes.rb
andresag4 Jul 30, 2024
655a259
Update routes.rb
andresag4 Jul 30, 2024
97926dc
Refactor profiles routes
andresag4 Jul 30, 2024
4a16783
Merge branch '22-qr-code-generation' of github.com:TelosLabs/rails-wo…
andresag4 Jul 30, 2024
aa4d473
Standard js fix
LuigiR0jas Jul 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .database_consistency.todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ Profile:
self_ref:
MissingIndexChecker:
enabled: false
uuid:
ColumnPresenceChecker:
enabled: false
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ gem "avo", ">= 3.2.1"

# Other
gem "bootsnap", require: false
gem "draper"
gem "inline_svg"
gem "puma", ">= 5.0"
gem "ransack"
Expand Down
15 changes: 15 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,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)
Expand Down Expand Up @@ -166,6 +170,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)
Expand Down Expand Up @@ -375,6 +386,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)
Expand Down Expand Up @@ -436,6 +449,7 @@ GEM
rubocop (~> 1.61)
rubocop-rspec (~> 3, >= 3.0.1)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
ruby_parser (3.21.0)
racc (~> 1.5)
sexp_processor (~> 4.16)
Expand Down Expand Up @@ -546,6 +560,7 @@ DEPENDENCIES
database_consistency
debug
dotenv
draper
erb_lint
factory_bot_rails
faker
Expand Down
8 changes: 8 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -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
andresag4 marked this conversation as resolved.
Show resolved Hide resolved
andresag4 marked this conversation as resolved.
Show resolved Hide resolved
end
22 changes: 21 additions & 1 deletion app/controllers/profiles_controller.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
class ProfilesController < ApplicationController
before_action :set_profile, only: :show

def show
@profile = current_profile
@profile = @profile.decorate
end

def new
@profile = current_user.build_profile
end
LuigiR0jas marked this conversation as resolved.
Show resolved Hide resolved

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)
Expand All @@ -21,6 +37,10 @@ def update

private

def set_profile
@profile = Profile.public_profiles.find_by!(uuid: params[:uuid])
end

def current_profile
current_user.profile || current_user.build_profile
end
Expand Down
13 changes: 13 additions & 0 deletions app/decorators/profile_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class ProfileDecorator < Draper::Decorator
delegate_all

def svg_qr_code(options = {})
RQRCode::QRCode.new(profile_url).as_svg(options)
end

private

def profile_url
Rails.application.routes.url_helpers.profile_url(object.uuid)
end
end
14 changes: 14 additions & 0 deletions app/models/profile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
# 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
#
# Indexes
#
# index_profiles_on_profileable (profileable_type,profileable_id)
# index_profiles_on_uuid (uuid) UNIQUE
#
class Profile < ApplicationRecord
has_one_attached :image
Expand All @@ -29,4 +31,16 @@ class Profile < ApplicationRecord
has_one :speaker, through: :self_ref, source: :profileable, source_type: "Speaker"

belongs_to :profileable, polymorphic: true

validates :uuid, uniqueness: true, presence: true

before_validation :set_uuid

scope :public_profiles, -> { where(is_public: true) }

private

def set_uuid
self.uuid ||= SecureRandom.uuid
end
end
1 change: 1 addition & 0 deletions app/views/profiles/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
</div>
</div>
</div>
<%= render inline: @profile.svg_qr_code(module_size: 4) %>
<div class="p-4 flex flex-col items-center gap-4 w-full">
<%= link_to 'Edit Profile', edit_profile_path, class: "text-red font-bold rounded-sm underline italic text-lg" %>
</div>
Expand Down
5 changes: 5 additions & 0 deletions config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
2 changes: 2 additions & 0 deletions config/environments/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions config/initializers/inflections.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"
andresag4 marked this conversation as resolved.
Show resolved Hide resolved
end
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@
resource :password_reset, only: [:new, :create, :edit, :update] do
get :post_submit
end

resources :profiles, only: [:show, :edit, :update], param: :uuid
LuigiR0jas marked this conversation as resolved.
Show resolved Hide resolved
end
6 changes: 6 additions & 0 deletions db/migrate/20240710213305_add_profile_uuid_to_profile.rb
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions spec/controllers/profiles_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# 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
end
11 changes: 11 additions & 0 deletions spec/decorators/profile_decorator_spec.rb
Original file line number Diff line number Diff line change
@@ -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("<svg")
end
end
end
7 changes: 7 additions & 0 deletions spec/factories/profiles.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
# 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
#
# Indexes
#
# index_profiles_on_profileable (profileable_type,profileable_id)
# index_profiles_on_uuid (uuid) UNIQUE
#
FactoryBot.define do
factory :profile do
Expand All @@ -30,9 +32,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
11 changes: 11 additions & 0 deletions spec/models/profile_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
# 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
#
# Indexes
#
# index_profiles_on_profileable (profileable_type,profileable_id)
# index_profiles_on_uuid (uuid) UNIQUE
#
require "rails_helper"

Expand All @@ -29,4 +31,13 @@
it "has a valid factory" do
expect(profile).to be_valid
end

describe "callbacks" do
let(:profile) { build(:profile, :with_user) }

it "sets a UUID before creation" do
profile.save
expect(profile.uuid).to be_present
end
end
end