Fixed my problem and now have correctly linked multiple form submission to more than one model and am able to update all relevant forms within the model.

This commit is contained in:
Ben 2024-02-17 02:42:12 -06:00
parent 84c0092701
commit cf759a4cc7
25 changed files with 253 additions and 90 deletions

View File

@ -102,6 +102,12 @@ class EmployersController < ApplicationController
redirect_to some_path, alert: 'Employer not found.' redirect_to some_path, alert: 'Employer not found.'
end end
def onboarding
@employer = employer.find(params[:id])
@onboarding_items = @employer.onboarding_items.includes(:form)
end
private private
def set_employer def set_employer

View File

@ -43,9 +43,10 @@ class FormsController < ApplicationController
end end
def form_params def form_params
params.require(:form).permit(:name, :required, :program, :role) params.require(:form).permit(:name, :required, :program, role_ids: [])
end end
def check_admin def check_admin
redirect_to(root_path, alert: "Not authorized") unless current_user.admin? redirect_to(root_path, alert: "Not authorized") unless current_user.admin?
end end

View File

@ -1,5 +1,5 @@
class OnboardingsController < ApplicationController class OnboardingsController < ApplicationController
before_action :set_owner before_action :set_owner, only: [:index, :submit_onboarding]
def index def index
# Make sure to set @owner first. If not found, you should redirect or handle the error appropriately. # Make sure to set @owner first. If not found, you should redirect or handle the error appropriately.
@ -34,31 +34,50 @@ class OnboardingsController < ApplicationController
end end
def submit_onboarding def submit_onboarding
params[:onboarding_items].each do |id, item_params| @owner = find_owner
onboarding_item = OnboardingItem.find(id) onboarding_items_params.values.each do |item_params|
onboarding_item.update(item_params.permit(:note, :date_completed)) item = OnboardingItem.find_or_initialize_by(id: item_params.delete(:id))
item.assign_attributes(item_params)
item.owner = @owner
item.save
end end
redirect_to polymorphic_path([@owner]), notice: 'Onboarding information updated successfully.' redirect_to polymorphic_path(@owner), notice: 'Onboarding information updated successfully.'
end end
private private
def set_owner def set_owner
# Example: finds "participant_id", sets @owner to the corresponding Participant object
params.each do |name, value| params.each do |name, value|
if name =~ /(.+)_id$/ if name =~ /(.+)_id$/
model = $1.classify.constantize model_name = name.match(/(.+)_id$/)[1].classify
@owner = model.find_by(id: value) @owner = model_name.constantize.find(value)
break if @owner # Break if owner is found break
end end
end end
redirect_to(root_path, alert: "Owner not found.") unless @owner unless @owner
redirect_to root_path, alert: "Owner not found."
end
end end
def onboarding_items_params def onboarding_items_params
# Ensure you permit the correct parameters based on your form fields params.permit(onboarding_items: [:id, :note, :date_completed]).fetch(:onboarding_items, {})
params.require(:onboarding_item).permit(:form_id, :note, :date_completed) end
def find_owner
# Check each expected owner type and find the corresponding record
if params[:participant_id]
@owner = Participant.find(params[:participant_id])
elsif params[:employer_id]
@owner = Employer.find(params[:employer_id])
elsif params[:worker_id]
@owner = Worker.find(params[:worker_id])
elsif params[:vendor_id]
@owner = Vendor.find(params[:vendor_id])
else
# Handle the case where no recognized owner parameter is provided
redirect_to root_path, alert: "Owner not found."
return nil
end
end end
end end

View File

@ -1,13 +1,16 @@
module OnboardingsHelper module OnboardingsHelper
def submit_onboarding_path_helper(owner) def submit_onboarding_polymorphic_path(owner)
case owner case owner
when Participant when Participant
submit_onboarding_participant_onboardings_path(owner) submit_onboarding_participant_onboardings_path(owner)
when Worker when Worker
submit_onboarding_worker_onboardings_path(owner) submit_onboarding_worker_onboardings_path(owner)
# Add cases for other owner types when Vendor
else submit_onboarding_vendor_onboardings_path(owner)
root_path # Fallback path when Employer
end submit_onboarding_employer_onboardings_path(owner)
end else
root_path # Default path if owner type is unrecognized
end
end
end end

View File

