Add mailing address form

This commit is contained in:
Max Wofford 2025-05-09 16:36:51 -04:00
parent a7bc1101ea
commit 70f0977bbc
13 changed files with 186 additions and 1 deletions

View file

@ -47,6 +47,9 @@ WILDCARD_HOST=your_wildcard_host_here
# key for updating loops via airtable
LOOPS_AIRTABLE_PAT=your_airtable_key_here
# key for updating address records
ADDRESS_AIRTABLE_PAT=your_airtable_pat
# GitHub oauth used for github signin
GITHUB_CLIENT_ID=your_github_client_id_here
GITHUB_CLIENT_SECRET=your_github_client_secret_here

View file

@ -0,0 +1,19 @@
module My
class MailingAddressesController < ApplicationController
def show
@user = current_user
# Generate OTC if it doesn't exist
if params[:from_fillout]
FetchMailingAddressJob.perform_now(@user.id)
else
@user.update_column(:mailing_address_otc, SecureRandom.hex(8))
end
end
def edit
current_user.update_column(:mailing_address_otc, SecureRandom.hex(8))
redirect_to "https://forms.hackclub.com/t/mo6hitqC6Vus?otc=#{current_user.mailing_address_otc}", allow_other_host: true
end
end
end

View file

@ -0,0 +1,31 @@
class FetchMailingAddressJob < ApplicationJob
queue_as :default
Table = Norairrecord.table(ENV["ADDRESS_AIRTABLE_PAT"], "appEC3w8nxAvCwAjL", "tbldZMvkUWGkkteQu")
def perform(user_id)
user = User.find(user_id)
return unless user.mailing_address_otc.present?
# Search Airtable for the address with this OTC
records = Table.all(filter: "{OTC} = '#{user.mailing_address_otc}'")
return if records.empty?
address_data = records.first.fields
# Create or update the mailing address
mailing_address = user.mailing_address || user.build_mailing_address
mailing_address.update!(
first_name: address_data["first_name"],
last_name: address_data["last_name"],
line_1: address_data["line_1"],
line_2: address_data["line_2"],
city: address_data["city"],
state: address_data["state"],
zip_code: address_data["zip_code"],
country: address_data["country"]
)
records.first.destroy
end
end

View file

@ -0,0 +1,27 @@
class MailingAddress < ApplicationRecord
has_paper_trail
belongs_to :user
encrypts :first_name, deterministic: true
encrypts :last_name, deterministic: true
encrypts :zip_code, deterministic: true
encrypts :line_1, deterministic: true
encrypts :line_2, deterministic: true
encrypts :city, deterministic: true
encrypts :state, deterministic: true
encrypts :country, deterministic: true
after_save :update_user_country_code
private
def update_user_country_code
return unless country.present?
# Find the country by name and get its ISO code
country_obj = ISO3166::Country.find_country_by_any_name(country)
return unless country_obj
user.update_column(:country_code, country_obj.alpha2)
end
end

View file

@ -18,6 +18,7 @@ class User < ApplicationRecord
has_many :email_verification_requests, dependent: :destroy
has_many :sign_in_tokens, dependent: :destroy
has_many :project_repo_mappings
has_one :mailing_address, dependent: :destroy
has_many :hackatime_heartbeats,
foreign_key: :user_id,

View file

@ -0,0 +1,29 @@
<% content_for :title do %>
My Mailing Address
<% end %>
<main class="container">
<header>
<h1>My Mailing Address</h1>
</header>
<% if @user.mailing_address.present? %>
<section class="mailing-address">
<div class="address-details">
<p><%= @user.mailing_address.first_name %> <%= @user.mailing_address.last_name %></p>
<p><%= @user.mailing_address.line_1 %></p>
<% if @user.mailing_address.line_2.present? %>
<p><%= @user.mailing_address.line_2 %></p>
<% end %>
<p><%= @user.mailing_address.city %>, <%= @user.mailing_address.state %> <%= @user.mailing_address.zip_code %></p>
<p><%= @user.mailing_address.country %></p>
</div>
</section>
<% end %>
<p>
<%= link_to @user.mailing_address.present? ? "Update this address" : "Add your address",
edit_my_mailing_address_path,
class: "button" %>
</p>
</main>

