diff --git a/Gemfile b/Gemfile
index 3df49aa..e6f95ca 100644
--- a/Gemfile
+++ b/Gemfile
@@ -16,6 +16,9 @@ group :development, :test do
gem 'rspec-rails'
end
gem 'rails-controller-testing', '~> 1.0', '>= 1.0.5'
+group :test do
+ gem 'factory_bot_rails'
+end
# Start debugger with binding.b [https://github.com/ruby/debug]
diff --git a/activejob-web.gemspec b/activejob-web.gemspec
index fa9fa19..cdac4d7 100644
--- a/activejob-web.gemspec
+++ b/activejob-web.gemspec
@@ -24,4 +24,5 @@ Gem::Specification.new do |spec|
spec.add_dependency "rails", ">= 7.0.8"
spec.add_development_dependency 'rspec-rails'
+ spec.add_development_dependency "factory_bot_rails"
end
diff --git a/app/controllers/activejob_web/job_executions_controller.rb b/app/controllers/activejob_web/job_executions_controller.rb
new file mode 100644
index 0000000..05068c6
--- /dev/null
+++ b/app/controllers/activejob_web/job_executions_controller.rb
@@ -0,0 +1,38 @@
+class ActivejobWeb::JobExecutionsController < ApplicationController
+ before_action :set_job_id
+ def index
+ @job_executions = ActivejobWeb::JobExecution.where(job_id: params[:job_id])
+ @job_execution = @job.job_executions.new
+ end
+ def edit
+ @job_execution = @job.job_executions.find(params[:id])
+ end
+ def update
+ @job_execution = ActivejobWeb::JobExecution.find(params[:id])
+ if @job_execution.update(job_execution_params)
+ redirect_to activejob_web_job_job_execution_path(@job), notice: 'Job execution was successfully updated.'
+ else
+ render :edit
+ end
+ end
+ def show
+ @job_execution = ActivejobWeb::JobExecution.find(params[:id])
+ end
+ def create
+ @job_execution = @job.job_executions.new(job_execution_params)
+ if @job_execution.save
+ flash[:notice] = "Job execution created successfully."
+ redirect_to activejob_web_job_job_executions_path(@job)
+ else
+ @job_executions = ActivejobWeb::JobExecution.where(job_id: params[:job_id])
+ render :index
+ end
+ end
+end
+ private
+ def job_execution_params
+ params.require(:activejob_web_job_execution).permit(:requestor_comments, :status, :job_id,:auto_execute_on_approval)
+ end
+ def set_job_id
+ @job = ActivejobWeb::Job.find(params[:job_id])
+ end
\ No newline at end of file
diff --git a/app/helpers/activejob_web/job_executions_helper.rb b/app/helpers/activejob_web/job_executions_helper.rb
new file mode 100644
index 0000000..6967355
--- /dev/null
+++ b/app/helpers/activejob_web/job_executions_helper.rb
@@ -0,0 +1,2 @@
+module ActivejobWeb::JobExecutionsHelper
+end
diff --git a/app/models/activejob_web/job.rb b/app/models/activejob_web/job.rb
index 89b9b08..c29c035 100644
--- a/app/models/activejob_web/job.rb
+++ b/app/models/activejob_web/job.rb
@@ -7,6 +7,7 @@ class ActivejobWeb::Job < ApplicationRecord
# Default value for queue
after_initialize :set_default_queue
has_one_attached :template_file
+ has_many :job_executions, :class_name => 'ActivejobWeb::JobExecution'
private
# Default value for queue
def set_default_queue
diff --git a/app/models/activejob_web/job_execution.rb b/app/models/activejob_web/job_execution.rb
new file mode 100644
index 0000000..87d696b
--- /dev/null
+++ b/app/models/activejob_web/job_execution.rb
@@ -0,0 +1,22 @@
+class ActivejobWeb::JobExecution < ApplicationRecord
+ enum status: {
+ requested: 0,
+ approved: 1,
+ rejected: 2,
+ executed: 3,
+ cancelled: 4,
+ succeeded: 5,
+ failed: 6
+ }
+
+ validates :requestor_comments, presence: true
+
+ after_initialize :set_default_status
+ belongs_to :job, :class_name => 'ActivejobWeb::Job', foreign_key: 'job_id'
+
+ private
+
+ def set_default_status
+ self.status ||= :requested
+ end
+end
diff --git a/app/views/activejob_web/job_executions/_job_execution_form.html.erb b/app/views/activejob_web/job_executions/_job_execution_form.html.erb
new file mode 100644
index 0000000..ae21939
--- /dev/null
+++ b/app/views/activejob_web/job_executions/_job_execution_form.html.erb
@@ -0,0 +1,18 @@
+<%= form_for [@job, @job_execution] ,url: url do |form| %>
+ <% if @job_execution.errors.any? %>
+
+
<%= pluralize(@job_execution.errors.count, "error") %> prohibited this job_execution from being saved:
+
+
+ <% @job_execution.errors.full_messages.each do |message| %>
+ - <%= message %>
+ <% end %>
+ <%end %>
+
+
+ <%= form.select :status, ActivejobWeb::JobExecution.statuses.keys %>
+ <%= form.text_field :requestor_comments, placeholder: "Requestor Comments" %>
+ <%= form.label :auto_execute_on_approval %>
+ <%= form.check_box :auto_execute_on_approval %>
+ <%= form.submit %>
+<% end %>
diff --git a/app/views/activejob_web/job_executions/edit.html.erb b/app/views/activejob_web/job_executions/edit.html.erb
new file mode 100644
index 0000000..5c00755
--- /dev/null
+++ b/app/views/activejob_web/job_executions/edit.html.erb
@@ -0,0 +1,2 @@
+Edit Job Execution
+<%= render partial: 'job_execution_form',locals: {url:activejob_web_job_job_execution_path(@job,@job_execution)} %>
diff --git a/app/views/activejob_web/job_executions/index.html.erb b/app/views/activejob_web/job_executions/index.html.erb
new file mode 100644
index 0000000..efbe2c3
--- /dev/null
+++ b/app/views/activejob_web/job_executions/index.html.erb
@@ -0,0 +1,27 @@
+Job Executions
+<% if flash[:notice].present? %>
+
+ <%= flash[:notice] %>
+
+<% end %>
+<%= render partial: 'job_execution_form',locals: {url:activejob_web_job_job_executions_path(@job)}%>
+
+
+ | ID |
+ Status |
+ Requestor Comments |
+ Auto Execute On Approval |
+ Actions |
+
+ <% @job_executions.each do |job_execution| %>
+
+ | <%= job_execution.id %> |
+ <%= job_execution.status %> |
+ <%= job_execution.requestor_comments %> |
+ <%= job_execution.auto_execute_on_approval %> |
+ <%= link_to 'Show', activejob_web_job_job_execution_path(@job,job_execution) %> |
+ <%= link_to 'Back', activejob_web_jobs_path %> |
+
+ <% end %>
+
+
diff --git a/app/views/activejob_web/job_executions/show.html.erb b/app/views/activejob_web/job_executions/show.html.erb
new file mode 100644
index 0000000..e51e432
--- /dev/null
+++ b/app/views/activejob_web/job_executions/show.html.erb
@@ -0,0 +1,14 @@
+Job Execution Details
+
+ID: <%= @job_execution.id %>
+Status: <%= @job_execution.status %>
+Requestor Comments: <%= @job_execution.requestor_comments %>
+Auto_execute_on_approval: <%= @job_execution.auto_execute_on_approval %>
+Reason for Failure: <%= @job_execution.reason_for_failure %>
+Arguments:<%= @job_execution.arguments %>
+Auto Execute on Approval: <%= @job_execution.auto_execute_on_approval %>
+Run At: <%= @job_execution.run_at %>
+Execution Started At: <%= @job_execution.execution_started_at %>
+
+<%= link_to 'Edit', edit_activejob_web_job_job_execution_path(@job,@job_execution) %> |
+<%= link_to 'Back',activejob_web_job_job_executions_path %>
diff --git a/app/views/activejob_web/jobs/index.html.erb b/app/views/activejob_web/jobs/index.html.erb
index 5a36384..9b229d0 100644
--- a/app/views/activejob_web/jobs/index.html.erb
+++ b/app/views/activejob_web/jobs/index.html.erb
@@ -18,6 +18,7 @@
<%= job.id %> |
<%= job.queue %> |
<%= link_to 'Show', activejob_web_job_path(job) %> |
+
<% end %>
diff --git a/app/views/activejob_web/jobs/show.html.erb b/app/views/activejob_web/jobs/show.html.erb
index 32456a6..d3cd01b 100644
--- a/app/views/activejob_web/jobs/show.html.erb
+++ b/app/views/activejob_web/jobs/show.html.erb
@@ -11,4 +11,5 @@
<% else %>
no template available
<% end %>
-<%= link_to 'Back', activejob_web_jobs_path %>
\ No newline at end of file
+<%= link_to 'Back', activejob_web_jobs_path %>
+<%= link_to 'job executions', activejob_web_job_job_executions_path(@job) %> |
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index bc0511c..367896a 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -5,6 +5,7 @@
member do
get :download_pdf
end
+ resources :job_executions
end
end
diff --git a/db/migrate/20231030145254_create_active_storage_tables.active_storage.rb b/db/migrate/20231030145254_create_active_storage_tables.active_storage.rb
index 3781086..33031c6 100644
--- a/db/migrate/20231030145254_create_active_storage_tables.active_storage.rb
+++ b/db/migrate/20231030145254_create_active_storage_tables.active_storage.rb
@@ -1,6 +1,7 @@
# This migration comes from active_storage (originally 20170806125915)
class CreateActiveStorageTables < ActiveRecord::Migration[7.0]
def change
+ primary_key_type, foreign_key_type = primary_and_foreign_key_types
unless table_exists?(:active_storage_blobs)
create_table :active_storage_blobs, id: primary_key_type do |t|
t.string :key, null: false
@@ -21,7 +22,6 @@ def change
end
end
# Use Active Record's configured type for primary and foreign keys
- primary_key_type, foreign_key_type = primary_and_foreign_key_types
unless table_exists?(:active_storage_attachments)
create_table :active_storage_attachments, id: primary_key_type do |t|
diff --git a/db/migrate/20231106105039_create_activejob_web_job_executions.rb b/db/migrate/20231106105039_create_activejob_web_job_executions.rb
new file mode 100644
index 0000000..efab964
--- /dev/null
+++ b/db/migrate/20231106105039_create_activejob_web_job_executions.rb
@@ -0,0 +1,16 @@
+class CreateActivejobWebJobExecutions < ActiveRecord::Migration[7.1]
+ def change
+ create_table :activejob_web_job_executions ,id: :uuid do |t|
+ t.integer :requestor_id
+ t.uuid :job_id
+ t.string :requestor_comments
+ t.json :arguments
+ t.integer :status
+ t.string :reason_for_failure
+ t.boolean :auto_execute_on_approval
+ t.timestamp :run_at
+ t.timestamp :execution_started_at
+ t.timestamps
+ end
+ end
+end
diff --git a/spec/factories/job_executions.rb b/spec/factories/job_executions.rb
new file mode 100644
index 0000000..61be55f
--- /dev/null
+++ b/spec/factories/job_executions.rb
@@ -0,0 +1,26 @@
+# spec/factories/job_executions.rb
+FactoryBot.define do
+ factory :job_execution, class: ActivejobWeb::JobExecution do
+ requestor_id { 1 } # Adjust as needed
+ job_id { SecureRandom.uuid } # Generates a random UUID
+ requestor_comments { 'Requestor comments' }
+ arguments { { key: 'value' } } # Example JSON structure, adjust as needed
+ status { 0 } # Example status, adjust as needed
+ reason_for_failure { 'Reason for failure' }
+ auto_execute_on_approval { false }
+ run_at { Time.current }
+ execution_started_at { Time.current }
+ end
+
+ factory :valid_job_execution, class: ActivejobWeb::JobExecution do
+ status { 'requested' }
+ requestor_comments { 'joy' }
+ auto_execute_on_approval { true }
+ end
+
+ factory :invalid_job_execution, class: ActivejobWeb::JobExecution do
+ # This factory intentionally creates an invalid job execution with an invalid status
+ status { 'approved' }
+ auto_execute_on_approval { true }
+ end
+end
diff --git a/spec/factories/jobs.rb b/spec/factories/jobs.rb
new file mode 100644
index 0000000..a03935f
--- /dev/null
+++ b/spec/factories/jobs.rb
@@ -0,0 +1,6 @@
+FactoryBot.define do
+ factory :job1, class: ActivejobWeb::Job do
+ title { 'Job title' }
+ description {'description for job'}
+ end
+end
diff --git a/spec/helpers/activejob_web/job_executions_helper_spec.rb b/spec/helpers/activejob_web/job_executions_helper_spec.rb
new file mode 100644
index 0000000..1773269
--- /dev/null
+++ b/spec/helpers/activejob_web/job_executions_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'rails_helper'
+
+# Specs in this file have access to a helper object that includes
+# the ActivejobWeb::JobExecutionsHelper. For example:
+#
+# describe ActivejobWeb::JobExecutionsHelper do
+# describe "string concat" do
+# it "concats two strings with spaces" do
+# expect(helper.concat_strings("this","that")).to eq("this that")
+# end
+# end
+# end
+RSpec.describe ActivejobWeb::JobExecutionsHelper, type: :helper do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/models/activejob_web/job_execution_spec.rb b/spec/models/activejob_web/job_execution_spec.rb
new file mode 100644
index 0000000..7a53329
--- /dev/null
+++ b/spec/models/activejob_web/job_execution_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe ActivejobWeb::JobExecution, type: :model do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
index 3ba12de..819d781 100644
--- a/spec/rails_helper.rb
+++ b/spec/rails_helper.rb
@@ -5,6 +5,9 @@
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
+require 'factory_bot_rails'
+FactoryBot.definition_file_paths << File.join(File.dirname(__FILE__), 'factories')
+FactoryBot.reload
# Add additional requires below this line. Rails is not loaded until this point!
# Requires supporting ruby files with custom matchers and macros, etc, in
@@ -34,6 +37,7 @@
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
+ config.include FactoryBot::Syntax::Methods
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
diff --git a/spec/requests/activejob_web/job_executions_spec.rb b/spec/requests/activejob_web/job_executions_spec.rb
new file mode 100644
index 0000000..cad06c4
--- /dev/null
+++ b/spec/requests/activejob_web/job_executions_spec.rb
@@ -0,0 +1,82 @@
+require 'rails_helper'
+RSpec.describe ActivejobWeb::JobExecutionsController, type: :request do
+ describe 'GET #index' do
+ let(:job) { create(:job1) } # Assuming you have a Job model
+
+ it 'renders the index template' do
+ get activejob_web_job_job_executions_path(job_id: job.id)
+
+ expect(response).to have_http_status 200
+ expect(response).to render_template(:index)
+ end
+ end
+
+ describe 'GET #show' do
+ let(:job) { create(:job1) }
+ let(:execution) { create(:job_execution, job: job) }
+
+ it 'renders the show template' do
+ get activejob_web_job_job_execution_path(job_id: job.id, id: execution.id)
+
+ expect(response).to have_http_status 200
+ expect(response).to render_template(:show)
+ end
+ end
+
+ describe 'GET #edit' do
+ let(:job) { create(:job1) } # Assuming you have a Job factory
+ let(:job_execution) { create(:job_execution, job: job) } # Assuming you have a JobExecution factory
+
+ it 'renders the edit template' do
+ get edit_activejob_web_job_job_execution_path(job, job_execution)
+
+ expect(response).to have_http_status 200
+ expect(response).to render_template(:edit)
+ end
+ end
+
+ describe 'POST #create' do
+ let(:job) { create(:job1) }
+ context 'with valid parameters' do
+ let(:valid_execution_attributes) { attributes_for(:valid_job_execution) }
+
+ it 'creates a new job execution' do
+ post activejob_web_job_job_executions_path(job), params: {
+ activejob_web_job_execution: valid_execution_attributes
+ }
+
+ expect(response).to have_http_status(302) # Redirect status
+ expect(flash[:notice]).to eq("Job execution created successfully.")
+ expect(response).to redirect_to(activejob_web_job_job_executions_path(job))
+ end
+ end
+
+ context 'with invalid parameters' do
+ let(:invalid_execution_attributes) { attributes_for(:invalid_job_execution) }
+
+ it 'renders the index template' do
+ post activejob_web_job_job_executions_path(job), params: {
+ activejob_web_job_execution: invalid_execution_attributes
+ }
+
+ expect(response).to have_http_status(200) # Success status since it renders the index template
+ expect(response).to render_template(:index)
+ end
+ end
+ end
+ describe 'PATCH #update' do
+ let(:job) { create(:job1) } # Assuming you have a Job factory
+ let(:job_execution) { create(:job_execution, job: job) } # Assuming you have a JobExecution factory
+
+ context 'with valid parameters' do
+ it 'updates the job execution and redirects to the show page' do
+ patch activejob_web_job_job_execution_path(job, job_execution),
+ params: { activejob_web_job_execution: { status: 'requested' } }
+
+ expect(response).to have_http_status 302 # Redirect status
+ expect(flash[:notice]).to eq('Job execution was successfully updated.')
+ expect(response).to redirect_to(activejob_web_job_job_execution_path(job))
+ end
+ end
+ end
+end
diff --git a/test/dummy/db/schema.rb b/test/dummy/db/schema.rb
index c037468..56abd6a 100644
--- a/test/dummy/db/schema.rb
+++ b/test/dummy/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.1].define(version: 2023_10_30_145254) do
+ActiveRecord::Schema[7.1].define(version: 2023_11_06_105039) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -42,6 +42,20 @@
t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
end
+ create_table "activejob_web_job_executions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+ t.integer "requestor_id"
+ t.uuid "job_id"
+ t.string "requestor_comments"
+ t.json "arguments"
+ t.integer "status"
+ t.string "reason_for_failure"
+ t.boolean "auto_execute_on_approval"
+ t.datetime "run_at", precision: nil
+ t.datetime "execution_started_at", precision: nil
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
create_table "activejob_web_jobs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.string "title"
t.string "description"