@ -14,6 +14,8 @@ class Employer < ApplicationRecord
"#{first_name} #{last_name}" "#{first_name} #{last_name}"
end end
has_many :onboarding_items, as: :owner
accepts_nested_attributes_for :onboarding_items
class Employer < ApplicationRecord class Employer < ApplicationRecord
# Associations and other methods as before... # Associations and other methods as before...
@ -30,5 +32,19 @@ class Employer < ApplicationRecord
end end
end end
end end
def create_onboarding_items_for_forms
# Ensure there's a 'Role' model with an association set up between Forms and Roles.
employer_role = Role.find_by(name: 'Employer')
return unless employer_role
# Fetch all forms associated with the 'Employer' role.
forms = Form.joins(:roles).where(roles: { id: employer_role.id })
forms.each do |form|
self.onboarding_items.find_or_create_by(form: form)
end
end
end end

View File

@ -1,6 +1,9 @@
class Form < ApplicationRecord class Form < ApplicationRecord
# Assuming each form can have many onboarding items associated with different owners. # Assuming each form can have many onboarding items associated with different owners.
has_many :onboarding_items has_many :onboarding_items
has_many :forms_roles
has_many :roles, through: :forms_roles
accepts_nested_attributes_for :forms_roles, allow_destroy: true
validates :name, presence: true validates :name, presence: true
validates :role, inclusion: { in: %w[Participant Worker Vendor Employer] } validates :role, inclusion: { in: %w[Participant Worker Vendor Employer] }
@ -11,13 +14,13 @@ class Form < ApplicationRecord
private private
def update_onboarding_items def update_onboarding_items
# Dynamically find the model class based on the role. Ensure 'role' matches your model name exactly. roles.each do |role|
owner_class = role.constantize # Assuming `role.name` is 'Participant', 'Worker', 'Vendor', or 'Employer'
owner_class = role.name.constantize
# For each instance of the model, find or create an onboarding item linked to this form. owner_class.find_each do |owner|
owner_class.find_each do |owner| OnboardingItem.find_or_create_by(owner: owner, form: self)
OnboardingItem.find_or_create_by(owner: owner, form: self) end
end end
end end
end end

6
app/models/forms_role.rb Normal file
View File

@ -0,0 +1,6 @@
class FormsRole < ApplicationRecord
belongs_to :form
belongs_to :role
attribute :note, :string
attribute :date_completed, :date
end

View File

@ -31,10 +31,15 @@ class Participant < ApplicationRecord
end end
def create_onboarding_items_for_forms def create_onboarding_items_for_forms
# Fetch all forms relevant to participants # Ensure there's a 'Role' model with an association set up between Forms and Roles.
forms = Form.where(role: 'Participant') participant_role = Role.find_by(name: 'Participant')
return unless participant_role
# Fetch all forms associated with the 'Participant' role.
forms = Form.joins(:roles).where(roles: { id: participant_role.id })
forms.each do |form| forms.each do |form|
self.onboarding_items.create(form: form) self.onboarding_items.find_or_create_by(form: form)
end end
end end
end end

4
app/models/role.rb Normal file
View File

@ -0,0 +1,4 @@
class Role < ApplicationRecord
has_many :forms_roles
has_many :forms, through: :forms_roles
end

View File

@ -4,6 +4,8 @@ class Vendor < ApplicationRecord
has_many :service_contracts has_many :service_contracts
has_many :participants, through: :service_contracts has_many :participants, through: :service_contracts
has_many :bank_accounts, as: :owner has_many :bank_accounts, as: :owner
has_many :onboarding_items, as: :owner
accepts_nested_attributes_for :onboarding_items
# Validations # Validations
validates :tin, uniqueness: true, allow_blank: true, presence: true validates :tin, uniqueness: true, allow_blank: true, presence: true

View File

@ -9,6 +9,9 @@ class Worker < ApplicationRecord
has_many :employers, through: :participants, source: :employer has_many :employers, through: :participants, source: :employer
has_many :employer_records, through: :participants has_many :employer_records, through: :participants
has_many :onboarding_items, as: :owner
accepts_nested_attributes_for :onboarding_items
# Validations # Validations
validates :first_name, presence: true validates :first_name, presence: true
validates :last_name, presence: true validates :last_name, presence: true

View File

@ -26,8 +26,8 @@
</div> </div>
<div class="mb-3"> <div class="mb-3">
<%= f.label :role, 'Who/Role', class: 'form-label' %> <%= f.label :role_ids, 'Roles', class: 'form-label' %>
<%= f.text_field :role, class: 'form-control', placeholder: 'Enter role' %> <%= f.collection_select :role_ids, Role.all, :id, :name, {}, { multiple: true, class: "form-control" } %>
</div> </div>
<div class="actions"> <div class="actions">