View file

@ -57,6 +57,11 @@
Mailers
<% end %>
<% end %>
<% admin_tool(nil, "li") do %>
<%= link_to my_mailing_address_path, class: "nav-item #{current_page?(my_mailing_address_path) ? 'active' : ''}" do %>
Mailing Address
<% end %>
<% end %>
<% admin_tool(nil, "li") do %>
<%= link_to ahoy_captain_path, class: "nav-item #{current_page?(ahoy_captain_path) ? 'active' : ''}" do %>
Ahoy Captain

View file

@ -73,6 +73,7 @@ Rails.application.routes.draw do
namespace :my do
resources :project_repo_mappings, param: :project_name, only: [ :edit, :update ]
resource :mailing_address, only: [ :show, :edit ]
end
get "my/wakatime_setup", to: "users#wakatime_setup"

View file

@ -0,0 +1,17 @@
class CreateMailingAddresses < ActiveRecord::Migration[8.0]
def change
create_table :mailing_addresses do |t|
t.references :user, null: false, foreign_key: true
t.string :first_name, null: false
t.string :last_name, null: false
t.string :zip_code, null: false
t.string :line_1, null: false
t.string :line_2
t.string :city, null: false
t.string :state, null: false
t.string :country, null: false
t.timestamps
end
end
end

View file

@ -0,0 +1,5 @@
class AddMailingAddressOtcToUsers < ActiveRecord::Migration[8.0]
def change
add_column :users, :mailing_address_otc, :string
end
end

19
db/schema.rb generated
View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2025_05_09_170101) do
ActiveRecord::Schema[8.0].define(version: 2025_05_09_191155) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
@ -236,6 +236,21 @@ ActiveRecord::Schema[8.0].define(version: 2025_05_09_170101) do
t.integer "period_type", default: 0, null: false
end
create_table "mailing_addresses", force: :cascade do |t|
t.bigint "user_id", null: false
t.string "first_name", null: false
t.string "last_name", null: false
t.string "zip_code", null: false
t.string "line_1", null: false
t.string "line_2"
t.string "city", null: false
t.string "state", null: false
t.string "country", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_mailing_addresses_on_user_id"
end
create_table "project_repo_mappings", force: :cascade do |t|
t.bigint "user_id", null: false
t.string "project_name", null: false
@ -313,6 +328,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_05_09_170101) do
t.string "slack_neighborhood_channel"
t.integer "trust_level", default: 0, null: false
t.string "country_code"
t.string "mailing_address_otc"
t.index ["slack_uid"], name: "index_users_on_slack_uid", unique: true
t.index ["timezone"], name: "index_users_on_timezone"
end
@ -334,6 +350,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_05_09_170101) do
add_foreign_key "heartbeats", "users"
add_foreign_key "leaderboard_entries", "leaderboards"
add_foreign_key "leaderboard_entries", "users"
add_foreign_key "mailing_addresses", "users"
add_foreign_key "project_repo_mappings", "users"
add_foreign_key "sign_in_tokens", "users"
end

23
test/fixtures/mailing_addresses.yml vendored Normal file
View file

@ -0,0 +1,23 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
user: one
first_name: MyString
last_name: MyString
zip_code: MyString
line_1: MyString
line_2: MyString
city: MyString
state: MyString
country: MyString
two:
user: two
first_name: MyString
last_name: MyString
zip_code: MyString
line_1: MyString
line_2: MyString
city: MyString
state: MyString
country: MyString

View file

@ -0,0 +1,7 @@
require "test_helper"
class MailingAddressTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end