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

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

View File

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

View File

@ -1,5 +1,5 @@
class OnboardingsController < ApplicationController
before_action :set_owner
before_action :set_owner, only: [:index, :submit_onboarding]
def index
# 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
def submit_onboarding
params[:onboarding_items].each do |id, item_params|
onboarding_item = OnboardingItem.find(id)
onboarding_item.update(item_params.permit(:note, :date_completed))
@owner = find_owner
onboarding_items_params.values.each do |item_params|
item = OnboardingItem.find_or_initialize_by(id: item_params.delete(:id))
item.assign_attributes(item_params)
item.owner = @owner
item.save
end
redirect_to polymorphic_path([@owner]), notice: 'Onboarding information updated successfully.'
redirect_to polymorphic_path(@owner), notice: 'Onboarding information updated successfully.'
end
private
def set_owner
# Example: finds "participant_id", sets @owner to the corresponding Participant object
params.each do |name, value|
if name =~ /(.+)_id$/
model = $1.classify.constantize
@owner = model.find_by(id: value)
break if @owner # Break if owner is found
model_name = name.match(/(.+)_id$/)[1].classify
@owner = model_name.constantize.find(value)
break
end
end
redirect_to(root_path, alert: "Owner not found.") unless @owner
unless @owner
redirect_to root_path, alert: "Owner not found."
end
end
def onboarding_items_params
# Ensure you permit the correct parameters based on your form fields
params.require(:onboarding_item).permit(:form_id, :note, :date_completed)
params.permit(onboarding_items: [:id, :note, :date_completed]).fetch(:onboarding_items, {})
end
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

View File

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

View File

@ -14,6 +14,8 @@ class Employer < ApplicationRecord
"#{first_name} #{last_name}"
end
has_many :onboarding_items, as: :owner
accepts_nested_attributes_for :onboarding_items
class Employer < ApplicationRecord
# Associations and other methods as before...
@ -30,5 +32,19 @@ class Employer < ApplicationRecord
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

View File

@ -1,6 +1,9 @@
class Form < ApplicationRecord
# Assuming each form can have many onboarding items associated with different owners.
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 :role, inclusion: { in: %w[Participant Worker Vendor Employer] }
@ -11,13 +14,13 @@ class Form < ApplicationRecord
private
def update_onboarding_items
# Dynamically find the model class based on the role. Ensure 'role' matches your model name exactly.
owner_class = role.constantize
# For each instance of the model, find or create an onboarding item linked to this form.
owner_class.find_each do |owner|
OnboardingItem.find_or_create_by(owner: owner, form: self)
roles.each do |role|
# Assuming `role.name` is 'Participant', 'Worker', 'Vendor', or 'Employer'
owner_class = role.name.constantize
owner_class.find_each do |owner|
OnboardingItem.find_or_create_by(owner: owner, form: self)
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
def create_onboarding_items_for_forms
# Fetch all forms relevant to participants
forms = Form.where(role: 'Participant')
# Ensure there's a 'Role' model with an association set up between Forms and Roles.
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|
self.onboarding_items.create(form: form)
self.onboarding_items.find_or_create_by(form: form)
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 :participants, through: :service_contracts
has_many :bank_accounts, as: :owner
has_many :onboarding_items, as: :owner
accepts_nested_attributes_for :onboarding_items
# Validations
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 :employer_records, through: :participants
has_many :onboarding_items, as: :owner
accepts_nested_attributes_for :onboarding_items
# Validations
validates :first_name, presence: true
validates :last_name, presence: true

View File

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

View File

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

View File

@ -1,44 +1,42 @@
<div class="container mt-5">
<div class="row justify-content-center">
<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>
<h1 class="mb-4 text-center">Onboarding</h1>
</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 %>
<script>
document.addEventListener('DOMContentLoaded', function() {

View File

@ -32,8 +32,11 @@ Rails.application.routes.draw do
resources :workers do
resources :onboardings, only: [:index, :create, :update]
post 'submit_onboarding', on: :collection
resources :onboardings, only: [:index, :create, :update] do
collection do
post 'submit_onboarding'
end
end
resources :bank_accounts, only: [:index, :new, :create, :edit, :update, :destroy]
member do
post 'link_participant'
@ -44,8 +47,11 @@ Rails.application.routes.draw do
resources :vendors do
resources :onboardings, only: [:index, :create, :update]
post 'submit_onboarding', on: :collection
resources :onboardings, only: [:index, :create, :update] do
collection do
post 'submit_onboarding'
end
end
resources :bank_accounts, only: [:index, :new, :create, :edit, :update, :destroy]
collection do
get 'search'
@ -62,13 +68,19 @@ Rails.application.routes.draw do
resources :service_contracts
resources :employers do
resources :onboardings, only: [:index, :create, :update]
post 'submit_onboarding', on: :collection
member do
post "link_worker"
resources :onboardings, only: [:index, :create, :update] do
collection do
post 'submit_onboarding'
end
end
member do
post 'link_worker'
end
collection do
get 'search'
end
get 'search', on: :collection
end
resources :forms
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.
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|
t.string "institution_name"
t.string "account_type"
@ -81,6 +81,17 @@ ActiveRecord::Schema[7.1].define(version: 2024_02_17_005105) do
t.string "role"
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|
t.integer "form_id"
t.text "note"
@ -132,6 +143,12 @@ ActiveRecord::Schema[7.1].define(version: 2024_02_17_005105) do
t.datetime "updated_at", null: false
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|
t.integer "participant_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 "employments", "participants"
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", "workers"
add_foreign_key "service_contracts", "participants"

View File

@ -7,3 +7,9 @@
# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name|
# MovieGenre.find_or_create_by!(name: genre_name)
# 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