diff --git a/Gemfile.lock b/Gemfile.lock
index b2cc3f60c..190255f9c 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -115,7 +115,7 @@ GEM
bootsnap (1.15.0)
msgpack (~> 1.2)
builder (3.2.4)
- bullet_train (1.1.9)
+ bullet_train (1.1.10)
awesome_print
bullet_train-fields
bullet_train-has_uuid
@@ -187,7 +187,7 @@ GEM
rails (>= 7.0.0)
bullet_train-super_load_and_authorize_resource (1.0.1)
rails (>= 6.0.0)
- bullet_train-super_scaffolding (1.1.14)
+ bullet_train-super_scaffolding (1.1.15)
bullet_train
indefinite_article
rails (>= 6.0.0)
@@ -215,7 +215,7 @@ GEM
charlock_holmes (0.7.7)
chronic (0.10.2)
chunky_png (1.4.0)
- cloudinary (1.23.0)
+ cloudinary (1.24.0)
aws_cf_signer
rest-client (>= 2.0.0)
code_analyzer (0.5.5)
@@ -230,6 +230,7 @@ GEM
addressable
cssbundling-rails (1.1.1)
railties (>= 6.0.0)
+ date (3.3.1)
debug (1.7.0)
irb (>= 1.5.0)
reline (>= 0.3.1)
@@ -338,11 +339,12 @@ GEM
minitest (>= 5.0)
msgpack (1.6.0)
multi_xml (0.6.0)
- net-imap (0.3.1)
+ net-imap (0.3.2)
+ date
net-protocol
net-pop (0.1.2)
net-protocol
- net-protocol (0.1.3)
+ net-protocol (0.2.1)
timeout
net-smtp (0.3.3)
net-protocol
@@ -405,7 +407,7 @@ GEM
pry-stack_explorer (0.6.1)
binding_of_caller (~> 1.0)
pry (~> 0.13)
- public_suffix (5.0.0)
+ public_suffix (5.0.1)
puma (6.0.0)
nio4r (~> 2.0)
pwned (2.0.2)
@@ -533,7 +535,7 @@ GEM
stripe (8.0.0)
thor (1.2.1)
thread-local (1.1.0)
- timeout (0.3.0)
+ timeout (0.3.1)
turbo-rails (1.3.2)
actionpack (>= 6.0.0)
activejob (>= 6.0.0)
diff --git a/app/controllers/account/scaffolding/completely_concrete/simple_singletons_controller.rb b/app/controllers/account/scaffolding/completely_concrete/simple_singletons_controller.rb
new file mode 100644
index 000000000..cd88d2dbf
--- /dev/null
+++ b/app/controllers/account/scaffolding/completely_concrete/simple_singletons_controller.rb
@@ -0,0 +1,69 @@
+class Account::Scaffolding::CompletelyConcrete::SimpleSingletonsController < Account::ApplicationController
+ account_load_and_authorize_resource :simple_singleton, through: :absolutely_abstract_creative_concept, through_association: :completely_concrete_simple_singletons
+
+ # GET /account/scaffolding/absolutely_abstract/creative_concepts/:absolutely_abstract_creative_concept_id/completely_concrete/simple_singletons
+ # GET /account/scaffolding/absolutely_abstract/creative_concepts/:absolutely_abstract_creative_concept_id/completely_concrete/simple_singletons.json
+ def index
+ delegate_json_to_api
+ end
+
+ # GET /account/scaffolding/completely_concrete/simple_singletons/:id
+ # GET /account/scaffolding/completely_concrete/simple_singletons/:id.json
+ def show
+ delegate_json_to_api
+ end
+
+ # GET /account/scaffolding/absolutely_abstract/creative_concepts/:absolutely_abstract_creative_concept_id/completely_concrete/simple_singletons/new
+ def new
+ end
+
+ # GET /account/scaffolding/completely_concrete/simple_singletons/:id/edit
+ def edit
+ end
+
+ # POST /account/scaffolding/absolutely_abstract/creative_concepts/:absolutely_abstract_creative_concept_id/completely_concrete/simple_singletons
+ # POST /account/scaffolding/absolutely_abstract/creative_concepts/:absolutely_abstract_creative_concept_id/completely_concrete/simple_singletons.json
+ def create
+ respond_to do |format|
+ if @simple_singleton.save
+ format.html { redirect_to [:account, @absolutely_abstract_creative_concept, :completely_concrete_simple_singletons], notice: I18n.t("scaffolding/completely_concrete/simple_singletons.notifications.created") }
+ format.json { render :show, status: :created, location: [:account, @simple_singleton] }
+ else
+ format.html { render :new, status: :unprocessable_entity }
+ format.json { render json: @simple_singleton.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # PATCH/PUT /account/scaffolding/completely_concrete/simple_singletons/:id
+ # PATCH/PUT /account/scaffolding/completely_concrete/simple_singletons/:id.json
+ def update
+ respond_to do |format|
+ if @simple_singleton.update(simple_singleton_params)
+ format.html { redirect_to [:account, @simple_singleton], notice: I18n.t("scaffolding/completely_concrete/simple_singletons.notifications.updated") }
+ format.json { render :show, status: :ok, location: [:account, @simple_singleton] }
+ else
+ format.html { render :edit, status: :unprocessable_entity }
+ format.json { render json: @simple_singleton.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /account/scaffolding/completely_concrete/simple_singletons/:id
+ # DELETE /account/scaffolding/completely_concrete/simple_singletons/:id.json
+ def destroy
+ @simple_singleton.destroy
+ respond_to do |format|
+ format.html { redirect_to [:account, @absolutely_abstract_creative_concept, :completely_concrete_simple_singletons], notice: I18n.t("scaffolding/completely_concrete/simple_singletons.notifications.destroyed") }
+ format.json { head :no_content }
+ end
+ end
+
+ private
+
+ include strong_parameters_from_api
+
+ def process_params(strong_params)
+ # 🚅 super scaffolding will insert processing for new fields above this line.
+ end
+end
diff --git a/app/controllers/api/v1/scaffolding/completely_concrete/simple_singletons_controller.rb b/app/controllers/api/v1/scaffolding/completely_concrete/simple_singletons_controller.rb
new file mode 100644
index 000000000..b4332491c
--- /dev/null
+++ b/app/controllers/api/v1/scaffolding/completely_concrete/simple_singletons_controller.rb
@@ -0,0 +1,55 @@
+class Api::V1::Scaffolding::CompletelyConcrete::SimpleSingletonsController < Api::V1::ApplicationController
+ account_load_and_authorize_resource :simple_singleton, through: :absolutely_abstract_creative_concept, through_association: :completely_concrete_simple_singletons
+
+ # GET /api/v1/scaffolding/absolutely_abstract/creative_concepts/:absolutely_abstract_creative_concept_id/completely_concrete/simple_singletons
+ def index
+ end
+
+ # GET /api/v1/scaffolding/completely_concrete/simple_singletons/:id
+ def show
+ end
+
+ # POST /api/v1/scaffolding/absolutely_abstract/creative_concepts/:absolutely_abstract_creative_concept_id/completely_concrete/simple_singletons
+ def create
+ if @simple_singleton.save
+ render :show, status: :created, location: [:api, :v1, @simple_singleton]
+ else
+ render json: @simple_singleton.errors, status: :unprocessable_entity
+ end
+ end
+
+ # PATCH/PUT /api/v1/scaffolding/completely_concrete/simple_singletons/:id
+ def update
+ if @simple_singleton.update(simple_singleton_params)
+ render :show
+ else
+ render json: @simple_singleton.errors, status: :unprocessable_entity
+ end
+ end
+
+ # DELETE /api/v1/scaffolding/completely_concrete/simple_singletons/:id
+ def destroy
+ @simple_singleton.destroy
+ end
+
+ private
+
+ module StrongParameters
+ # Only allow a list of trusted parameters through.
+ def simple_singleton_params
+ strong_params = params.require(:scaffolding_completely_concrete_simple_singleton).permit(
+ *permitted_fields,
+ :name,
+ # 🚅 super scaffolding will insert new fields above this line.
+ *permitted_arrays,
+ # 🚅 super scaffolding will insert new arrays above this line.
+ )
+
+ process_params(strong_params)
+
+ strong_params
+ end
+ end
+
+ include StrongParameters
+end
diff --git a/app/models/scaffolding/completely_concrete.rb b/app/models/scaffolding/completely_concrete.rb
new file mode 100644
index 000000000..fc9482c17
--- /dev/null
+++ b/app/models/scaffolding/completely_concrete.rb
@@ -0,0 +1,5 @@
+module Scaffolding::CompletelyConcrete
+ def self.table_name_prefix
+ "scaffolding_completely_concrete_"
+ end
+end
diff --git a/app/models/scaffolding/completely_concrete/simple_singleton.rb b/app/models/scaffolding/completely_concrete/simple_singleton.rb
new file mode 100644
index 000000000..2b2797f97
--- /dev/null
+++ b/app/models/scaffolding/completely_concrete/simple_singleton.rb
@@ -0,0 +1,24 @@
+class Scaffolding::CompletelyConcrete::SimpleSingleton < ApplicationRecord
+ # 🚅 add concerns above.
+
+ # 🚅 add attribute accessors above.
+
+ belongs_to :absolutely_abstract_creative_concept, class_name: "Scaffolding::AbsolutelyAbstract::CreativeConcept"
+ # 🚅 add belongs_to associations above.
+
+ # 🚅 add has_many associations above.
+
+ has_one :team, through: :absolutely_abstract_creative_concept
+ # 🚅 add has_one associations above.
+
+ # 🚅 add scopes above.
+
+ validates :name, presence: true
+ # 🚅 add validations above.
+
+ # 🚅 add callbacks above.
+
+ # 🚅 add delegations above.
+
+ # 🚅 add methods above.
+end
diff --git a/app/views/account/scaffolding/completely_concrete/simple_singletons/_breadcrumbs.html.erb b/app/views/account/scaffolding/completely_concrete/simple_singletons/_breadcrumbs.html.erb
new file mode 100644
index 000000000..b21ac3a32
--- /dev/null
+++ b/app/views/account/scaffolding/completely_concrete/simple_singletons/_breadcrumbs.html.erb
@@ -0,0 +1,8 @@
+<% simple_singleton ||= @simple_singleton %>
+<% absolutely_abstract_creative_concept ||= @absolutely_abstract_creative_concept || simple_singleton&.absolutely_abstract_creative_concept %>
+<%= render 'account/scaffolding/absolutely_abstract/creative_concepts/breadcrumbs', creative_concept: absolutely_abstract_creative_concept %>
+<%= render 'account/shared/breadcrumb', label: t('.label'), url: [:account, absolutely_abstract_creative_concept, :completely_concrete_simple_singletons] %>
+<% if simple_singleton&.persisted? %>
+ <%= render 'account/shared/breadcrumb', label: simple_singleton.label_string, url: [:account, simple_singleton] %>
+<% end %>
+<%= render 'account/shared/breadcrumbs/actions', only_for: 'scaffolding/completely_concrete/simple_singletons' %>
diff --git a/app/views/account/scaffolding/completely_concrete/simple_singletons/_form.html.erb b/app/views/account/scaffolding/completely_concrete/simple_singletons/_form.html.erb
new file mode 100644
index 000000000..a92a9d5aa
--- /dev/null
+++ b/app/views/account/scaffolding/completely_concrete/simple_singletons/_form.html.erb
@@ -0,0 +1,17 @@
+<% cancel_path ||= simple_singleton.persisted? ? [:account, simple_singleton] : [:account, @absolutely_abstract_creative_concept, :completely_concrete_simple_singletons] %>
+
+<%= form_with model: simple_singleton, url: (simple_singleton.persisted? ? [:account, simple_singleton] : [:account, @absolutely_abstract_creative_concept, :completely_concrete_simple_singletons]), local: true, class: 'form' do |form| %>
+ <%= render "shared/limits/form", form: form, cancel_path: cancel_path do %>
+ <%= render 'account/shared/forms/errors', form: form %>
+
+ <% with_field_settings form: form do %>
+ <%= render 'shared/fields/text_field', method: :name, options: {autofocus: true} %>
+ <%# 🚅 super scaffolding will insert new fields above this line. %>
+ <% end %>
+
+
+ <%= form.submit (form.object.persisted? ? t('.buttons.update') : t('.buttons.create')), class: "button" %>
+ <%= link_to t('global.buttons.cancel'), cancel_path, class: "button-secondary" %>
+
+ <% end %>
+<% end %>
diff --git a/app/views/account/scaffolding/completely_concrete/simple_singletons/_index.html.erb b/app/views/account/scaffolding/completely_concrete/simple_singletons/_index.html.erb
new file mode 100644
index 000000000..622e2afb1
--- /dev/null
+++ b/app/views/account/scaffolding/completely_concrete/simple_singletons/_index.html.erb
@@ -0,0 +1,81 @@
+<% absolutely_abstract_creative_concept = @absolutely_abstract_creative_concept || @creative_concept %>
+<% context ||= absolutely_abstract_creative_concept %>
+<% collection ||= :completely_concrete_simple_singletons %>
+<% hide_actions ||= false %>
+<% hide_back ||= false %>
+
+<% simple_singletons = simple_singletons.order(:id) unless has_order?(simple_singletons) %>
+<% pagy, simple_singletons = pagy(simple_singletons, page_param: :simple_singletons_page) %>
+
+<%= action_model_select_controller do %>
+ <%= updates_for context, collection do %>
+ <%= render 'account/shared/box', pagy: pagy do |p| %>
+ <% p.content_for :title, t(".contexts.#{context.class.name.underscore}.header") %>
+ <% p.content_for :description do %>
+ <%= t(".contexts.#{context.class.name.underscore}.description#{"_empty" unless simple_singletons.any?}") %>
+ <%= render "shared/limits/index", model: simple_singletons.model %>
+ <% end %>
+
+ <% p.content_for :table do %>
+ <% if simple_singletons.any? %>
+
+
+
+ <%= render "shared/tables/select_all" %>
+ <%= t('.fields.name.heading') %> |
+ <%# 🚅 super scaffolding will insert new field headers above this line. %>
+ <%= t('.fields.created_at.heading') %> |
+ |
+
+
+
+ <% simple_singletons.each do |simple_singleton| %>
+ <% with_attribute_settings object: simple_singleton do %>
+
+ <%= render "shared/tables/checkbox", object: simple_singleton %>
+ <%= render 'shared/attributes/text', attribute: :name, url: [:account, simple_singleton] %> |
+ <%# 🚅 super scaffolding will insert new fields above this line. %>
+ <%= render 'shared/attributes/date_and_time', attribute: :created_at %> |
+
+ <% unless hide_actions %>
+ <% if can? :edit, simple_singleton %>
+ <%= link_to t('.buttons.shorthand.edit'), [:edit, :account, simple_singleton], class: 'button-secondary button-smaller' %>
+ <% end %>
+ <% if can? :destroy, simple_singleton %>
+ <%= button_to t('.buttons.shorthand.destroy'), [:account, simple_singleton], method: :delete, data: { confirm: t('.buttons.confirmations.destroy', model_locales(simple_singleton)) }, class: 'button-secondary button-smaller' %>
+ <% end %>
+ <%# 🚅 super scaffolding will insert new action model buttons above this line. %>
+ <% end %>
+ |
+
+ <% end %>
+ <% end %>
+
+
+ <% end %>
+ <% end %>
+
+ <% p.content_for :actions do %>
+ <% unless hide_actions %>
+ <% if context == absolutely_abstract_creative_concept %>
+ <% if can? :create, Scaffolding::CompletelyConcrete::SimpleSingleton.new(absolutely_abstract_creative_concept: absolutely_abstract_creative_concept) %>
+ <%= link_to t('.buttons.new'), [:new, :account, absolutely_abstract_creative_concept, :completely_concrete_simple_singleton], class: "#{first_button_primary(:completely_concrete_simple_singleton)} new" %>
+ <% end %>
+ <% end %>
+
+ <%# 🚅 super scaffolding will insert new targets one parent action model buttons above this line. %>
+ <%# 🚅 super scaffolding will insert new bulk action model buttons above this line. %>
+ <%= render "shared/bulk_action_select" %>
+
+ <% unless hide_back %>
+ <%= link_to t('global.buttons.back'), [:account, context], class: "#{first_button_primary(:completely_concrete_simple_singleton)} back" %>
+ <% end %>
+ <% end %>
+ <% end %>
+
+ <% p.content_for :raw_footer do %>
+ <%# 🚅 super scaffolding will insert new action model index views above this line. %>
+ <% end %>
+ <% end %>
+ <% end %>
+<% end %>
diff --git a/app/views/account/scaffolding/completely_concrete/simple_singletons/_menu_item.html.erb b/app/views/account/scaffolding/completely_concrete/simple_singletons/_menu_item.html.erb
new file mode 100644
index 000000000..591055f7b
--- /dev/null
+++ b/app/views/account/scaffolding/completely_concrete/simple_singletons/_menu_item.html.erb
@@ -0,0 +1,10 @@
+<% if can? :read, Scaffolding::CompletelyConcrete::SimpleSingleton.new(team: current_team) %>
+ <%= render 'account/shared/menu/item', {
+ url: main_app.polymorphic_path([:account, current_team, :scaffolding_completely_concrete_simple_singletons]),
+ label: t('scaffolding/completely_concrete/simple_singletons.navigation.label'),
+ } do |p| %>
+ <% p.content_for :icon do %>
+
+ <% end %>
+ <% end %>
+<% end %>
diff --git a/app/views/account/scaffolding/completely_concrete/simple_singletons/edit.html.erb b/app/views/account/scaffolding/completely_concrete/simple_singletons/edit.html.erb
new file mode 100644
index 000000000..47ff08517
--- /dev/null
+++ b/app/views/account/scaffolding/completely_concrete/simple_singletons/edit.html.erb
@@ -0,0 +1,12 @@
+<%= render 'account/shared/page' do |p| %>
+ <% p.content_for :title, t('.section') %>
+ <% p.content_for :body do %>
+ <%= render 'account/shared/box', divider: true do |p| %>
+ <% p.content_for :title, t('.header') %>
+ <% p.content_for :description, t('.description') %>
+ <% p.content_for :body do %>
+ <%= render 'form', simple_singleton: @simple_singleton %>
+ <% end %>
+ <% end %>
+ <% end %>
+<% end %>
diff --git a/app/views/account/scaffolding/completely_concrete/simple_singletons/index.html.erb b/app/views/account/scaffolding/completely_concrete/simple_singletons/index.html.erb
new file mode 100644
index 000000000..107aff535
--- /dev/null
+++ b/app/views/account/scaffolding/completely_concrete/simple_singletons/index.html.erb
@@ -0,0 +1,6 @@
+<%= render 'account/shared/page' do |p| %>
+ <% p.content_for :title, t('.section') %>
+ <% p.content_for :body do %>
+ <%= render 'index', simple_singletons: @simple_singletons %>
+ <% end %>
+<% end %>
diff --git a/app/views/account/scaffolding/completely_concrete/simple_singletons/new.html.erb b/app/views/account/scaffolding/completely_concrete/simple_singletons/new.html.erb
new file mode 100644
index 000000000..47ff08517
--- /dev/null
+++ b/app/views/account/scaffolding/completely_concrete/simple_singletons/new.html.erb
@@ -0,0 +1,12 @@
+<%= render 'account/shared/page' do |p| %>
+ <% p.content_for :title, t('.section') %>
+ <% p.content_for :body do %>
+ <%= render 'account/shared/box', divider: true do |p| %>
+ <% p.content_for :title, t('.header') %>
+ <% p.content_for :description, t('.description') %>
+ <% p.content_for :body do %>
+ <%= render 'form', simple_singleton: @simple_singleton %>
+ <% end %>
+ <% end %>
+ <% end %>
+<% end %>
diff --git a/app/views/account/scaffolding/completely_concrete/simple_singletons/show.html.erb b/app/views/account/scaffolding/completely_concrete/simple_singletons/show.html.erb
new file mode 100644
index 000000000..c53842baa
--- /dev/null
+++ b/app/views/account/scaffolding/completely_concrete/simple_singletons/show.html.erb
@@ -0,0 +1,34 @@
+<%= render 'account/shared/page' do |p| %>
+ <% p.content_for :title, t('.section') %>
+ <% p.content_for :body do %>
+ <%= updates_for @simple_singleton do %>
+ <%= render 'account/shared/box', divider: true do |p| %>
+ <% p.content_for :title, t('.header') %>
+ <% p.content_for :description do %>
+ <%= t('.description') %>
+ <%= t('.manage_description') if can? :manage, @simple_singleton %>
+ <% end %>
+
+ <% p.content_for :body do %>
+ <% with_attribute_settings object: @simple_singleton, strategy: :label do %>
+ <%= render 'shared/attributes/text', attribute: :name %>
+ <%# 🚅 super scaffolding will insert new fields above this line. %>
+ <% end %>
+ <% end %>
+
+ <% p.content_for :actions do %>
+ <%= link_to t('.buttons.edit'), [:edit, :account, @simple_singleton], class: first_button_primary if can? :edit, @simple_singleton %>
+ <%# 🚅 super scaffolding will insert new action model buttons above this line. %>
+ <%= button_to t('.buttons.destroy'), [:account, @simple_singleton], method: :delete, class: first_button_primary, data: { confirm: t('.buttons.confirmations.destroy', model_locales(@simple_singleton)) } if can? :destroy, @simple_singleton %>
+ <%= link_to t('global.buttons.back'), [:account, @absolutely_abstract_creative_concept, :completely_concrete_simple_singletons], class: first_button_primary %>
+ <% end %>
+
+ <% p.content_for :raw_footer do %>
+ <%# 🚅 super scaffolding will insert new action model index views above this line. %>
+ <% end %>
+ <% end %>
+ <% end %>
+
+ <%# 🚅 super scaffolding will insert new children above this line. %>
+ <% end %>
+<% end %>
diff --git a/app/views/api/v1/open_api/index.yaml.erb b/app/views/api/v1/open_api/index.yaml.erb
index e885d9586..258f54c01 100644
--- a/app/views/api/v1/open_api/index.yaml.erb
+++ b/app/views/api/v1/open_api/index.yaml.erb
@@ -19,6 +19,7 @@ components:
<%= automatic_components_for User %>
<%= automatic_components_for Webhooks::Outgoing::Endpoint %>
<%= automatic_components_for Scaffolding::CompletelyConcrete::TangibleThing unless scaffolding_things_disabled? %>
+ <%= automatic_components_for Scaffolding::CompletelyConcrete::SimpleSingleton %>
<%# 🚅 super scaffolding will insert new components above this line. %>
parameters:
id:
@@ -50,4 +51,5 @@ paths:
<%= paths_for User %>
<%= automatic_paths_for Webhooks::Outgoing::Endpoint, Team %>
<%= automatic_paths_for Scaffolding::CompletelyConcrete::TangibleThing, Scaffolding::AbsolutelyAbstract::CreativeConcept unless scaffolding_things_disabled? %>
+ <%= automatic_paths_for Scaffolding::CompletelyConcrete::SimpleSingleton, Scaffolding::AbsolutelyAbstract::CreativeConcept %>
<%# 🚅 super scaffolding will insert new paths above this line. %>
diff --git a/app/views/api/v1/scaffolding/completely_concrete/simple_singletons/_simple_singleton.json.jbuilder b/app/views/api/v1/scaffolding/completely_concrete/simple_singletons/_simple_singleton.json.jbuilder
new file mode 100644
index 000000000..aa12351f6
--- /dev/null
+++ b/app/views/api/v1/scaffolding/completely_concrete/simple_singletons/_simple_singleton.json.jbuilder
@@ -0,0 +1,7 @@
+json.extract! simple_singleton,
+ :id,
+ :absolutely_abstract_creative_concept_id,
+ :name,
+ # 🚅 super scaffolding will insert new fields above this line.
+ :created_at,
+ :updated_at
diff --git a/app/views/api/v1/scaffolding/completely_concrete/simple_singletons/index.json.jbuilder b/app/views/api/v1/scaffolding/completely_concrete/simple_singletons/index.json.jbuilder
new file mode 100644
index 000000000..8170ba642
--- /dev/null
+++ b/app/views/api/v1/scaffolding/completely_concrete/simple_singletons/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @simple_singletons, partial: "api/v1/scaffolding/completely_concrete/simple_singletons/simple_singleton", as: :simple_singleton
diff --git a/app/views/api/v1/scaffolding/completely_concrete/simple_singletons/show.json.jbuilder b/app/views/api/v1/scaffolding/completely_concrete/simple_singletons/show.json.jbuilder
new file mode 100644
index 000000000..e35068814
--- /dev/null
+++ b/app/views/api/v1/scaffolding/completely_concrete/simple_singletons/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "api/v1/scaffolding/completely_concrete/simple_singletons/simple_singleton", simple_singleton: @simple_singleton
diff --git a/config/locales/en/scaffolding/completely_concrete/simple_singletons.en.yml b/config/locales/en/scaffolding/completely_concrete/simple_singletons.en.yml
new file mode 100644
index 000000000..acd41dfc6
--- /dev/null
+++ b/config/locales/en/scaffolding/completely_concrete/simple_singletons.en.yml
@@ -0,0 +1,91 @@
+en:
+ scaffolding/completely_concrete/simple_singletons: &simple_singletons
+ label: &label Simple Singletons
+ breadcrumbs:
+ label: *label
+ navigation:
+ label: *label
+ icon: fal fa-puzzle-piece
+ buttons: &buttons
+ new: Add New Simple Singleton
+ create: Create Simple Singleton
+ edit: Edit Simple Singleton
+ update: Update Simple Singleton
+ destroy: Remove Simple Singleton
+ shorthand:
+ edit: Edit
+ destroy: Delete
+ confirmations:
+ # TODO customize for your use-case.
+ destroy: Are you sure you want to remove %{simple_singleton_name}? This will also remove any child resources and can't be undone.
+ fields: &fields
+ id:
+ heading: Simple Singleton ID
+ absolutely_abstract_creative_concept_id:
+ heading: Creative Concept ID
+ name:
+ _: &name Name
+ label: *name
+ heading: *name
+ # 🚅 super scaffolding will insert new fields above this line.
+ created_at:
+ _: &created_at Added
+ label: *created_at
+ heading: *created_at
+ updated_at:
+ _: &updated_at Updated
+ label: *updated_at
+ heading: *updated_at
+ api:
+ collection_actions: "Collection Actions for Simple Singletons"
+ index: "List Simple Singletons"
+ create: "Add a New Simple Singleton"
+ member_actions: "Actions for an Individual Simple Singleton"
+ show: "Retrieve a Simple Singleton"
+ update: "Update a Simple Singleton"
+ destroy: "Delete a Simple Singleton"
+ fields: *fields
+ index:
+ section: "%{creative_concepts_possessive} Simple Singletons"
+ contexts:
+ scaffolding/absolutely_abstract/creative_concept:
+ header: Simple Singletons
+ description: Below is a list of Simple Singletons that have been added for %{creative_concept_name}.
+ description_empty: No Simple Singletons have been added for %{creative_concept_name}.
+ fields: *fields
+ buttons: *buttons
+ show:
+ section: "%{simple_singleton_name}"
+ header: Simple Singleton Details
+ description: Below are the details we have for %{simple_singleton_name}.
+ manage_description: You'll also find options for updating these details or removing %{simple_singleton_name} from %{creative_concept_name} entirely.
+ fields: *fields
+ buttons: *buttons
+ form: &form
+ buttons: *buttons
+ fields: *fields
+ new:
+ section: "New Simple Singleton for %{creative_concept_name}"
+ header: New Simple Singleton Details
+ description: Please provide the details of the new Simple Singleton you'd like to add to %{creative_concept_name}.
+ form: *form
+ edit:
+ section: "%{simple_singleton_name}"
+ header: Edit Simple Singleton Details
+ description: You can update the details or settings for %{simple_singleton_name} below.
+ form: *form
+ notifications:
+ created: Simple Singleton was successfully created.
+ updated: Simple Singleton was successfully updated.
+ destroyed: Simple Singleton was successfully destroyed.
+ account:
+ scaffolding:
+ completely_concrete:
+ simple_singletons: *simple_singletons
+ activerecord:
+ attributes:
+ scaffolding/completely_concrete/simple_singleton:
+ name: *name
+ # 🚅 super scaffolding will insert new activerecord attributes above this line.
+ created_at: *created_at
+ updated_at: *updated_at
diff --git a/config/models/roles.yml b/config/models/roles.yml
index 4584a2e9d..a1bfaf204 100644
--- a/config/models/roles.yml
+++ b/config/models/roles.yml
@@ -1,5 +1,6 @@
default:
models:
+ Scaffolding::CompletelyConcrete::SimpleSingleton: read
Team: read
Membership:
- read
@@ -28,6 +29,7 @@ admin:
- admin
- editor
models:
+ Scaffolding::CompletelyConcrete::SimpleSingleton: manage
Team: manage
Membership: manage
Scaffolding::AbsolutelyAbstract::CreativeConcept: manage
diff --git a/config/routes.rb b/config/routes.rb
index ab4c7bb36..709663a60 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -12,7 +12,7 @@
# This helps mark `resources` definitions below as not actually defining the routes for a given resource, but just
# making it possible for developers to extend definitions that are already defined by the `bullet_train` Ruby gem.
# TODO Would love to get this out of the application routes file.
- extending = {only: []}
+ extending = { only: [] }
scope module: "public" do
# To keep things organized, we put non-authenticated controllers in the `Public::` namespace.
@@ -66,6 +66,20 @@
namespace :integrations do
# 🚅 super scaffolding will insert new integration installations above this line.
end
+
+ namespace :scaffolding do
+ namespace :absolutely_abstract do
+ namespace :completely_concrete do
+ resources :simple_singletons
+ end
+ end
+
+ # resources :absolutely_abstract_creative_concepts, path: 'absolutely_abstract/creative_concepts' do
+ # namespace :completely_concrete do
+ # resources :simple_singletons
+ # end
+ # end
+ end
end
end
end
diff --git a/config/routes/api/v1.rb b/config/routes/api/v1.rb
index f20bc6a72..d604af285 100644
--- a/config/routes/api/v1.rb
+++ b/config/routes/api/v1.rb
@@ -30,6 +30,20 @@
namespace :integrations do
# 🚅 super scaffolding will insert new integration installations above this line.
end
+
+ namespace :scaffolding do
+ namespace :absolutely_abstract do
+ namespace :completely_concrete do
+ resources :simple_singletons
+ end
+ end
+
+ resources :absolutely_abstract_creative_concepts, path: 'absolutely_abstract/creative_concepts' do
+ namespace :completely_concrete do
+ resources :simple_singletons
+ end
+ end
+ end
end
end
end
diff --git a/db/migrate/20221215152529_create_scaffolding_completely_concrete_simple_singletons.rb b/db/migrate/20221215152529_create_scaffolding_completely_concrete_simple_singletons.rb
new file mode 100644
index 000000000..a0654c741
--- /dev/null
+++ b/db/migrate/20221215152529_create_scaffolding_completely_concrete_simple_singletons.rb
@@ -0,0 +1,10 @@
+class CreateScaffoldingCompletelyConcreteSimpleSingletons < ActiveRecord::Migration[7.0]
+ def change
+ create_table :scaffolding_completely_concrete_simple_singletons do |t|
+ t.references :absolutely_abstract_creative_concept, null: false, foreign_key: {to_table: "scaffolding_absolutely_abstract_creative_concepts"}, index: {name: "index_simple_singletons_on_creative_concept_id"}
+ t.string :name
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 2f2ae4741..fb5bfeafc 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.0].define(version: 2022_11_28_191001) do
+ActiveRecord::Schema[7.0].define(version: 2022_12_15_152529) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -193,6 +193,14 @@
t.index ["membership_id"], name: "index_creative_concepts_collaborators_on_membership_id"
end
+ create_table "scaffolding_completely_concrete_simple_singletons", force: :cascade do |t|
+ t.bigint "absolutely_abstract_creative_concept_id", null: false
+ t.string "name"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["absolutely_abstract_creative_concept_id"], name: "index_simple_singletons_on_creative_concept_id"
+ end
+
create_table "scaffolding_completely_concrete_tangible_things", force: :cascade do |t|
t.bigint "absolutely_abstract_creative_concept_id", null: false
t.string "text_field_value"
@@ -353,6 +361,7 @@
add_foreign_key "scaffolding_absolutely_abstract_creative_concepts", "teams"
add_foreign_key "scaffolding_absolutely_abstract_creative_concepts_collaborators", "memberships"
add_foreign_key "scaffolding_absolutely_abstract_creative_concepts_collaborators", "scaffolding_absolutely_abstract_creative_concepts", column: "creative_concept_id"
+ add_foreign_key "scaffolding_completely_concrete_simple_singletons", "scaffolding_absolutely_abstract_creative_concepts", column: "absolutely_abstract_creative_concept_id"
add_foreign_key "scaffolding_completely_concrete_tangible_things", "scaffolding_absolutely_abstract_creative_concepts", column: "absolutely_abstract_creative_concept_id"
add_foreign_key "scaffolding_completely_concrete_tangible_things_assignments", "memberships"
add_foreign_key "scaffolding_completely_concrete_tangible_things_assignments", "scaffolding_completely_concrete_tangible_things", column: "tangible_thing_id"
diff --git a/test/controllers/api/v1/scaffolding/completely_concrete/simple_singletons_controller_test.rb b/test/controllers/api/v1/scaffolding/completely_concrete/simple_singletons_controller_test.rb
new file mode 100644
index 000000000..e59ba7026
--- /dev/null
+++ b/test/controllers/api/v1/scaffolding/completely_concrete/simple_singletons_controller_test.rb
@@ -0,0 +1,115 @@
+require "controllers/api/v1/test"
+
+class Api::V1::Scaffolding::CompletelyConcrete::SimpleSingletonsControllerTest < Api::Test
+ def setup
+ # See `test/controllers/api/test.rb` for common set up for API tests.
+ super
+
+ @absolutely_abstract_creative_concept = create(:scaffolding_absolutely_abstract_creative_concept, team: @team)
+@simple_singleton = build(:scaffolding_completely_concrete_simple_singleton, absolutely_abstract_creative_concept: @absolutely_abstract_creative_concept)
+ @other_simple_singletons = create_list(:scaffolding_completely_concrete_simple_singleton, 3)
+
+ @another_simple_singleton = create(:scaffolding_completely_concrete_simple_singleton, absolutely_abstract_creative_concept: @absolutely_abstract_creative_concept)
+
+ # 🚅 super scaffolding will insert file-related logic above this line.
+ @simple_singleton.save
+ @another_simple_singleton.save
+ end
+
+ # This assertion is written in such a way that new attributes won't cause the tests to start failing, but removing
+ # data we were previously providing to users _will_ break the test suite.
+ def assert_proper_object_serialization(simple_singleton_data)
+ # Fetch the simple_singleton in question and prepare to compare it's attributes.
+ simple_singleton = Scaffolding::CompletelyConcrete::SimpleSingleton.find(simple_singleton_data["id"])
+
+ assert_equal_or_nil simple_singleton_data['name'], simple_singleton.name
+ # 🚅 super scaffolding will insert new fields above this line.
+
+ assert_equal simple_singleton_data["absolutely_abstract_creative_concept_id"], simple_singleton.absolutely_abstract_creative_concept_id
+ end
+
+ test "index" do
+ # Fetch and ensure nothing is seriously broken.
+ get "/api/v1/scaffolding/absolutely_abstract/creative_concepts/#{@absolutely_abstract_creative_concept.id}/completely_concrete/simple_singletons", params: {access_token: access_token}
+ assert_response :success
+
+ # Make sure it's returning our resources.
+ simple_singleton_ids_returned = response.parsed_body.map { |simple_singleton| simple_singleton["id"] }
+ assert_includes(simple_singleton_ids_returned, @simple_singleton.id)
+
+ # But not returning other people's resources.
+ assert_not_includes(simple_singleton_ids_returned, @other_simple_singletons[0].id)
+
+ # And that the object structure is correct.
+ assert_proper_object_serialization response.parsed_body.first
+ end
+
+ test "show" do
+ # Fetch and ensure nothing is seriously broken.
+ get "/api/v1/scaffolding/completely_concrete/simple_singletons/#{@simple_singleton.id}", params: {access_token: access_token}
+ assert_response :success
+
+ # Ensure all the required data is returned properly.
+ assert_proper_object_serialization response.parsed_body
+
+ # Also ensure we can't do that same action as another user.
+ get "/api/v1/scaffolding/completely_concrete/simple_singletons/#{@simple_singleton.id}", params: {access_token: another_access_token}
+ assert_response :not_found
+ end
+
+ test "create" do
+ # Use the serializer to generate a payload, but strip some attributes out.
+ params = {access_token: access_token}
+ simple_singleton_data = JSON.parse(build(:scaffolding_completely_concrete_simple_singleton, absolutely_abstract_creative_concept: nil).to_api_json)
+ simple_singleton_data.except!("id", "absolutely_abstract_creative_concept_id", "created_at", "updated_at")
+ params[:scaffolding_completely_concrete_simple_singleton] = simple_singleton_data
+
+ post "/api/v1/scaffolding/absolutely_abstract/creative_concepts/#{@absolutely_abstract_creative_concept.id}/completely_concrete/simple_singletons", params: params
+ assert_response :success
+
+ # # Ensure all the required data is returned properly.
+ assert_proper_object_serialization response.parsed_body
+
+ # Also ensure we can't do that same action as another user.
+ post "/api/v1/scaffolding/absolutely_abstract/creative_concepts/#{@absolutely_abstract_creative_concept.id}/completely_concrete/simple_singletons",
+ params: params.merge({access_token: another_access_token})
+ assert_response :not_found
+ end
+
+ test "update" do
+ # Post an attribute update ensure nothing is seriously broken.
+ put "/api/v1/scaffolding/completely_concrete/simple_singletons/#{@simple_singleton.id}", params: {
+ access_token: access_token,
+ scaffolding_completely_concrete_simple_singleton: {
+ name: 'Alternative String Value',
+ # 🚅 super scaffolding will also insert new fields above this line.
+ }
+ }
+
+ assert_response :success
+
+ # Ensure all the required data is returned properly.
+ assert_proper_object_serialization response.parsed_body
+
+ # But we have to manually assert the value was properly updated.
+ @simple_singleton.reload
+ assert_equal @simple_singleton.name, 'Alternative String Value'
+ # 🚅 super scaffolding will additionally insert new fields above this line.
+
+ # Also ensure we can't do that same action as another user.
+ put "/api/v1/scaffolding/completely_concrete/simple_singletons/#{@simple_singleton.id}", params: {access_token: another_access_token}
+ assert_response :not_found
+ end
+
+ test "destroy" do
+ # Delete and ensure it actually went away.
+ assert_difference("Scaffolding::CompletelyConcrete::SimpleSingleton.count", -1) do
+ delete "/api/v1/scaffolding/completely_concrete/simple_singletons/#{@simple_singleton.id}", params: {access_token: access_token}
+ assert_response :success
+ end
+
+ # Also ensure we can't do that same action as another user.
+ delete "/api/v1/scaffolding/completely_concrete/simple_singletons/#{@another_simple_singleton.id}", params: {access_token: another_access_token}
+ assert_response :not_found
+ end
+end
diff --git a/test/factories/scaffolding/completely_concrete/simple_singletons.rb b/test/factories/scaffolding/completely_concrete/simple_singletons.rb
new file mode 100644
index 000000000..2bfa0ab0b
--- /dev/null
+++ b/test/factories/scaffolding/completely_concrete/simple_singletons.rb
@@ -0,0 +1,6 @@
+FactoryBot.define do
+ factory :scaffolding_completely_concrete_simple_singleton, class: 'Scaffolding::CompletelyConcrete::SimpleSingleton' do
+ association :absolutely_abstract_creative_concept, factory: :scaffolding_absolutely_abstract_creative_concept
+ name { "MyString" }
+ end
+end
diff --git a/test/models/scaffolding/completely_concrete/simple_singleton_test.rb b/test/models/scaffolding/completely_concrete/simple_singleton_test.rb
new file mode 100644
index 000000000..fac551d1d
--- /dev/null
+++ b/test/models/scaffolding/completely_concrete/simple_singleton_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class Scaffolding::CompletelyConcrete::SimpleSingletonTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end