diff --git a/.rubocop.yml b/.rubocop.yml
index 68349d6..267d958 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -12,3 +12,6 @@ AllCops:
# # Use `[a, [b, c]]` not `[ a, [ b, c ] ]`
# Layout/SpaceInsideArrayLiteralBrackets:
# Enabled: false
+
+Bundler/OrderedGems:
+ Enabled: true
diff --git a/Gemfile b/Gemfile
index d59d620..4ceebcc 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,23 +2,25 @@ source "https://rubygems.org"
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 8.1.3"
-# The modern asset pipeline for Rails [https://github.com/rails/propshaft]
-gem "propshaft"
-# Use sqlite3 as the database for Active Record
-gem "sqlite3", ">= 2.9.6"
-# Use the Puma web server [https://github.com/puma/puma]
-gem "puma", ">= 5.0"
+
+
+gem "devise", "~> 5.0"
# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
gem "importmap-rails"
-# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
-gem "turbo-rails"
-# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
-gem "stimulus-rails"
# Build JSON APIs with ease [https://github.com/rails/jbuilder]
gem "jbuilder"
-
+# The modern asset pipeline for Rails [https://github.com/rails/propshaft]
+gem "propshaft"
+# Use the Puma web server [https://github.com/puma/puma]
+gem "puma", ">= 5.0"
# Handle Cross-Origin Resource Sharing so the Expo app can call the API [https://github.com/cyu/rack-cors]
gem "rack-cors"
+# Use sqlite3 as the database for Active Record
+gem "sqlite3", ">= 2.9.6"
+# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
+gem "stimulus-rails"
+# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
+gem "turbo-rails"
# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
# gem "bcrypt", "~> 3.1.7"
@@ -27,9 +29,9 @@ gem "rack-cors"
gem "tzinfo-data", platforms: %i[ windows jruby ]
# Use the database-backed adapters for Rails.cache, Active Job, and Action Cable
+gem "solid_cable"
gem "solid_cache"
gem "solid_queue"
-gem "solid_cable"
# Reduces boot times through caching; required in config/boot.rb
gem "bootsnap", require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 7ffa82e..d923c23 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -79,6 +79,7 @@ GEM
public_suffix (>= 2.0.2, < 8.0)
ast (2.4.3)
base64 (0.3.0)
+ bcrypt (3.1.22)
bcrypt_pbkdf (1.1.2)
bigdecimal (4.1.2)
bindex (0.8.1)
@@ -106,6 +107,12 @@ GEM
debug (1.11.1)
irb (~> 1.10)
reline (>= 0.3.8)
+ devise (5.0.4)
+ bcrypt (~> 3.0)
+ orm_adapter (~> 0.1)
+ railties (>= 7.0)
+ responders
+ warden (~> 1.2.3)
dotenv (3.2.0)
drb (2.2.3)
ed25519 (1.4.0)
@@ -201,6 +208,7 @@ GEM
racc (~> 1.4)
nokogiri (1.19.4-x86_64-linux-musl)
racc (~> 1.4)
+ orm_adapter (0.5.0)
ostruct (0.6.3)
parallel (2.1.0)
parser (3.3.11.1)
@@ -274,6 +282,9 @@ GEM
regexp_parser (2.12.0)
reline (0.6.3)
io-console (~> 0.5)
+ responders (3.2.1)
+ actionpack (>= 7.0)
+ railties (>= 7.0)
rexml (3.4.4)
rubocop (1.88.1)
json (~> 2.3)
@@ -364,6 +375,8 @@ GEM
unicode-emoji (4.2.0)
uri (1.1.1)
useragent (0.16.11)
+ warden (1.2.9)
+ rack (>= 2.0.9)
web-console (4.3.0)
actionview (>= 8.0.0)
bindex (>= 0.4.0)
@@ -395,6 +408,7 @@ DEPENDENCIES
bundler-audit
capybara
debug
+ devise (~> 5.0)
image_processing (~> 2.0)
importmap-rails
jbuilder
@@ -432,6 +446,7 @@ CHECKSUMS
addressable (2.9.0) sha256=7fdf6ac3660f7f4e867a0838be3f6cf722ace541dd97767fa42bc6cfa980c7af
ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
+ bcrypt (3.1.22) sha256=1f0072e88c2d705d94aff7f2c5cb02eb3f1ec4b8368671e19112527489f29032
bcrypt_pbkdf (1.1.2) sha256=c2414c23ce66869b3eb9f643d6a3374d8322dfb5078125c82792304c10b94cf6
bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd
bindex (0.8.1) sha256=7b1ecc9dc539ed8bccfc8cb4d2732046227b09d6f37582ff12e50a5047ceb17e
@@ -445,6 +460,7 @@ CHECKSUMS
crass (1.0.7) sha256=94868719948664c89ddcaf0a37c65048413dfcb1c869470a5f7a7ceb5390b295
date (3.5.1) sha256=750d06384d7b9c15d562c76291407d89e368dda4d4fff957eb94962d325a0dc0
debug (1.11.1) sha256=2e0b0ac6119f2207a6f8ac7d4a73ca8eb4e440f64da0a3136c30343146e952b6
+ devise (5.0.4) sha256=d605f2b85854e74e56ee789e2d398702bc2d06e6bcd894717a670a3199c74cc1
dotenv (3.2.0) sha256=e375b83121ea7ca4ce20f214740076129ab8514cd81378161f11c03853fe619d
drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373
ed25519 (1.4.0) sha256=16e97f5198689a154247169f3453ef4cfd3f7a47481fde0ae33206cdfdcac506
@@ -493,6 +509,7 @@ CHECKSUMS
nokogiri (1.19.4-arm64-darwin) sha256=a46db9853286e6597b36ebc6953817d15acf3a299583eb3f89fdc6f91dd63527
nokogiri (1.19.4-x86_64-linux-gnu) sha256=379fae440b28915e3f19d752ce2dcf8465ed2b2fbefd2a7ca0dd497bc981a06a
nokogiri (1.19.4-x86_64-linux-musl) sha256=17dfb7c1fa194ae02fbf7c51a7afc8d278045ab3fdacfd86f91d02d7b274470b
+ orm_adapter (0.5.0) sha256=aa5d0be5d540cbb46d3a93e88061f4ece6a25f6e97d6a47122beb84fe595e9b9
ostruct (0.6.3) sha256=95a2ed4a4bd1d190784e666b47b2d3f078e4a9efda2fccf18f84ddc6538ed912
parallel (2.1.0) sha256=b35258865c2e31134c5ecb708beaaf6772adf9d5efae28e93e99260877b09356
parser (3.3.11.1) sha256=d17ace7aabe3e72c3cc94043714be27cc6f852f104d81aa284c2281aecc65d54
@@ -519,6 +536,7 @@ CHECKSUMS
rdoc (8.0.0) sha256=03bf8c08a9639658855a0cfd77c0abca8325c227693f7f33f82957811348c469
regexp_parser (2.12.0) sha256=35a916a1d63190ab5c9009457136ae5f3c0c7512d60291d0d1378ba18ce08ebb
reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835
+ responders (3.2.1) sha256=c2772970cbda654c0e772d852e5a851e82cd8e96f5fa958650861ba75b8ffa84
rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142
rubocop (1.88.1) sha256=726af773d6bc169ed3ff852f3ca020b7c58d39c34e7a8d879a8e0147cc994f26
rubocop-ast (1.50.0) sha256=b9ca88300da0803ee222ad20cdb30494c0a784eed06fdc35d254b06d662788db
@@ -555,6 +573,7 @@ CHECKSUMS
unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
useragent (0.16.11) sha256=700e6413ad4bb954bb63547fa098dddf7b0ebe75b40cc6f93b8d54255b173844
+ warden (1.2.9) sha256=46684f885d35a69dbb883deabf85a222c8e427a957804719e143005df7a1efd0
web-console (4.3.0) sha256=e13b71301cdfc2093f155b5aa3a622db80b4672d1f2f713119cc7ec7ac6a6da4
websocket (1.2.11) sha256=b7e7a74e2410b5e85c25858b26b3322f29161e300935f70a0e0d3c35e0462737
websocket-driver (0.8.2) sha256=97c556b019bf3410b4961002ac501621e9322d3f8a7bc02161a09301cc4c4146
diff --git a/app/assets/images/horse.jpg b/app/assets/images/horse.jpg
new file mode 100644
index 0000000..201e1bd
Binary files /dev/null and b/app/assets/images/horse.jpg differ
diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb
new file mode 100644
index 0000000..6396a5f
--- /dev/null
+++ b/app/controllers/home_controller.rb
@@ -0,0 +1,7 @@
+class HomeController < ApplicationController
+ def index
+ end
+
+ def world
+ end
+end
diff --git a/app/controllers/medication_types_controller.rb b/app/controllers/medication_types_controller.rb
new file mode 100644
index 0000000..7bae334
--- /dev/null
+++ b/app/controllers/medication_types_controller.rb
@@ -0,0 +1,70 @@
+class MedicationTypesController < ApplicationController
+ before_action :set_medication_type, only: %i[ show edit update destroy ]
+
+ # GET /medication_types or /medication_types.json
+ def index
+ @medication_types = MedicationType.all
+ end
+
+ # GET /medication_types/1 or /medication_types/1.json
+ def show
+ end
+
+ # GET /medication_types/new
+ def new
+ @medication_type = MedicationType.new
+ end
+
+ # GET /medication_types/1/edit
+ def edit
+ end
+
+ # POST /medication_types or /medication_types.json
+ def create
+ @medication_type = MedicationType.new(medication_type_params)
+
+ respond_to do |format|
+ if @medication_type.save
+ format.html { redirect_to @medication_type, notice: "Medication type was successfully created." }
+ format.json { render :show, status: :created, location: @medication_type }
+ else
+ format.html { render :new, status: :unprocessable_content }
+ format.json { render json: @medication_type.errors, status: :unprocessable_content }
+ end
+ end
+ end
+
+ # PATCH/PUT /medication_types/1 or /medication_types/1.json
+ def update
+ respond_to do |format|
+ if @medication_type.update(medication_type_params)
+ format.html { redirect_to @medication_type, notice: "Medication type was successfully updated.", status: :see_other }
+ format.json { render :show, status: :ok, location: @medication_type }
+ else
+ format.html { render :edit, status: :unprocessable_content }
+ format.json { render json: @medication_type.errors, status: :unprocessable_content }
+ end
+ end
+ end
+
+ # DELETE /medication_types/1 or /medication_types/1.json
+ def destroy
+ @medication_type.destroy!
+
+ respond_to do |format|
+ format.html { redirect_to medication_types_path, notice: "Medication type was successfully destroyed.", status: :see_other }
+ format.json { head :no_content }
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_medication_type
+ @medication_type = MedicationType.find(params.expect(:id))
+ end
+
+ # Only allow a list of trusted parameters through.
+ def medication_type_params
+ params.expect(medication_type: [ :name ])
+ end
+end
diff --git a/app/controllers/medications_controller.rb b/app/controllers/medications_controller.rb
new file mode 100644
index 0000000..804f765
--- /dev/null
+++ b/app/controllers/medications_controller.rb
@@ -0,0 +1,70 @@
+class MedicationsController < ApplicationController
+ before_action :set_medication, only: %i[ show edit update destroy ]
+
+ # GET /medications or /medications.json
+ def index
+ @medications = Medication.all
+ end
+
+ # GET /medications/1 or /medications/1.json
+ def show
+ end
+
+ # GET /medications/new
+ def new
+ @medication = Medication.new
+ end
+
+ # GET /medications/1/edit
+ def edit
+ end
+
+ # POST /medications or /medications.json
+ def create
+ @medication = Medication.new(medication_params)
+
+ respond_to do |format|
+ if @medication.save
+ format.html { redirect_to @medication, notice: "Medication was successfully created." }
+ format.json { render :show, status: :created, location: @medication }
+ else
+ format.html { render :new, status: :unprocessable_content }
+ format.json { render json: @medication.errors, status: :unprocessable_content }
+ end
+ end
+ end
+
+ # PATCH/PUT /medications/1 or /medications/1.json
+ def update
+ respond_to do |format|
+ if @medication.update(medication_params)
+ format.html { redirect_to @medication, notice: "Medication was successfully updated.", status: :see_other }
+ format.json { render :show, status: :ok, location: @medication }
+ else
+ format.html { render :edit, status: :unprocessable_content }
+ format.json { render json: @medication.errors, status: :unprocessable_content }
+ end
+ end
+ end
+
+ # DELETE /medications/1 or /medications/1.json
+ def destroy
+ @medication.destroy!
+
+ respond_to do |format|
+ format.html { redirect_to medications_path, notice: "Medication was successfully destroyed.", status: :see_other }
+ format.json { head :no_content }
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_medication
+ @medication = Medication.find(params.expect(:id))
+ end
+
+ # Only allow a list of trusted parameters through.
+ def medication_params
+ params.expect(medication: [ :name, :medication_type_id, :current, :dosage, :frequency, :time_of_day, :form, :purpose, :start_date, :stop_date, :refill, :notes ])
+ end
+end
diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb
new file mode 100644
index 0000000..f68035c
--- /dev/null
+++ b/app/controllers/people_controller.rb
@@ -0,0 +1,70 @@
+class PeopleController < ApplicationController
+ before_action :set_person, only: %i[ show edit update destroy ]
+
+ # GET /people or /people.json
+ def index
+ @people = Person.all
+ end
+
+ # GET /people/1 or /people/1.json
+ def show
+ end
+
+ # GET /people/new
+ def new
+ @person = Person.new
+ end
+
+ # GET /people/1/edit
+ def edit
+ end
+
+ # POST /people or /people.json
+ def create
+ @person = Person.new(person_params)
+
+ respond_to do |format|
+ if @person.save
+ format.html { redirect_to @person, notice: "Person was successfully created." }
+ format.json { render :show, status: :created, location: @person }
+ else
+ format.html { render :new, status: :unprocessable_content }
+ format.json { render json: @person.errors, status: :unprocessable_content }
+ end
+ end
+ end
+
+ # PATCH/PUT /people/1 or /people/1.json
+ def update
+ respond_to do |format|
+ if @person.update(person_params)
+ format.html { redirect_to @person, notice: "Person was successfully updated.", status: :see_other }
+ format.json { render :show, status: :ok, location: @person }
+ else
+ format.html { render :edit, status: :unprocessable_content }
+ format.json { render json: @person.errors, status: :unprocessable_content }
+ end
+ end
+ end
+
+ # DELETE /people/1 or /people/1.json
+ def destroy
+ @person.destroy!
+
+ respond_to do |format|
+ format.html { redirect_to people_path, notice: "Person was successfully destroyed.", status: :see_other }
+ format.json { head :no_content }
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_person
+ @person = Person.find(params.expect(:id))
+ end
+
+ # Only allow a list of trusted parameters through.
+ def person_params
+ params.expect(person: [ :first_name, :last_name, :date_of_birth, :social_security_number, :email, :relationship_id ])
+ end
+end
diff --git a/app/helpers/home_helper.rb b/app/helpers/home_helper.rb
new file mode 100644
index 0000000..23de56a
--- /dev/null
+++ b/app/helpers/home_helper.rb
@@ -0,0 +1,2 @@
+module HomeHelper
+end
diff --git a/app/helpers/medication_types_helper.rb b/app/helpers/medication_types_helper.rb
new file mode 100644
index 0000000..84a67f0
--- /dev/null
+++ b/app/helpers/medication_types_helper.rb
@@ -0,0 +1,2 @@
+module MedicationTypesHelper
+end
diff --git a/app/helpers/medications_helper.rb b/app/helpers/medications_helper.rb
new file mode 100644
index 0000000..1cca854
--- /dev/null
+++ b/app/helpers/medications_helper.rb
@@ -0,0 +1,2 @@
+module MedicationsHelper
+end
diff --git a/app/helpers/people_helper.rb b/app/helpers/people_helper.rb
new file mode 100644
index 0000000..b682fbf
--- /dev/null
+++ b/app/helpers/people_helper.rb
@@ -0,0 +1,2 @@
+module PeopleHelper
+end
diff --git a/app/models/medication.rb b/app/models/medication.rb
new file mode 100644
index 0000000..3527fc1
--- /dev/null
+++ b/app/models/medication.rb
@@ -0,0 +1,3 @@
+class Medication < ApplicationRecord
+ belongs_to :medication_type
+end
diff --git a/app/models/medication_type.rb b/app/models/medication_type.rb
new file mode 100644
index 0000000..548d639
--- /dev/null
+++ b/app/models/medication_type.rb
@@ -0,0 +1,2 @@
+class MedicationType < ApplicationRecord
+end
diff --git a/app/models/person.rb b/app/models/person.rb
new file mode 100644
index 0000000..9791ac6
--- /dev/null
+++ b/app/models/person.rb
@@ -0,0 +1,3 @@
+class Person < ApplicationRecord
+ belongs_to :relationship
+end
diff --git a/app/models/relationship.rb b/app/models/relationship.rb
new file mode 100644
index 0000000..3cabc44
--- /dev/null
+++ b/app/models/relationship.rb
@@ -0,0 +1,2 @@
+class Relationship < ApplicationRecord
+end
diff --git a/app/models/user.rb b/app/models/user.rb
new file mode 100644
index 0000000..4f14a8d
--- /dev/null
+++ b/app/models/user.rb
@@ -0,0 +1,7 @@
+class User < ApplicationRecord
+ # Include default devise modules. Others available are:
+ # :omniauthable
+ devise :database_authenticatable, :registerable,
+ :recoverable, :rememberable, :validatable,
+ :lockable, :trackable, :confirmable
+end
diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb
new file mode 100644
index 0000000..3c21122
--- /dev/null
+++ b/app/views/devise/confirmations/new.html.erb
@@ -0,0 +1,16 @@
+
Resend confirmation instructions
+
+<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
+ <%= render "devise/shared/error_messages", resource: resource %>
+
+
+
<%= f.label :email %>
+
<%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
+
+
+
+ <%= f.submit "Resend confirmation instructions" %>
+
+<% end %>
+
+<%= render "devise/shared/links" %>
diff --git a/app/views/devise/mailer/confirmation_instructions.html.erb b/app/views/devise/mailer/confirmation_instructions.html.erb
new file mode 100644
index 0000000..dc55f64
--- /dev/null
+++ b/app/views/devise/mailer/confirmation_instructions.html.erb
@@ -0,0 +1,5 @@
+Welcome <%= @email %>!
+
+You can confirm your account email through the link below:
+
+<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>
diff --git a/app/views/devise/mailer/email_changed.html.erb b/app/views/devise/mailer/email_changed.html.erb
new file mode 100644
index 0000000..32f4ba8
--- /dev/null
+++ b/app/views/devise/mailer/email_changed.html.erb
@@ -0,0 +1,7 @@
+Hello <%= @email %>!
+
+<% if @resource.try(:unconfirmed_email?) %>
+ We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.
+<% else %>
+ We're contacting you to notify you that your email has been changed to <%= @resource.email %>.
+<% end %>
diff --git a/app/views/devise/mailer/password_change.html.erb b/app/views/devise/mailer/password_change.html.erb
new file mode 100644
index 0000000..b41daf4
--- /dev/null
+++ b/app/views/devise/mailer/password_change.html.erb
@@ -0,0 +1,3 @@
+Hello <%= @resource.email %>!
+
+We're contacting you to notify you that your password has been changed.
diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb
new file mode 100644
index 0000000..f667dc1
--- /dev/null
+++ b/app/views/devise/mailer/reset_password_instructions.html.erb
@@ -0,0 +1,8 @@
+Hello <%= @resource.email %>!
+
+Someone has requested a link to change your password. You can do this through the link below.
+
+<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>
+
+If you didn't request this, please ignore this email.
+Your password won't change until you access the link above and create a new one.
diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb
new file mode 100644
index 0000000..41e148b
--- /dev/null
+++ b/app/views/devise/mailer/unlock_instructions.html.erb
@@ -0,0 +1,7 @@
+Hello <%= @resource.email %>!
+
+Your account has been locked due to an excessive number of unsuccessful sign in attempts.
+
+Click the link below to unlock your account:
+
+<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>
diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb
new file mode 100644
index 0000000..3f1dbc7
--- /dev/null
+++ b/app/views/devise/passwords/edit.html.erb
@@ -0,0 +1,25 @@
+Change your password
+
+<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
+ <%= render "devise/shared/error_messages", resource: resource %>
+ <%= f.hidden_field :reset_password_token %>
+
+
+
<%= f.label :password, "New password" %>
+ <% if @minimum_password_length %>
+
(<%= @minimum_password_length %> characters minimum)
+ <% end %>
+
<%= f.password_field :password, autofocus: true, autocomplete: "new-password" %>
+
+
+
+
<%= f.label :password_confirmation, "Confirm new password" %>
+
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
+
+
+
+ <%= f.submit "Change my password" %>
+
+<% end %>
+
+<%= render "devise/shared/links" %>
diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb
new file mode 100644
index 0000000..bea7ad1
--- /dev/null
+++ b/app/views/devise/passwords/new.html.erb
@@ -0,0 +1,16 @@
+Forgot your password?
+
+<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
+ <%= render "devise/shared/error_messages", resource: resource %>
+
+
+
<%= f.label :email %>
+
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
+
+
+
+ <%= f.submit "Send me password reset instructions" %>
+
+<% end %>
+
+<%= render "devise/shared/links" %>
diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb
new file mode 100644
index 0000000..19bb019
--- /dev/null
+++ b/app/views/devise/registrations/edit.html.erb
@@ -0,0 +1,42 @@
+Edit <%= resource_name.to_s.humanize %>
+
+<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
+ <%= render "devise/shared/error_messages", resource: resource %>
+
+
+
<%= f.label :email %>
+
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
+
+
+ <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
+ Currently waiting confirmation for: <%= resource.unconfirmed_email %>
+ <% end %>
+
+
+
<%= f.label :password %> (leave blank if you don't want to change it)
+
<%= f.password_field :password, autocomplete: "new-password" %>
+ <% if @minimum_password_length %>
+
<%= @minimum_password_length %> characters minimum
+ <% end %>
+
+
+
+
<%= f.label :password_confirmation %>
+
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
+
+
+
+
<%= f.label :current_password %> (we need your current password to confirm your changes)
+
<%= f.password_field :current_password, autocomplete: "current-password" %>
+
+
+
+ <%= f.submit "Update" %>
+
+<% end %>
+
+Cancel my account
+
+Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %>
+
+<%= link_to "Back", :back %>
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb
new file mode 100644
index 0000000..03f48fb
--- /dev/null
+++ b/app/views/devise/registrations/new.html.erb
@@ -0,0 +1,29 @@
+Sign up
+
+<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
+ <%= render "devise/shared/error_messages", resource: resource %>
+
+
+
<%= f.label :email %>
+
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
+
+
+
+
<%= f.label :password %>
+ <% if @minimum_password_length %>
+
(<%= @minimum_password_length %> characters minimum)
+ <% end %>
+
<%= f.password_field :password, autocomplete: "new-password" %>
+
+
+
+
<%= f.label :password_confirmation %>
+
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
+
+
+
+ <%= f.submit "Sign up" %>
+
+<% end %>
+
+<%= render "devise/shared/links" %>
diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb
new file mode 100644
index 0000000..6eeb9fc
--- /dev/null
+++ b/app/views/devise/sessions/new.html.erb
@@ -0,0 +1,26 @@
+Log in
+
+<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
+
+
<%= f.label :email %>
+
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
+
+
+
+
<%= f.label :password %>
+
<%= f.password_field :password, autocomplete: "current-password" %>
+
+
+ <% if devise_mapping.rememberable? %>
+
+
<%= f.check_box :remember_me %>
+
<%= f.label :remember_me %>
+
+ <% end %>
+
+
+ <%= f.submit "Log in" %>
+
+<% end %>
+
+<%= render "devise/shared/links" %>
diff --git a/app/views/devise/shared/_error_messages.html.erb b/app/views/devise/shared/_error_messages.html.erb
new file mode 100644
index 0000000..8c9c171
--- /dev/null
+++ b/app/views/devise/shared/_error_messages.html.erb
@@ -0,0 +1,15 @@
+<% if resource.errors.any? %>
+
+
+ <%= I18n.t("errors.messages.not_saved",
+ count: resource.errors.count,
+ resource: resource.class.model_name.human.downcase)
+ %>
+
+
+ <% resource.errors.full_messages.each do |message| %>
+ - <%= message %>
+ <% end %>
+
+
+<% end %>
diff --git a/app/views/devise/shared/_links.html.erb b/app/views/devise/shared/_links.html.erb
new file mode 100644
index 0000000..21cf422
--- /dev/null
+++ b/app/views/devise/shared/_links.html.erb
@@ -0,0 +1,25 @@
+<%- if controller_name != 'sessions' %>
+ <%= link_to "Log in", new_session_path(resource_name) %>
+<% end %>
+
+<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
+ <%= link_to "Sign up", new_registration_path(resource_name) %>
+<% end %>
+
+<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
+ <%= link_to "Forgot your password?", new_password_path(resource_name) %>
+<% end %>
+
+<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
+ <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
+<% end %>
+
+<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
+ <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
+<% end %>
+
+<%- if devise_mapping.omniauthable? %>
+ <%- resource_class.omniauth_providers.each do |provider| %>
+ <%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false } %>
+ <% end %>
+<% end %>
diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb
new file mode 100644
index 0000000..6b68d72
--- /dev/null
+++ b/app/views/devise/unlocks/new.html.erb
@@ -0,0 +1,16 @@
+Resend unlock instructions
+
+<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
+ <%= render "devise/shared/error_messages", resource: resource %>
+
+
+
<%= f.label :email %>
+
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
+
+
+
+ <%= f.submit "Resend unlock instructions" %>
+
+<% end %>
+
+<%= render "devise/shared/links" %>
diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb
new file mode 100644
index 0000000..3485ac1
--- /dev/null
+++ b/app/views/home/index.html.erb
@@ -0,0 +1,11 @@
+heading
+Hi
+<%= image_tag "horse.jpg", alt: "Horse", class: "horse-image" %>
+
+<% if user_signed_in? %>
+ <%= link_to 'Sign out', destroy_user_session_path, data: { turbo_method: :delete } %>
+<% else %>
+ <%= link_to 'Sign in', new_user_session_path %>
+ <%= link_to 'Sign up', new_user_registration_path %>
+<% end %>
+
diff --git a/app/views/medication_types/_form.html.erb b/app/views/medication_types/_form.html.erb
new file mode 100644
index 0000000..3fd2f7b
--- /dev/null
+++ b/app/views/medication_types/_form.html.erb
@@ -0,0 +1,22 @@
+<%= form_with(model: medication_type) do |form| %>
+ <% if medication_type.errors.any? %>
+
+
<%= pluralize(medication_type.errors.count, "error") %> prohibited this medication_type from being saved:
+
+
+ <% medication_type.errors.each do |error| %>
+ - <%= error.full_message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= form.label :name, style: "display: block" %>
+ <%= form.text_field :name %>
+
+
+
+ <%= form.submit %>
+
+<% end %>
diff --git a/app/views/medication_types/_medication_type.html.erb b/app/views/medication_types/_medication_type.html.erb
new file mode 100644
index 0000000..6b97951
--- /dev/null
+++ b/app/views/medication_types/_medication_type.html.erb
@@ -0,0 +1,7 @@
+
+
+ Name:
+ <%= medication_type.name %>
+
+
+
diff --git a/app/views/medication_types/_medication_type.json.jbuilder b/app/views/medication_types/_medication_type.json.jbuilder
new file mode 100644
index 0000000..b8273fa
--- /dev/null
+++ b/app/views/medication_types/_medication_type.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! medication_type, :id, :name, :created_at, :updated_at
+json.url medication_type_url(medication_type, format: :json)
diff --git a/app/views/medication_types/edit.html.erb b/app/views/medication_types/edit.html.erb
new file mode 100644
index 0000000..de94f6c
--- /dev/null
+++ b/app/views/medication_types/edit.html.erb
@@ -0,0 +1,12 @@
+<% content_for :title, "Editing medication type" %>
+
+Editing medication type
+
+<%= render "form", medication_type: @medication_type %>
+
+
+
+
+ <%= link_to "Show this medication type", @medication_type %> |
+ <%= link_to "Back to medication types", medication_types_path %>
+
diff --git a/app/views/medication_types/index.html.erb b/app/views/medication_types/index.html.erb
new file mode 100644
index 0000000..ef7c687
--- /dev/null
+++ b/app/views/medication_types/index.html.erb
@@ -0,0 +1,16 @@
+<%= notice %>
+
+<% content_for :title, "Medication types" %>
+
+Medication types
+
+
+ <% @medication_types.each do |medication_type| %>
+ <%= render medication_type %>
+
+ <%= link_to "Show this medication type", medication_type %>
+
+ <% end %>
+
+
+<%= link_to "New medication type", new_medication_type_path %>
diff --git a/app/views/medication_types/index.json.jbuilder b/app/views/medication_types/index.json.jbuilder
new file mode 100644
index 0000000..699339e
--- /dev/null
+++ b/app/views/medication_types/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @medication_types, partial: "medication_types/medication_type", as: :medication_type
diff --git a/app/views/medication_types/new.html.erb b/app/views/medication_types/new.html.erb
new file mode 100644
index 0000000..14c0467
--- /dev/null
+++ b/app/views/medication_types/new.html.erb
@@ -0,0 +1,11 @@
+<% content_for :title, "New medication type" %>
+
+New medication type
+
+<%= render "form", medication_type: @medication_type %>
+
+
+
+
+ <%= link_to "Back to medication types", medication_types_path %>
+
diff --git a/app/views/medication_types/show.html.erb b/app/views/medication_types/show.html.erb
new file mode 100644
index 0000000..7ec776e
--- /dev/null
+++ b/app/views/medication_types/show.html.erb
@@ -0,0 +1,10 @@
+<%= notice %>
+
+<%= render @medication_type %>
+
+
+ <%= link_to "Edit this medication type", edit_medication_type_path(@medication_type) %> |
+ <%= link_to "Back to medication types", medication_types_path %>
+
+ <%= button_to "Destroy this medication type", @medication_type, method: :delete %>
+
diff --git a/app/views/medication_types/show.json.jbuilder b/app/views/medication_types/show.json.jbuilder
new file mode 100644
index 0000000..b175477
--- /dev/null
+++ b/app/views/medication_types/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "medication_types/medication_type", medication_type: @medication_type
diff --git a/app/views/medications/_form.html.erb b/app/views/medications/_form.html.erb
new file mode 100644
index 0000000..678d8b6
--- /dev/null
+++ b/app/views/medications/_form.html.erb
@@ -0,0 +1,77 @@
+<%= form_with(model: medication) do |form| %>
+ <% if medication.errors.any? %>
+
+
<%= pluralize(medication.errors.count, "error") %> prohibited this medication from being saved:
+
+
+ <% medication.errors.each do |error| %>
+ - <%= error.full_message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= form.label :name, style: "display: block" %>
+ <%= form.text_field :name %>
+
+
+
+ <%= form.label :medication_type_id, style: "display: block" %>
+ <%= form.text_field :medication_type_id %>
+
+
+
+ <%= form.label :current, style: "display: block" %>
+ <%= form.checkbox :current %>
+
+
+
+ <%= form.label :dosage, style: "display: block" %>
+ <%= form.text_field :dosage %>
+
+
+
+ <%= form.label :frequency, style: "display: block" %>
+ <%= form.text_field :frequency %>
+
+
+
+ <%= form.label :time_of_day, style: "display: block" %>
+ <%= form.text_field :time_of_day %>
+
+
+
+ <%= form.label :form, style: "display: block" %>
+ <%= form.text_field :form %>
+
+
+
+ <%= form.label :purpose, style: "display: block" %>
+ <%= form.textarea :purpose %>
+
+
+
+ <%= form.label :start_date, style: "display: block" %>
+ <%= form.date_field :start_date %>
+
+
+
+ <%= form.label :stop_date, style: "display: block" %>
+ <%= form.date_field :stop_date %>
+
+
+
+ <%= form.label :refill, style: "display: block" %>
+ <%= form.text_field :refill %>
+
+
+
+ <%= form.label :notes, style: "display: block" %>
+ <%= form.textarea :notes %>
+
+
+
+ <%= form.submit %>
+
+<% end %>
diff --git a/app/views/medications/_medication.html.erb b/app/views/medications/_medication.html.erb
new file mode 100644
index 0000000..9d4de65
--- /dev/null
+++ b/app/views/medications/_medication.html.erb
@@ -0,0 +1,62 @@
+
+
+ Name:
+ <%= medication.name %>
+
+
+
+ Medication type:
+ <%= medication.medication_type_id %>
+
+
+
+ Current:
+ <%= medication.current %>
+
+
+
+ Dosage:
+ <%= medication.dosage %>
+
+
+
+ Frequency:
+ <%= medication.frequency %>
+
+
+
+ Time of day:
+ <%= medication.time_of_day %>
+
+
+
+ Form:
+ <%= medication.form %>
+
+
+
+ Purpose:
+ <%= medication.purpose %>
+
+
+
+ Start date:
+ <%= medication.start_date %>
+
+
+
+ Stop date:
+ <%= medication.stop_date %>
+
+
+
+ Refill:
+ <%= medication.refill %>
+
+
+
+ Notes:
+ <%= medication.notes %>
+
+
+
diff --git a/app/views/medications/_medication.json.jbuilder b/app/views/medications/_medication.json.jbuilder
new file mode 100644
index 0000000..7035a68
--- /dev/null
+++ b/app/views/medications/_medication.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! medication, :id, :name, :medication_type_id, :current, :dosage, :frequency, :time_of_day, :form, :purpose, :start_date, :stop_date, :refill, :notes, :created_at, :updated_at
+json.url medication_url(medication, format: :json)
diff --git a/app/views/medications/edit.html.erb b/app/views/medications/edit.html.erb
new file mode 100644
index 0000000..501cf0d
--- /dev/null
+++ b/app/views/medications/edit.html.erb
@@ -0,0 +1,12 @@
+<% content_for :title, "Editing medication" %>
+
+Editing medication
+
+<%= render "form", medication: @medication %>
+
+
+
+
+ <%= link_to "Show this medication", @medication %> |
+ <%= link_to "Back to medications", medications_path %>
+
diff --git a/app/views/medications/index.html.erb b/app/views/medications/index.html.erb
new file mode 100644
index 0000000..af091f8
--- /dev/null
+++ b/app/views/medications/index.html.erb
@@ -0,0 +1,16 @@
+<%= notice %>
+
+<% content_for :title, "Medications" %>
+
+Medications
+
+
+ <% @medications.each do |medication| %>
+ <%= render medication %>
+
+ <%= link_to "Show this medication", medication %>
+
+ <% end %>
+
+
+<%= link_to "New medication", new_medication_path %>
diff --git a/app/views/medications/index.json.jbuilder b/app/views/medications/index.json.jbuilder
new file mode 100644
index 0000000..fa6c129
--- /dev/null
+++ b/app/views/medications/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @medications, partial: "medications/medication", as: :medication
diff --git a/app/views/medications/new.html.erb b/app/views/medications/new.html.erb
new file mode 100644
index 0000000..64c6d1c
--- /dev/null
+++ b/app/views/medications/new.html.erb
@@ -0,0 +1,11 @@
+<% content_for :title, "New medication" %>
+
+New medication
+
+<%= render "form", medication: @medication %>
+
+
+
+
+ <%= link_to "Back to medications", medications_path %>
+
diff --git a/app/views/medications/show.html.erb b/app/views/medications/show.html.erb
new file mode 100644
index 0000000..603914f
--- /dev/null
+++ b/app/views/medications/show.html.erb
@@ -0,0 +1,10 @@
+<%= notice %>
+
+<%= render @medication %>
+
+
+ <%= link_to "Edit this medication", edit_medication_path(@medication) %> |
+ <%= link_to "Back to medications", medications_path %>
+
+ <%= button_to "Destroy this medication", @medication, method: :delete %>
+
diff --git a/app/views/medications/show.json.jbuilder b/app/views/medications/show.json.jbuilder
new file mode 100644
index 0000000..b2ae681
--- /dev/null
+++ b/app/views/medications/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "medications/medication", medication: @medication
diff --git a/app/views/people/_form.html.erb b/app/views/people/_form.html.erb
new file mode 100644
index 0000000..0d19245
--- /dev/null
+++ b/app/views/people/_form.html.erb
@@ -0,0 +1,47 @@
+<%= form_with(model: person) do |form| %>
+ <% if person.errors.any? %>
+
+
<%= pluralize(person.errors.count, "error") %> prohibited this person from being saved:
+
+
+ <% person.errors.each do |error| %>
+ - <%= error.full_message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= form.label :first_name, style: "display: block" %>
+ <%= form.text_field :first_name %>
+
+
+
+ <%= form.label :last_name, style: "display: block" %>
+ <%= form.text_field :last_name %>
+
+
+
+ <%= form.label :date_of_birth, style: "display: block" %>
+ <%= form.date_field :date_of_birth %>
+
+
+
+ <%= form.label :social_security_number, style: "display: block" %>
+ <%= form.text_field :social_security_number %>
+
+
+
+ <%= form.label :email, style: "display: block" %>
+ <%= form.text_field :email %>
+
+
+
+ <%= form.label :relationship_id, style: "display: block" %>
+ <%= form.text_field :relationship_id %>
+
+
+
+ <%= form.submit %>
+
+<% end %>
diff --git a/app/views/people/_person.html.erb b/app/views/people/_person.html.erb
new file mode 100644
index 0000000..36f544d
--- /dev/null
+++ b/app/views/people/_person.html.erb
@@ -0,0 +1,32 @@
+
+
+ First name:
+ <%= person.first_name %>
+
+
+
+ Last name:
+ <%= person.last_name %>
+
+
+
+ Date of birth:
+ <%= person.date_of_birth %>
+
+
+
+ Social security number:
+ <%= person.social_security_number %>
+
+
+
+ Email:
+ <%= person.email %>
+
+
+
+ Relationship:
+ <%= person.relationship_id %>
+
+
+
diff --git a/app/views/people/_person.json.jbuilder b/app/views/people/_person.json.jbuilder
new file mode 100644
index 0000000..95ae139
--- /dev/null
+++ b/app/views/people/_person.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! person, :id, :first_name, :last_name, :date_of_birth, :social_security_number, :email, :relationship_id, :created_at, :updated_at
+json.url person_url(person, format: :json)
diff --git a/app/views/people/edit.html.erb b/app/views/people/edit.html.erb
new file mode 100644
index 0000000..82fbae5
--- /dev/null
+++ b/app/views/people/edit.html.erb
@@ -0,0 +1,12 @@
+<% content_for :title, "Editing person" %>
+
+Editing person
+
+<%= render "form", person: @person %>
+
+
+
+
+ <%= link_to "Show this person", @person %> |
+ <%= link_to "Back to people", people_path %>
+
diff --git a/app/views/people/index.html.erb b/app/views/people/index.html.erb
new file mode 100644
index 0000000..c4611fb
--- /dev/null
+++ b/app/views/people/index.html.erb
@@ -0,0 +1,16 @@
+<%= notice %>
+
+<% content_for :title, "People" %>
+
+People
+
+
+ <% @people.each do |person| %>
+ <%= render person %>
+
+ <%= link_to "Show this person", person %>
+
+ <% end %>
+
+
+<%= link_to "New person", new_person_path %>
diff --git a/app/views/people/index.json.jbuilder b/app/views/people/index.json.jbuilder
new file mode 100644
index 0000000..14d7899
--- /dev/null
+++ b/app/views/people/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @people, partial: "people/person", as: :person
diff --git a/app/views/people/new.html.erb b/app/views/people/new.html.erb
new file mode 100644
index 0000000..d26f879
--- /dev/null
+++ b/app/views/people/new.html.erb
@@ -0,0 +1,11 @@
+<% content_for :title, "New person" %>
+
+New person
+
+<%= render "form", person: @person %>
+
+
+
+
+ <%= link_to "Back to people", people_path %>
+
diff --git a/app/views/people/show.html.erb b/app/views/people/show.html.erb
new file mode 100644
index 0000000..5fa7251
--- /dev/null
+++ b/app/views/people/show.html.erb
@@ -0,0 +1,10 @@
+<%= notice %>
+
+<%= render @person %>
+
+
+ <%= link_to "Edit this person", edit_person_path(@person) %> |
+ <%= link_to "Back to people", people_path %>
+
+ <%= button_to "Destroy this person", @person, method: :delete %>
+
diff --git a/app/views/people/show.json.jbuilder b/app/views/people/show.json.jbuilder
new file mode 100644
index 0000000..cf0f817
--- /dev/null
+++ b/app/views/people/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "people/person", person: @person
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
new file mode 100644
index 0000000..1c2def7
--- /dev/null
+++ b/config/initializers/devise.rb
@@ -0,0 +1,316 @@
+# frozen_string_literal: true
+
+# Assuming you have not yet modified this file, each configuration option below
+# is set to its default value. Note that some are commented out while others
+# are not: uncommented lines are intended to protect your configuration from
+# breaking changes in upgrades (i.e., in the event that future versions of
+# Devise change the default values for those options).
+#
+# Use this hook to configure devise mailer, warden hooks and so forth.
+# Many of these configuration options can be set straight in your model.
+Devise.setup do |config|
+ # The secret key used by Devise. Devise uses this key to generate
+ # random tokens. Changing this key will render invalid all existing
+ # confirmation, reset password and unlock tokens in the database.
+ # Devise will use the `secret_key_base` as its `secret_key`
+ # by default. You can change it below and use your own secret key.
+ # config.secret_key = 'be48cc765be7e2ec33ba15d2a1fbdac62ecd68ea971d1294f8bfaf1dc502921adcbb9a42180741dfe89dccc80c2a1d9d4943cc6c288ce8a6443cb404505e22b3'
+
+ # ==> Controller configuration
+ # Configure the parent class to the devise controllers.
+ # config.parent_controller = 'DeviseController'
+
+ # ==> Mailer Configuration
+ # Configure the e-mail address which will be shown in Devise::Mailer,
+ # note that it will be overwritten if you use your own mailer class
+ # with default "from" parameter.
+ config.mailer_sender = "please-change-me-at-config-initializers-devise@example.com"
+
+ # Configure the class responsible to send e-mails.
+ # config.mailer = 'Devise::Mailer'
+
+ # Configure the parent class responsible to send e-mails.
+ # config.parent_mailer = 'ActionMailer::Base'
+
+ # ==> ORM configuration
+ # Load and configure the ORM. Supports :active_record (default) and
+ # :mongoid (bson_ext recommended) by default. Other ORMs may be
+ # available as additional gems.
+ require "devise/orm/active_record"
+
+ # ==> Configuration for any authentication mechanism
+ # Configure which keys are used when authenticating a user. The default is
+ # just :email. You can configure it to use [:username, :subdomain], so for
+ # authenticating a user, both parameters are required. Remember that those
+ # parameters are used only when authenticating and not when retrieving from
+ # session. If you need permissions, you should implement that in a before filter.
+ # You can also supply a hash where the value is a boolean determining whether
+ # or not authentication should be aborted when the value is not present.
+ # config.authentication_keys = [:email]
+
+ # Configure parameters from the request object used for authentication. Each entry
+ # given should be a request method and it will automatically be passed to the
+ # find_for_authentication method and considered in your model lookup. For instance,
+ # if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
+ # The same considerations mentioned for authentication_keys also apply to request_keys.
+ # config.request_keys = []
+
+ # Configure which authentication keys should be case-insensitive.
+ # These keys will be downcased upon creating or modifying a user and when used
+ # to authenticate or find a user. Default is :email.
+ config.case_insensitive_keys = [ :email ]
+
+ # Configure which authentication keys should have whitespace stripped.
+ # These keys will have whitespace before and after removed upon creating or
+ # modifying a user and when used to authenticate or find a user. Default is :email.
+ config.strip_whitespace_keys = [ :email ]
+
+ # Tell if authentication through request.params is enabled. True by default.
+ # It can be set to an array that will enable params authentication only for the
+ # given strategies, for example, `config.params_authenticatable = [:database]` will
+ # enable it only for database (email + password) authentication.
+ # config.params_authenticatable = true
+
+ # Tell if authentication through HTTP Auth is enabled. False by default.
+ # It can be set to an array that will enable http authentication only for the
+ # given strategies, for example, `config.http_authenticatable = [:database]` will
+ # enable it only for database authentication.
+ # For API-only applications to support authentication "out-of-the-box", you will likely want to
+ # enable this with :database unless you are using a custom strategy.
+ # The supported strategies are:
+ # :database = Support basic authentication with authentication key + password
+ # config.http_authenticatable = false
+
+ # If 401 status code should be returned for AJAX requests. True by default.
+ # config.http_authenticatable_on_xhr = true
+
+ # The realm used in Http Basic Authentication. 'Application' by default.
+ # config.http_authentication_realm = 'Application'
+
+ # It will change confirmation, password recovery and other workflows
+ # to behave the same regardless if the e-mail provided was right or wrong.
+ # Does not affect registerable.
+ # config.paranoid = true
+
+ # By default Devise will store the user in session. You can skip storage for
+ # particular strategies by setting this option.
+ # Notice that if you are skipping storage for all authentication paths, you
+ # may want to disable generating routes to Devise's sessions controller by
+ # passing skip: :sessions to `devise_for` in your config/routes.rb
+ config.skip_session_storage = [ :http_auth ]
+
+ # By default, Devise cleans up the CSRF token on authentication to
+ # avoid CSRF token fixation attacks. This means that, when using AJAX
+ # requests for sign in and sign up, you need to get a new CSRF token
+ # from the server. You can disable this option at your own risk.
+ # config.clean_up_csrf_token_on_authentication = true
+
+ # When false, Devise will not attempt to reload routes on eager load.
+ # This can reduce the time taken to boot the app but if your application
+ # requires the Devise mappings to be loaded during boot time the application
+ # won't boot properly.
+ # config.reload_routes = true
+
+ # ==> Configuration for :database_authenticatable
+ # For bcrypt, this is the cost for hashing the password and defaults to 12. If
+ # using other algorithms, it sets how many times you want the password to be hashed.
+ # The number of stretches used for generating the hashed password are stored
+ # with the hashed password. This allows you to change the stretches without
+ # invalidating existing passwords.
+ #
+ # Limiting the stretches to just one in testing will increase the performance of
+ # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
+ # a value less than 10 in other environments. Note that, for bcrypt (the default
+ # algorithm), the cost increases exponentially with the number of stretches (e.g.
+ # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
+ config.stretches = Rails.env.test? ? 1 : 12
+
+ # Set up a pepper to generate the hashed password.
+ # config.pepper = '127706bcb62f32c2160abb282491c2810ecf01a418769b330824734bb3a5bbf935ef806c4f977db9681c9aaa31c01e773ee372c40f94b5326690c7d9c7c37c6b'
+
+ # Send a notification to the original email when the user's email is changed.
+ # config.send_email_changed_notification = false
+
+ # Send a notification email when the user's password is changed.
+ # config.send_password_change_notification = false
+
+ # ==> Configuration for :confirmable
+ # A period that the user is allowed to access the website even without
+ # confirming their account. For instance, if set to 2.days, the user will be
+ # able to access the website for two days without confirming their account,
+ # access will be blocked just in the third day.
+ # You can also set it to nil, which will allow the user to access the website
+ # without confirming their account.
+ # Default is 0.days, meaning the user cannot access the website without
+ # confirming their account.
+ config.allow_unconfirmed_access_for = nil
+
+ # A period that the user is allowed to confirm their account before their
+ # token becomes invalid. For example, if set to 3.days, the user can confirm
+ # their account within 3 days after the mail was sent, but on the fourth day
+ # their account can't be confirmed with the token any more.
+ # Default is nil, meaning there is no restriction on how long a user can take
+ # before confirming their account.
+ # config.confirm_within = 3.days
+
+ # If true, requires any email changes to be confirmed (exactly the same way as
+ # initial account confirmation) to be applied. Requires additional unconfirmed_email
+ # db field (see migrations). Until confirmed, new email is stored in
+ # unconfirmed_email column, and copied to email column on successful confirmation.
+ # Also, when used in conjunction with `send_email_changed_notification`,
+ # the notification is sent to the original email when the change is requested,
+ # not when the unconfirmed email is confirmed.
+ config.reconfirmable = true
+
+ # Defines which key will be used when confirming an account
+ # config.confirmation_keys = [:email]
+
+ # ==> Configuration for :rememberable
+ # The time the user will be remembered without asking for credentials again.
+ # config.remember_for = 2.weeks
+
+ # Invalidates all the remember me tokens when the user signs out.
+ config.expire_all_remember_me_on_sign_out = true
+
+ # If true, extends the user's remember period when remembered via cookie.
+ # config.extend_remember_period = false
+
+ # Options to be passed to the created cookie. For instance, you can set
+ # secure: true in order to force SSL only cookies.
+ # config.rememberable_options = {}
+
+ # ==> Configuration for :validatable
+ # Range for password length.
+ config.password_length = 6..128
+
+ # Email regex used to validate email formats. It simply asserts that
+ # one (and only one) @ exists in the given string. This is mainly
+ # to give user feedback and not to assert the e-mail validity.
+ config.email_regexp = /\A[^@\s]+@[^@\s]+\z/
+
+ # ==> Configuration for :timeoutable
+ # The time you want to timeout the user session without activity. After this
+ # time the user will be asked for credentials again. Default is 30 minutes.
+ # config.timeout_in = 30.minutes
+
+ # ==> Configuration for :lockable
+ # Defines which strategy will be used to lock an account.
+ # :failed_attempts = Locks an account after a number of failed attempts to sign in.
+ # :none = No lock strategy. You should handle locking by yourself.
+ # config.lock_strategy = :failed_attempts
+
+ # Defines which key will be used when locking and unlocking an account
+ # config.unlock_keys = [:email]
+
+ # Defines which strategy will be used to unlock an account.
+ # :email = Sends an unlock link to the user email
+ # :time = Re-enables login after a certain amount of time (see :unlock_in below)
+ # :both = Enables both strategies
+ # :none = No unlock strategy. You should handle unlocking by yourself.
+ # config.unlock_strategy = :both
+
+ # Number of authentication tries before locking an account if lock_strategy
+ # is failed attempts.
+ # config.maximum_attempts = 20
+
+ # Time interval to unlock the account if :time is enabled as unlock_strategy.
+ # config.unlock_in = 1.hour
+
+ # Warn on the last attempt before the account is locked.
+ # config.last_attempt_warning = true
+
+ # ==> Configuration for :recoverable
+ #
+ # Defines which key will be used when recovering the password for an account
+ config.reset_password_keys = [:email]
+
+ # Time interval you can reset your password with a reset password key.
+ # Don't put a too small interval or your users won't have the time to
+ # change their passwords.
+ config.reset_password_within = 6.hours
+
+ # When set to false, does not sign a user in automatically after their password is
+ # reset. Defaults to true, so a user is signed in automatically after a reset.
+ # config.sign_in_after_reset_password = true
+
+ # ==> Configuration for :encryptable
+ # Allow you to use another hashing or encryption algorithm besides bcrypt (default).
+ # You can use :sha1, :sha512 or algorithms from others authentication tools as
+ # :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20
+ # for default behavior) and :restful_authentication_sha1 (then you should set
+ # stretches to 10, and copy REST_AUTH_SITE_KEY to pepper).
+ #
+ # Require the `devise-encryptable` gem when using anything other than bcrypt
+ # config.encryptor = :sha512
+
+ # ==> Scopes configuration
+ # Turn scoped views on. Before rendering "sessions/new", it will first check for
+ # "users/sessions/new". It's turned off by default because it's slower if you
+ # are using only default views.
+ # config.scoped_views = false
+
+ # Configure the default scope given to Warden. By default it's the first
+ # devise role declared in your routes (usually :user).
+ # config.default_scope = :user
+
+ # Set this configuration to false if you want /users/sign_out to sign out
+ # only the current scope. By default, Devise signs out all scopes.
+ # config.sign_out_all_scopes = true
+
+ # ==> Navigation configuration
+ # Lists the formats that should be treated as navigational. Formats like
+ # :html should redirect to the sign in page when the user does not have
+ # access, but formats like :xml or :json, should return 401.
+ #
+ # If you have any extra navigational formats, like :iphone or :mobile, you
+ # should add them to the navigational formats lists.
+ #
+ # The "*/*" below is required to match Internet Explorer requests.
+ # config.navigational_formats = ['*/*', :html, :turbo_stream]
+
+ # The default HTTP method used to sign out a resource. Default is :delete.
+ config.sign_out_via = :delete
+
+ # ==> OmniAuth
+ # Add a new OmniAuth provider. Check the wiki for more information on setting
+ # up on your models and hooks.
+ # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
+
+ # ==> Warden configuration
+ # If you want to use other strategies, that are not supported by Devise, or
+ # change the failure app, you can configure them inside the config.warden block.
+ #
+ # config.warden do |warden_config|
+ # warden_config.intercept_401 = false
+ # warden_config.default_strategies(scope: :user).unshift :some_external_strategy
+ # end
+
+ # ==> Mountable engine configurations
+ # When using Devise inside an engine, let's call it `MyEngine`, and this engine
+ # is mountable, there are some extra configurations to be taken into account.
+ # The following options are available, assuming the engine is mounted as:
+ #
+ # mount MyEngine, at: '/my_engine'
+ #
+ # The router that invoked `devise_for`, in the example above, would be:
+ # config.router_name = :my_engine
+ #
+ # When using OmniAuth, Devise cannot automatically set OmniAuth path,
+ # so you need to do it manually. For the users scope, it would be:
+ # config.omniauth_path_prefix = '/my_engine/users/auth'
+
+ # ==> Hotwire/Turbo configuration
+ # When using Devise with Hotwire/Turbo, the http status for error responses
+ # and some redirects must match the following. The default in Devise for existing
+ # apps is `200 OK` and `302 Found` respectively, but new apps are generated with
+ # these new defaults that match Hotwire/Turbo behavior.
+ # Note: These might become the new default in future versions of Devise.
+ config.responder.error_status = :unprocessable_content
+ config.responder.redirect_status = :see_other
+
+ # ==> Configuration for :registerable
+
+ # When set to false, does not sign a user in automatically after their password is
+ # changed. Defaults to true, so a user is signed in automatically after changing a password.
+ config.sign_in_after_change_password = true
+end
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
new file mode 100644
index 0000000..260e1c4
--- /dev/null
+++ b/config/locales/devise.en.yml
@@ -0,0 +1,65 @@
+# Additional translations at https://github.com/heartcombo/devise/wiki/I18n
+
+en:
+ devise:
+ confirmations:
+ confirmed: "Your email address has been successfully confirmed."
+ send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
+ send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
+ failure:
+ already_authenticated: "You are already signed in."
+ inactive: "Your account is not activated yet."
+ invalid: "Invalid %{authentication_keys} or password."
+ locked: "Your account is locked."
+ last_attempt: "You have one more attempt before your account is locked."
+ not_found_in_database: "Invalid %{authentication_keys} or password."
+ timeout: "Your session expired. Please sign in again to continue."
+ unauthenticated: "You need to sign in or sign up before continuing."
+ unconfirmed: "You have to confirm your email address before continuing."
+ mailer:
+ confirmation_instructions:
+ subject: "Confirmation instructions"
+ reset_password_instructions:
+ subject: "Reset password instructions"
+ unlock_instructions:
+ subject: "Unlock instructions"
+ email_changed:
+ subject: "Email Changed"
+ password_change:
+ subject: "Password Changed"
+ omniauth_callbacks:
+ failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
+ success: "Successfully authenticated from %{kind} account."
+ passwords:
+ no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
+ send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
+ send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
+ updated: "Your password has been changed successfully. You are now signed in."
+ updated_not_active: "Your password has been changed successfully."
+ registrations:
+ destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
+ signed_up: "Welcome! You have signed up successfully."
+ signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
+ signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
+ signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
+ update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address."
+ updated: "Your account has been updated successfully."
+ updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again."
+ sessions:
+ signed_in: "Signed in successfully."
+ signed_out: "Signed out successfully."
+ already_signed_out: "Signed out successfully."
+ unlocks:
+ send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
+ send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
+ unlocked: "Your account has been unlocked successfully. Please sign in to continue."
+ errors:
+ messages:
+ already_confirmed: "was already confirmed, please try signing in"
+ confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
+ expired: "has expired, please request a new one"
+ not_found: "not found"
+ not_locked: "was not locked"
+ not_saved:
+ one: "1 error prohibited this %{resource} from being saved:"
+ other: "%{count} errors prohibited this %{resource} from being saved:"
diff --git a/config/routes.rb b/config/routes.rb
index 4368cb6..499ad5c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,8 @@
Rails.application.routes.draw do
+ devise_for :users
+ resources :medications
+ resources :medication_types
+ resources :people
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# JSON API consumed by the Expo app in mobile/.
@@ -24,5 +28,6 @@
# get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker
# Defines the root path route ("/")
- # root "posts#index"
+ root "home#index"
+ get "world" => "home#world"
end
diff --git a/db/migrate/20260828183715_create_people.rb b/db/migrate/20260828183715_create_people.rb
new file mode 100644
index 0000000..159c2c8
--- /dev/null
+++ b/db/migrate/20260828183715_create_people.rb
@@ -0,0 +1,14 @@
+class CreatePeople < ActiveRecord::Migration[8.1]
+ def change
+ create_table :people do |t|
+ t.string :first_name
+ t.string :last_name
+ t.date :date_of_birth
+ t.string :social_security_number
+ t.string :email
+ t.belongs_to :relationship, null: false, foreign_key: true
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20260828184216_create_medication_types.rb b/db/migrate/20260828184216_create_medication_types.rb
new file mode 100644
index 0000000..9a71d5d
--- /dev/null
+++ b/db/migrate/20260828184216_create_medication_types.rb
@@ -0,0 +1,9 @@
+class CreateMedicationTypes < ActiveRecord::Migration[8.1]
+ def change
+ create_table :medication_types do |t|
+ t.string :name
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20260828193338_devise_create_users.rb b/db/migrate/20260828193338_devise_create_users.rb
new file mode 100644
index 0000000..b237e7a
--- /dev/null
+++ b/db/migrate/20260828193338_devise_create_users.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+class DeviseCreateUsers < ActiveRecord::Migration[8.1]
+ def change
+ create_table :users do |t|
+ ## Database authenticatable
+ t.string :email, null: false
+ t.string :encrypted_password, null: false
+
+ ## Recoverable
+ t.string :reset_password_token
+ t.datetime :reset_password_sent_at
+
+ ## Rememberable
+ t.datetime :remember_created_at
+
+ ## Trackable
+ t.integer :sign_in_count, default: 0, null: false
+ t.datetime :current_sign_in_at
+ t.datetime :last_sign_in_at
+ t.string :current_sign_in_ip
+ t.string :last_sign_in_ip
+
+ ## Confirmable
+ t.string :confirmation_token
+ t.datetime :confirmed_at
+ t.datetime :confirmation_sent_at
+ t.string :unconfirmed_email # Only if using reconfirmable
+
+ ## Lockable
+ t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
+ t.string :unlock_token # Only if unlock strategy is :email or :both
+ t.datetime :locked_at
+
+
+ t.timestamps null: false
+ end
+
+ add_index :users, :email, unique: true
+ add_index :users, :reset_password_token, unique: true
+ add_index :users, :confirmation_token, unique: true
+ add_index :users, :unlock_token, unique: true
+ end
+end
diff --git a/db/migrate/20260829113658_create_medications.rb b/db/migrate/20260829113658_create_medications.rb
new file mode 100644
index 0000000..613848b
--- /dev/null
+++ b/db/migrate/20260829113658_create_medications.rb
@@ -0,0 +1,20 @@
+class CreateMedications < ActiveRecord::Migration[8.1]
+ def change
+ create_table :medications do |t|
+ t.string :name
+ t.belongs_to :medication_type, null: false, foreign_key: true
+ t.boolean :current
+ t.string :dosage
+ t.string :frequency
+ t.string :time_of_day
+ t.string :form
+ t.text :purpose
+ t.date :start_date
+ t.date :stop_date
+ t.string :refill
+ t.text :notes
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20260829113836_create_relationships.rb b/db/migrate/20260829113836_create_relationships.rb
new file mode 100644
index 0000000..e81702b
--- /dev/null
+++ b/db/migrate/20260829113836_create_relationships.rb
@@ -0,0 +1,9 @@
+class CreateRelationships < ActiveRecord::Migration[8.1]
+ def change
+ create_table :relationships do |t|
+ t.string :name
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 8e5e9b6..c2e519c 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,11 +10,82 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[8.1].define(version: 2026_08_02_160512) do
+ActiveRecord::Schema[8.1].define(version: 2026_08_29_113836) do
+ create_table "medication_types", force: :cascade do |t|
+ t.datetime "created_at", null: false
+ t.string "name"
+ t.datetime "updated_at", null: false
+ end
+
+ create_table "medications", force: :cascade do |t|
+ t.datetime "created_at", null: false
+ t.boolean "current"
+ t.string "dosage"
+ t.string "form"
+ t.string "frequency"
+ t.integer "medication_type_id", null: false
+ t.string "name"
+ t.text "notes"
+ t.text "purpose"
+ t.string "refill"
+ t.date "start_date"
+ t.date "stop_date"
+ t.string "time_of_day"
+ t.datetime "updated_at", null: false
+ t.index ["medication_type_id"], name: "index_medications_on_medication_type_id"
+ end
+
+ create_table "people", force: :cascade do |t|
+ t.datetime "created_at", null: false
+ t.date "date_of_birth"
+ t.string "email"
+ t.string "first_name"
+ t.string "last_name"
+ t.integer "relationship_id", null: false
+ t.string "social_security_number"
+ t.datetime "updated_at", null: false
+ t.index ["relationship_id"], name: "index_people_on_relationship_id"
+ end
+
+ create_table "relationships", force: :cascade do |t|
+ t.datetime "created_at", null: false
+ t.string "name"
+ t.datetime "updated_at", null: false
+ end
+
create_table "tasks", force: :cascade do |t|
t.boolean "completed", default: false, null: false
t.datetime "created_at", null: false
t.string "title", null: false
t.datetime "updated_at", null: false
end
+
+ create_table "users", force: :cascade do |t|
+ t.datetime "confirmation_sent_at"
+ t.string "confirmation_token"
+ t.datetime "confirmed_at"
+ t.datetime "created_at", null: false
+ t.datetime "current_sign_in_at"
+ t.string "current_sign_in_ip"
+ t.string "email", null: false
+ t.string "encrypted_password", null: false
+ t.integer "failed_attempts", default: 0, null: false
+ t.datetime "last_sign_in_at"
+ t.string "last_sign_in_ip"
+ t.datetime "locked_at"
+ t.datetime "remember_created_at"
+ t.datetime "reset_password_sent_at"
+ t.string "reset_password_token"
+ t.integer "sign_in_count", default: 0, null: false
+ t.string "unconfirmed_email"
+ t.string "unlock_token"
+ t.datetime "updated_at", null: false
+ t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
+ t.index ["email"], name: "index_users_on_email", unique: true
+ t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
+ t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true
+ end
+
+ add_foreign_key "medications", "medication_types"
+ add_foreign_key "people", "relationships"
end
diff --git a/mise.toml b/mise.toml
new file mode 100644
index 0000000..2f58cce
--- /dev/null
+++ b/mise.toml
@@ -0,0 +1,3 @@
+[tools]
+node = "latest"
+ruby = "4.0.5"
diff --git a/test/controllers/home_controller_test.rb b/test/controllers/home_controller_test.rb
new file mode 100644
index 0000000..eac0e33
--- /dev/null
+++ b/test/controllers/home_controller_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class HomeControllerTest < ActionDispatch::IntegrationTest
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/controllers/medication_types_controller_test.rb b/test/controllers/medication_types_controller_test.rb
new file mode 100644
index 0000000..684c1a4
--- /dev/null
+++ b/test/controllers/medication_types_controller_test.rb
@@ -0,0 +1,48 @@
+require "test_helper"
+
+class MedicationTypesControllerTest < ActionDispatch::IntegrationTest
+ setup do
+ @medication_type = medication_types(:one)
+ end
+
+ test "should get index" do
+ get medication_types_url
+ assert_response :success
+ end
+
+ test "should get new" do
+ get new_medication_type_url
+ assert_response :success
+ end
+
+ test "should create medication_type" do
+ assert_difference("MedicationType.count") do
+ post medication_types_url, params: { medication_type: { name: @medication_type.name } }
+ end
+
+ assert_redirected_to medication_type_url(MedicationType.last)
+ end
+
+ test "should show medication_type" do
+ get medication_type_url(@medication_type)
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get edit_medication_type_url(@medication_type)
+ assert_response :success
+ end
+
+ test "should update medication_type" do
+ patch medication_type_url(@medication_type), params: { medication_type: { name: @medication_type.name } }
+ assert_redirected_to medication_type_url(@medication_type)
+ end
+
+ test "should destroy medication_type" do
+ assert_difference("MedicationType.count", -1) do
+ delete medication_type_url(@medication_type)
+ end
+
+ assert_redirected_to medication_types_url
+ end
+end
diff --git a/test/controllers/medications_controller_test.rb b/test/controllers/medications_controller_test.rb
new file mode 100644
index 0000000..58f7f29
--- /dev/null
+++ b/test/controllers/medications_controller_test.rb
@@ -0,0 +1,48 @@
+require "test_helper"
+
+class MedicationsControllerTest < ActionDispatch::IntegrationTest
+ setup do
+ @medication = medications(:one)
+ end
+
+ test "should get index" do
+ get medications_url
+ assert_response :success
+ end
+
+ test "should get new" do
+ get new_medication_url
+ assert_response :success
+ end
+
+ test "should create medication" do
+ assert_difference("Medication.count") do
+ post medications_url, params: { medication: { current: @medication.current, dosage: @medication.dosage, form: @medication.form, frequency: @medication.frequency, medication_type_id: @medication.medication_type_id, name: @medication.name, notes: @medication.notes, purpose: @medication.purpose, refill: @medication.refill, start_date: @medication.start_date, stop_date: @medication.stop_date, time_of_day: @medication.time_of_day } }
+ end
+
+ assert_redirected_to medication_url(Medication.last)
+ end
+
+ test "should show medication" do
+ get medication_url(@medication)
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get edit_medication_url(@medication)
+ assert_response :success
+ end
+
+ test "should update medication" do
+ patch medication_url(@medication), params: { medication: { current: @medication.current, dosage: @medication.dosage, form: @medication.form, frequency: @medication.frequency, medication_type_id: @medication.medication_type_id, name: @medication.name, notes: @medication.notes, purpose: @medication.purpose, refill: @medication.refill, start_date: @medication.start_date, stop_date: @medication.stop_date, time_of_day: @medication.time_of_day } }
+ assert_redirected_to medication_url(@medication)
+ end
+
+ test "should destroy medication" do
+ assert_difference("Medication.count", -1) do
+ delete medication_url(@medication)
+ end
+
+ assert_redirected_to medications_url
+ end
+end
diff --git a/test/controllers/people_controller_test.rb b/test/controllers/people_controller_test.rb
new file mode 100644
index 0000000..3dfc530
--- /dev/null
+++ b/test/controllers/people_controller_test.rb
@@ -0,0 +1,48 @@
+require "test_helper"
+
+class PeopleControllerTest < ActionDispatch::IntegrationTest
+ setup do
+ @person = people(:one)
+ end
+
+ test "should get index" do
+ get people_url
+ assert_response :success
+ end
+
+ test "should get new" do
+ get new_person_url
+ assert_response :success
+ end
+
+ test "should create person" do
+ assert_difference("Person.count") do
+ post people_url, params: { person: { date_of_birth: @person.date_of_birth, email: @person.email, first_name: @person.first_name, last_name: @person.last_name, relationship_id: @person.relationship_id, social_security_number: @person.social_security_number } }
+ end
+
+ assert_redirected_to person_url(Person.last)
+ end
+
+ test "should show person" do
+ get person_url(@person)
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get edit_person_url(@person)
+ assert_response :success
+ end
+
+ test "should update person" do
+ patch person_url(@person), params: { person: { date_of_birth: @person.date_of_birth, email: @person.email, first_name: @person.first_name, last_name: @person.last_name, relationship_id: @person.relationship_id, social_security_number: @person.social_security_number } }
+ assert_redirected_to person_url(@person)
+ end
+
+ test "should destroy person" do
+ assert_difference("Person.count", -1) do
+ delete person_url(@person)
+ end
+
+ assert_redirected_to people_url
+ end
+end
diff --git a/test/fixtures/medication_types.yml b/test/fixtures/medication_types.yml
new file mode 100644
index 0000000..7d41224
--- /dev/null
+++ b/test/fixtures/medication_types.yml
@@ -0,0 +1,7 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ name: MyString
+
+two:
+ name: MyString
diff --git a/test/fixtures/medications.yml b/test/fixtures/medications.yml
new file mode 100644
index 0000000..2487777
--- /dev/null
+++ b/test/fixtures/medications.yml
@@ -0,0 +1,29 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ name: MyString
+ medication_type: two
+ current: false
+ dosage: MyString
+ frequency: MyString
+ time_of_day: MyString
+ form: MyString
+ purpose: MyText
+ start_date: 2026-08-29
+ stop_date: 2026-08-29
+ refill: MyString
+ notes: MyText
+
+two:
+ name: MyString
+ medication_type: two
+ current: false
+ dosage: MyString
+ frequency: MyString
+ time_of_day: MyString
+ form: MyString
+ purpose: MyText
+ start_date: 2026-08-29
+ stop_date: 2026-08-29
+ refill: MyString
+ notes: MyText
diff --git a/test/fixtures/people.yml b/test/fixtures/people.yml
new file mode 100644
index 0000000..a6957bc
--- /dev/null
+++ b/test/fixtures/people.yml
@@ -0,0 +1,17 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ first_name: MyString
+ last_name: MyString
+ date_of_birth: 2026-08-28
+ social_security_number: MyString
+ email: MyString
+ relationship: one
+
+two:
+ first_name: MyString
+ last_name: MyString
+ date_of_birth: 2026-08-28
+ social_security_number: MyString
+ email: MyString
+ relationship: two
diff --git a/test/fixtures/relationships.yml b/test/fixtures/relationships.yml
new file mode 100644
index 0000000..7d41224
--- /dev/null
+++ b/test/fixtures/relationships.yml
@@ -0,0 +1,7 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ name: MyString
+
+two:
+ name: MyString
diff --git a/test/models/medication_test.rb b/test/models/medication_test.rb
new file mode 100644
index 0000000..8fcd105
--- /dev/null
+++ b/test/models/medication_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class MedicationTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/medication_type_test.rb b/test/models/medication_type_test.rb
new file mode 100644
index 0000000..6417e1a
--- /dev/null
+++ b/test/models/medication_type_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class MedicationTypeTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/person_test.rb b/test/models/person_test.rb
new file mode 100644
index 0000000..357c9af
--- /dev/null
+++ b/test/models/person_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class PersonTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/relationship_test.rb b/test/models/relationship_test.rb
new file mode 100644
index 0000000..6b1491a
--- /dev/null
+++ b/test/models/relationship_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class RelationshipTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/user_test.rb b/test/models/user_test.rb
new file mode 100644
index 0000000..5c07f49
--- /dev/null
+++ b/test/models/user_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class UserTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end