Class: InlineForms::SchemaController

Inherits:
InlineFormsApplicationController
  • Object
show all
Defined in:
app/controllers/inline_forms/schema_controller.rb

Overview

GUI to add a field to a model through the browser, building on the schema-staging services in inline_forms. Two ways to act on an intent:

  • DIRECT APPLY (dev only, the phase-0 flow): create runs inline_forms_addto in-process (model edit + migration file) but NOT db:migrate; the pending-migration gate covers the window.
  • BATCH DRAFTING (the pipeline flow): draft persists the intent into the current draft SchemaBatch (the "cart"); submit_batch freezes it for the automated pull -> CI -> deploy loop. Nothing is generated in the request cycle.

Production posture: direct apply is NEVER available in production (production never writes code). Drafting is also non-production unless the app opts in (InlineFormsSchemaEdit.production_drafting = true — the SaaS tenant case). The machine endpoints (export/batch_status) are token-authenticated and environment-independent, for the CI side.

Constant Summary collapse

HEADER =
InlineFormsSchemaEdit::IntentValidator::HEADER

Instance Method Summary collapse

Instance Method Details

#batch_statusObject

MACHINE ENDPOINT (token): CI reports progress back. Params: status (processing|ready|applied|failed), git_sha, error.



130
131
132
133
134
135
136
# File 'app/controllers/inline_forms/schema_controller.rb', line 130

def batch_status
  batch = InlineForms::SchemaBatch.find(params[:id])
  batch.transition!(params[:status].to_s, git_sha: params[:git_sha].presence, error: params[:error].presence)
  render json: { id: batch.id, status: batch.status }
rescue ArgumentError => e
  render json: { error: e.message }, status: :unprocessable_entity
end

#createObject

DIRECT APPLY (dev only): codegen into this checkout's tree.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'app/controllers/inline_forms/schema_controller.rb', line 63

def create
  @intent_params = intent_params
  @error = InlineFormsSchemaEdit::IntentValidator.error_for(@intent_params)
  return render(:new) if @error

  @intent    = build_intent(@intent_params)
  @is_header = @intent.form_element == :header
  begin
    @migration_path = InlineForms::SchemaApply.new(@intent).generate!(
      destination_root: Rails.root,
      executor: generator_executor || InlineForms::SchemaApply::DEFAULT_GENERATE_EXECUTOR
    )
    @migration_basename = @migration_path && File.basename(@migration_path)
    write_label!
  rescue StandardError => e
    @error = "Generator failed: #{e.message}"
    render(:new)
  end
end

#draftObject

BATCH DRAFTING: persist the intent into the current draft batch.



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'app/controllers/inline_forms/schema_controller.rb', line 84

def draft
  @intent_params = intent_params
  @error = InlineFormsSchemaEdit::IntentValidator.error_for(@intent_params)
  return render(:new) if @error

  batch = InlineForms::SchemaBatch.current_draft
  batch.intents.create!(
    target_model: @intent_params[:model_name],
    attr_name:    @intent_params[:attribute],
    form_element: @intent_params[:form_element],
    after_attr:   @intent_params[:after].presence,
    label:        @intent_params[:label].presence,
    locale:       @intent_params[:locale].presence
  )
  redirect_to inline_forms_schema_index_path
end

#exportObject

MACHINE ENDPOINT (token): the frozen batch as JSON for the CI side.



121
122
123
124
125
126
# File 'app/controllers/inline_forms/schema_controller.rb', line 121

def export
  batch = InlineForms::SchemaBatch.find(params[:id])
  return render(json: { error: "batch is still a draft" }, status: :conflict) if batch.draft?

  render json: InlineFormsSchemaEdit::BatchExport.payload(batch)
end

#indexObject

The cart + batch history.



38
39
40
41
# File 'app/controllers/inline_forms/schema_controller.rb', line 38

def index
  @draft_batch = InlineForms::SchemaBatch.with_status(:draft).order(:id).first
  @batches = InlineForms::SchemaBatch.where.not(status: "draft").order(id: :desc).limit(25)
end

#newObject



43
44
45
# File 'app/controllers/inline_forms/schema_controller.rb', line 43

def new
  @intent_params = blank_intent_params
end

#previewObject



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'app/controllers/inline_forms/schema_controller.rb', line 47

def preview
  @intent_params = intent_params
  @error = InlineFormsSchemaEdit::IntentValidator.error_for(@intent_params)
  return render(:new) if @error

  @intent    = build_intent(@intent_params)
  @is_header = @intent.form_element == :header
  if @is_header
    @attribute_list = InlineForms::SchemaPreview.attribute_list_for(@intent.model_class, @intent)
  else
    @preview, @attribute_list = InlineForms::SchemaPreview.build(@intent)
  end
  @batching_available = batch_tables_present?
end

#remove_draftObject



101
102
103
104
105
106
107
108
109
# File 'app/controllers/inline_forms/schema_controller.rb', line 101

def remove_draft
  intent = InlineForms::SchemaIntentRecord.find(params[:id])
  if intent.batch&.draft?
    intent.destroy
    redirect_to inline_forms_schema_index_path
  else
    redirect_to inline_forms_schema_index_path, alert: "Batch is frozen."
  end
end

#submit_batchObject



111
112
113
114
115
116
117
118
# File 'app/controllers/inline_forms/schema_controller.rb', line 111

def submit_batch
  batch = InlineForms::SchemaBatch.current_draft
  window = params[:window_at].presence && Time.zone.parse(params[:window_at])
  batch.submit!(requested_by: requesting_identity, window_at: window)
  redirect_to inline_forms_schema_index_path
rescue ArgumentError => e
  redirect_to inline_forms_schema_index_path, alert: e.message
end