View File

@ -21,7 +21,7 @@
<td><%= form.name %></td> <td><%= form.name %></td>
<td><%= form.required ? 'Required' : 'Optional' %></td> <td><%= form.required ? 'Required' : 'Optional' %></td>
<td><%= form.program %></td> <td><%= form.program %></td>
<td><%= form.role %></td> <td><%= form.roles.map(&:name).join(", ") %></td>
<td> <td>
<%= link_to edit_form_path(form), class: 'btn btn-info btn-sm' do %> <%= link_to edit_form_path(form), class: 'btn btn-info btn-sm' do %>
<i class="bi bi-pencil-fill" style="color: white;"></i> <i class="bi bi-pencil-fill" style="color: white;"></i>

View File

@ -1,44 +1,42 @@
<div class="container mt-5"> <div class="container mt-5">
<div class="row justify-content-center"> <h1 class="mb-4 text-center">Onboarding</h1>
<div class="col-md-8">
<h1 class="mb-4 text-center">Onboarding Forms</h1>
<%= form_with(model: [@owner, OnboardingItem.new], url: submit_onboarding_path_helper(@owner), local: true, html: { class: 'needs-validation', novalidate: true }) do |form| %>
<table class="table">
<thead class="table-light">
<tr>
<th>Form Name</th>
<th>Notes</th>
<th>Date Completed</th>
</tr>
</thead>
<tbody>
<% @onboarding_items.each do |item| %>
<tr>
<td><%= item.form.name %></td>
<td>
<%= text_area_tag "onboarding_items[#{item.id}][note]", item.note, class: "form-control", rows: 1 %>
</td>
<td>
<%= date_field_tag "onboarding_items[#{item.id}][date_completed]", item.date_completed, class: "form-control" %>
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="actions mt-4">
<%= form.submit 'Save', class: 'btn btn-dark' %>
</div>
<% end %>
<div class="mt-3 text-center">
<%= link_to 'Back', polymorphic_path(@owner), class: 'btn btn-secondary' %>
</div>
</div>
</div>
</div> </div>
<%= form_with(model: [@owner, OnboardingItem.new], url: submit_onboarding_polymorphic_path(@owner), local: true, html: { class: 'needs-validation', novalidate: true }) do |form| %>
<table class="table">
<thead class="table-light">
<tr>
<th>Form Name</th>
<th>Notes</th>
<th>Date Completed</th>
</tr>
</thead>
<tbody>
<% @onboarding_items.each_with_index do |item, index| %>
<tr>
<td><%= item.form.name %></td>
<td>
<%= text_area_tag "onboarding_items[#{index}][note]", item.note, id: "onboarding_items_#{index}_note", class: "form-control", rows: 1 %>
</td>
<td>
<%= date_field_tag "onboarding_items[#{index}][date_completed]", item.date_completed, id: "onboarding_items_#{index}_date_completed", class: "form-control" %>
</td>
<%= hidden_field_tag "onboarding_items[#{index}][id]", item.id %>
</tr>
<% end %>
</tbody>
</table>
<div class="actions mt-4">
<%= form.submit 'Save', class: 'btn btn-dark' %>
</div>
<% end %>
<div class="mt-3 text-center">
<%= link_to 'Back', polymorphic_path(@owner), class: 'btn btn-secondary' %>
</div>
<%# This is for resizing Notes area %> <%# This is for resizing Notes area %>
<script> <script>
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {

View File

@ -32,8 +32,11 @@ Rails.application.routes.draw do
resources :workers do resources :workers do
resources :onboardings, only: [:index, :create, :update] resources :onboardings, only: [:index, :create, :update] do
post 'submit_onboarding', on: :collection collection do
post 'submit_onboarding'
end
end
resources :bank_accounts, only: [:index, :new, :create, :edit, :update, :destroy] resources :bank_accounts, only: [:index, :new, :create, :edit, :update, :destroy]
member do member do
post 'link_participant' post 'link_participant'
@ -44,8 +47,11 @@ Rails.application.routes.draw do
resources :vendors do resources :vendors do
resources :onboardings, only: [:index, :create, :update] resources :onboardings, only: [:index, :create, :update] do
post 'submit_onboarding', on: :collection collection do
post 'submit_onboarding'
end
end
resources :bank_accounts, only: [:index, :new, :create, :edit, :update, :destroy] resources :bank_accounts, only: [:index, :new, :create, :edit, :update, :destroy]
collection do collection do
get 'search' get 'search'
@ -62,14 +68,20 @@ Rails.application.routes.draw do
resources :service_contracts resources :service_contracts
resources :employers do resources :employers do
resources :onboardings, only: [:index, :create, :update] resources :onboardings, only: [:index, :create, :update] do
post 'submit_onboarding', on: :collection collection do
member do post 'submit_onboarding'
post "link_worker" end
end
member do
post 'link_worker'
end
collection do
get 'search'
end end
get 'search', on: :collection
end end
resources :forms resources :forms
resources :users resources :users

View File

@ -0,0 +1,9 @@
class CreateRoles < ActiveRecord::Migration[7.1]
def change
create_table :roles do |t|
t.string :name
t.timestamps
end
end
end

View File

@ -0,0 +1,11 @@
class CreateFormsRoles < ActiveRecord::Migration[7.1]
def change
create_table :forms_roles do |t|
t.references :form, null: false, foreign_key: true
t.references :role, null: false, foreign_key: true
t.timestamps
end
end
end

View File

@ -0,0 +1,5 @@
class AddNoteToFormsRoles < ActiveRecord::Migration[7.1]
def change
add_column :forms_roles, :note, :string
end
end

View File

@ -0,0 +1,5 @@
class AddDateCompletedToFormsRoles < ActiveRecord::Migration[7.1]
def change
add_column :forms_roles, :date_completed, :date
end
end

21
db/schema.rb generated
View File

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.1].define(version: 2024_02_17_005105) do ActiveRecord::Schema[7.1].define(version: 2024_02_17_063857) do
create_table "bank_accounts", force: :cascade do |t| create_table "bank_accounts", force: :cascade do |t|
t.string "institution_name" t.string "institution_name"
t.string "account_type" t.string "account_type"
@ -81,6 +81,17 @@ ActiveRecord::Schema[7.1].define(version: 2024_02_17_005105) do
t.string "role" t.string "role"
end end
create_table "forms_roles", force: :cascade do |t|
t.integer "form_id", null: false
t.integer "role_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "note"
t.date "date_completed"
t.index ["form_id"], name: "index_forms_roles_on_form_id"
t.index ["role_id"], name: "index_forms_roles_on_role_id"
end
create_table "onboarding_items", force: :cascade do |t| create_table "onboarding_items", force: :cascade do |t|
t.integer "form_id" t.integer "form_id"
t.text "note" t.text "note"
@ -132,6 +143,12 @@ ActiveRecord::Schema[7.1].define(version: 2024_02_17_005105) do
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
end end
create_table "roles", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "service_contracts", force: :cascade do |t| create_table "service_contracts", force: :cascade do |t|
t.integer "participant_id", null: false t.integer "participant_id", null: false
t.integer "vendor_id", null: false t.integer "vendor_id", null: false
@ -197,6 +214,8 @@ ActiveRecord::Schema[7.1].define(version: 2024_02_17_005105) do
add_foreign_key "employer_records", "participants" add_foreign_key "employer_records", "participants"
add_foreign_key "employments", "participants" add_foreign_key "employments", "participants"
add_foreign_key "employments", "workers" add_foreign_key "employments", "workers"
add_foreign_key "forms_roles", "forms"
add_foreign_key "forms_roles", "roles"
add_foreign_key "participants", "employers" add_foreign_key "participants", "employers"
add_foreign_key "participants", "workers" add_foreign_key "participants", "workers"
add_foreign_key "service_contracts", "participants" add_foreign_key "service_contracts", "participants"

View File

@ -7,3 +7,9 @@
# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name| # ["Action", "Comedy", "Drama", "Horror"].each do |genre_name|
# MovieGenre.find_or_create_by!(name: genre_name) # MovieGenre.find_or_create_by!(name: genre_name)
# end # end
roles = ['Participant', 'Employer', 'Worker', 'Vendor']
roles.each do |role_name|
Role.find_or_create_by(name: role_name)
end

9
test/fixtures/forms_roles.yml vendored Normal file
View File

@ -0,0 +1,9 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
form: one
role: one
two:
form: two
role: two

7
test/fixtures/roles.yml vendored Normal file
View File

@ -0,0 +1,7 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
name: MyString
two:
name: MyString

View File

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

7
test/models/role_test.rb Normal file
View File

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