airview 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/airview/application.css +7 -0
- data/app/controllers/airview/resources_controller.rb +2 -0
- data/app/controllers/airview/setup_controller.rb +7 -1
- data/app/helpers/airview/application_helper.rb +34 -0
- data/app/models/airview/field_definition.rb +53 -0
- data/app/views/airview/resources/empty.html.erb +8 -2
- data/app/views/airview/setup/_form.html.erb +4 -1
- data/app/views/airview/setup/edit.html.erb +4 -1
- data/config/routes.rb +1 -0
- data/lib/airview/query.rb +14 -1
- data/lib/airview/resource.rb +9 -0
- data/lib/airview/resource_builder.rb +56 -1
- data/lib/airview/resource_synchronizer.rb +27 -0
- data/lib/airview/version.rb +1 -1
- data/lib/airview.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4698348a323226676e3caba98313791047e11f6ca61d5481c4161e93b72df435
|
|
4
|
+
data.tar.gz: 991db64ebdb3d015d6a57b7f2cc008b9d1bdad64cca67f2b87727f6aa7533be1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 057bac0d19e8c39a2e1238eab49cf778d84dffb742ea7e67abb1e50622cbdbd8539b55b71b661f117598f60dd3efeec1141838aa9d2aff08801cdd9410d1fe8d
|
|
7
|
+
data.tar.gz: f276cd3b707856ee4b2b3b0e554d4dda4cead471cb6de46aacc64f0474af45d06cf538f16255ff86abd3a6cf3f62435444937ac9a917d29cf903e96aa3da1b26
|
|
@@ -474,6 +474,13 @@
|
|
|
474
474
|
gap: 12px;
|
|
475
475
|
}
|
|
476
476
|
|
|
477
|
+
.airview-toolbar-actions {
|
|
478
|
+
align-items: center;
|
|
479
|
+
display: flex;
|
|
480
|
+
flex-wrap: wrap;
|
|
481
|
+
gap: 8px;
|
|
482
|
+
}
|
|
483
|
+
|
|
477
484
|
.airview-setup-table .airview-actions,
|
|
478
485
|
.airview-setup-fields .airview-actions {
|
|
479
486
|
white-space: nowrap;
|
|
@@ -15,6 +15,8 @@ module Airview
|
|
|
15
15
|
|
|
16
16
|
def show
|
|
17
17
|
@resources = Airview.resources.values
|
|
18
|
+
return render(:empty) if @resource.fields.empty?
|
|
19
|
+
|
|
18
20
|
@views = View.for_resource(@resource.key).ordered
|
|
19
21
|
@active_view = @views.find { |view| view.id.to_s == params[:view_id].to_s }
|
|
20
22
|
@sorted_fields = @resource.fields.values.sort_by { |field| field.label.downcase }
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Airview
|
|
4
4
|
class SetupController < ApplicationController
|
|
5
|
-
before_action :set_definition, only: %i[edit update destroy]
|
|
5
|
+
before_action :set_definition, only: %i[edit update sync destroy]
|
|
6
6
|
|
|
7
7
|
def index
|
|
8
8
|
@models = ModelDiscovery.models
|
|
@@ -37,6 +37,12 @@ module Airview
|
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
def sync
|
|
41
|
+
added_count = ResourceSynchronizer.new(@definition).sync_missing_fields
|
|
42
|
+
field_label = "field".pluralize(added_count)
|
|
43
|
+
redirect_to edit_setup_resource_path(@definition), notice: "#{added_count} #{field_label} added"
|
|
44
|
+
end
|
|
45
|
+
|
|
40
46
|
def destroy
|
|
41
47
|
@definition.destroy!
|
|
42
48
|
redirect_to setup_path, notice: "Resource removed"
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
module Airview
|
|
4
4
|
module ApplicationHelper
|
|
5
5
|
def airview_field_value(record, field)
|
|
6
|
+
return nil unless airview_field_available?(record, field)
|
|
7
|
+
|
|
6
8
|
value = record.public_send(field.name)
|
|
7
9
|
return value if field.collection_association?
|
|
8
10
|
return Airview.record_label(value, field.label_method) if field.association? && value
|
|
@@ -13,6 +15,7 @@ module Airview
|
|
|
13
15
|
|
|
14
16
|
def airview_cell_value(record, field)
|
|
15
17
|
value = airview_field_value(record, field)
|
|
18
|
+
return tag.span("", class: "airview-empty-value") unless airview_field_available?(record, field)
|
|
16
19
|
|
|
17
20
|
case field.type
|
|
18
21
|
when :boolean
|
|
@@ -37,6 +40,7 @@ module Airview
|
|
|
37
40
|
def airview_input_for(record, field)
|
|
38
41
|
value = airview_field_value(record, field)
|
|
39
42
|
name = "record[#{field.name}]"
|
|
43
|
+
return text_field_tag(name, nil, disabled: true) unless airview_field_available?(record, field)
|
|
40
44
|
|
|
41
45
|
case field.type
|
|
42
46
|
when :boolean
|
|
@@ -189,6 +193,8 @@ module Airview
|
|
|
189
193
|
end
|
|
190
194
|
|
|
191
195
|
def airview_reference_pill(record, field)
|
|
196
|
+
return tag.span("", class: "airview-empty-value") unless airview_field_available?(record, field)
|
|
197
|
+
|
|
192
198
|
related = record.public_send(field.name)
|
|
193
199
|
return tag.span("+ Link record", class: "airview-reference-empty") unless related
|
|
194
200
|
|
|
@@ -204,6 +210,8 @@ module Airview
|
|
|
204
210
|
end
|
|
205
211
|
|
|
206
212
|
def airview_collection_pills(record, field)
|
|
213
|
+
return tag.span("0 records", class: "airview-reference-empty") unless airview_field_available?(record, field)
|
|
214
|
+
|
|
207
215
|
records = record.public_send(field.name).limit(3).to_a
|
|
208
216
|
count = airview_collection_count(record, field)
|
|
209
217
|
|
|
@@ -225,6 +233,8 @@ module Airview
|
|
|
225
233
|
end
|
|
226
234
|
|
|
227
235
|
def airview_attachment_cell(record, field)
|
|
236
|
+
return tag.span("No file", class: "airview-reference-empty") unless airview_field_available?(record, field)
|
|
237
|
+
|
|
228
238
|
attachment = record.public_send(field.name)
|
|
229
239
|
return tag.span("No file", class: "airview-reference-empty") unless attachment.attached?
|
|
230
240
|
|
|
@@ -241,6 +251,8 @@ module Airview
|
|
|
241
251
|
end
|
|
242
252
|
|
|
243
253
|
def airview_reference_input(record, field, name)
|
|
254
|
+
return text_field_tag(name, nil, disabled: true) unless airview_field_available?(record, field)
|
|
255
|
+
|
|
244
256
|
related = record.public_send(field.name)
|
|
245
257
|
|
|
246
258
|
safe_join(
|
|
@@ -427,11 +439,33 @@ module Airview
|
|
|
427
439
|
return "##{record.id}" unless linked_resource
|
|
428
440
|
|
|
429
441
|
linked_resource.fields.values.reject(&:association?).first(3).filter_map do |field|
|
|
442
|
+
next unless airview_field_available?(record, field)
|
|
443
|
+
|
|
430
444
|
value = airview_field_value(record, field)
|
|
431
445
|
"#{field.label}: #{value}" if value.present?
|
|
432
446
|
end.join(" · ")
|
|
433
447
|
end
|
|
434
448
|
|
|
449
|
+
def airview_field_available?(record, field)
|
|
450
|
+
model_class = record.class
|
|
451
|
+
|
|
452
|
+
case field.type
|
|
453
|
+
when :belongs_to
|
|
454
|
+
association = model_class.reflect_on_association(field.name) if model_class.respond_to?(:reflect_on_association)
|
|
455
|
+
association&.macro == :belongs_to && model_class.column_names.include?(association.foreign_key.to_s)
|
|
456
|
+
when :has_many
|
|
457
|
+
association = model_class.reflect_on_association(field.name) if model_class.respond_to?(:reflect_on_association)
|
|
458
|
+
association&.macro == :has_many
|
|
459
|
+
when :attachment
|
|
460
|
+
model_class.respond_to?(:attachment_reflections) &&
|
|
461
|
+
model_class.attachment_reflections.key?(field.name.to_s)
|
|
462
|
+
else
|
|
463
|
+
model_class.respond_to?(:column_names) && model_class.column_names.include?(field.name.to_s)
|
|
464
|
+
end
|
|
465
|
+
rescue ActiveRecord::StatementInvalid, NameError
|
|
466
|
+
false
|
|
467
|
+
end
|
|
468
|
+
|
|
435
469
|
def airview_resource_for_model(model)
|
|
436
470
|
Airview.resources.values.find { |resource| resource.model == model.to_s }
|
|
437
471
|
end
|
|
@@ -18,5 +18,58 @@ module Airview
|
|
|
18
18
|
def default_visible?
|
|
19
19
|
metadata.fetch("default_visible", true)
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
def stale?
|
|
23
|
+
!schema_backed?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def stale_reason
|
|
27
|
+
return nil if schema_backed?
|
|
28
|
+
|
|
29
|
+
case field_type.to_sym
|
|
30
|
+
when :belongs_to
|
|
31
|
+
"Missing belongs_to association or foreign key"
|
|
32
|
+
when :has_many
|
|
33
|
+
"Missing has_many association"
|
|
34
|
+
when :attachment
|
|
35
|
+
"Missing attachment"
|
|
36
|
+
else
|
|
37
|
+
"Missing column"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def schema_backed?
|
|
42
|
+
model_class = resource_definition.model_class
|
|
43
|
+
|
|
44
|
+
case field_type.to_sym
|
|
45
|
+
when :belongs_to
|
|
46
|
+
belongs_to_schema_backed?(model_class)
|
|
47
|
+
when :has_many
|
|
48
|
+
association = model_class.reflect_on_association(name.to_sym)
|
|
49
|
+
association&.macro == :has_many
|
|
50
|
+
when :attachment
|
|
51
|
+
attachment_names(model_class).include?(name.to_s)
|
|
52
|
+
else
|
|
53
|
+
model_class.column_names.include?(name.to_s)
|
|
54
|
+
end
|
|
55
|
+
rescue ActiveRecord::StatementInvalid, NameError
|
|
56
|
+
false
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def belongs_to_schema_backed?(model_class)
|
|
62
|
+
association_key = association_name.presence || name
|
|
63
|
+
association = model_class.reflect_on_association(association_key.to_sym)
|
|
64
|
+
return false unless association&.macro == :belongs_to
|
|
65
|
+
|
|
66
|
+
model_class.column_names.include?(association.foreign_key.to_s)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def attachment_names(model_class)
|
|
70
|
+
return [] unless model_class.respond_to?(:attachment_reflections)
|
|
71
|
+
|
|
72
|
+
model_class.attachment_reflections.keys.map(&:to_s)
|
|
73
|
+
end
|
|
21
74
|
end
|
|
22
75
|
end
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
<main class="airview-empty">
|
|
2
|
-
<h1
|
|
3
|
-
<p>
|
|
2
|
+
<h1><%= @resource&.label || "Airview" %></h1>
|
|
3
|
+
<p>
|
|
4
|
+
<% if @resource %>
|
|
5
|
+
No available fields are backed by the current schema.
|
|
6
|
+
<% else %>
|
|
7
|
+
No resources are enabled yet.
|
|
8
|
+
<% end %>
|
|
9
|
+
</p>
|
|
4
10
|
<%= link_to "Configure resources", setup_path %>
|
|
5
11
|
</main>
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
<th>Visible</th>
|
|
38
38
|
<th>Readonly</th>
|
|
39
39
|
<th>Name</th>
|
|
40
|
+
<th>Status</th>
|
|
40
41
|
<th>Label</th>
|
|
41
42
|
<th>Type</th>
|
|
42
43
|
<th>Order</th>
|
|
@@ -46,8 +47,9 @@
|
|
|
46
47
|
</thead>
|
|
47
48
|
<tbody>
|
|
48
49
|
<%= form.fields_for :field_definitions do |field_form| %>
|
|
50
|
+
<% stale = field_form.object.stale? %>
|
|
49
51
|
<tr>
|
|
50
|
-
<td><%= field_form.check_box :visible %></td>
|
|
52
|
+
<td><%= field_form.check_box :visible, disabled: stale %></td>
|
|
51
53
|
<td><%= field_form.check_box :read_only %></td>
|
|
52
54
|
<td>
|
|
53
55
|
<%= field_form.hidden_field :id if field_form.object.persisted? %>
|
|
@@ -55,6 +57,7 @@
|
|
|
55
57
|
<%= field_form.hidden_field :association_name %>
|
|
56
58
|
<%= field_form.object.name %>
|
|
57
59
|
</td>
|
|
60
|
+
<td><%= stale ? field_form.object.stale_reason : "Available" %></td>
|
|
58
61
|
<td><%= field_form.text_field :label %></td>
|
|
59
62
|
<td><%= field_form.select :field_type, Airview::Field::TYPES.map { |type| [type.to_s.humanize, type] } %></td>
|
|
60
63
|
<td><%= field_form.number_field :position, min: 0 %></td>
|
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
<p><%= @definition.record_class_name %></p>
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
<div class="airview-toolbar-actions">
|
|
12
|
+
<%= button_to "Sync fields", sync_setup_resource_path(@definition), method: :post %>
|
|
13
|
+
<%= button_to "Remove resource", setup_resource_path(@definition), method: :delete, form: { data: { turbo_confirm: "Remove this Airview resource?" } } %>
|
|
14
|
+
</div>
|
|
12
15
|
</header>
|
|
13
16
|
|
|
14
17
|
<%= render "form", definition: @definition, url: setup_resource_path(@definition), method: :patch %>
|
data/config/routes.rb
CHANGED
|
@@ -8,6 +8,7 @@ Airview::Engine.routes.draw do
|
|
|
8
8
|
post "/setup/resources", to: "setup#create", as: :setup_resources
|
|
9
9
|
get "/setup/resources/:id/edit", to: "setup#edit", as: :edit_setup_resource
|
|
10
10
|
patch "/setup/resources/:id", to: "setup#update", as: :setup_resource
|
|
11
|
+
post "/setup/resources/:id/sync", to: "setup#sync", as: :sync_setup_resource
|
|
11
12
|
delete "/setup/resources/:id", to: "setup#destroy"
|
|
12
13
|
|
|
13
14
|
get "/resources", to: "resources#index", as: :resources
|
data/lib/airview/query.rb
CHANGED
|
@@ -43,7 +43,9 @@ module Airview
|
|
|
43
43
|
term = params[:q].to_s.strip
|
|
44
44
|
return scope if term.empty?
|
|
45
45
|
|
|
46
|
-
searchable = resource.fields.values.select
|
|
46
|
+
searchable = resource.fields.values.select do |field|
|
|
47
|
+
%i[string text select].include?(field.type) && queryable_field?(scope, field)
|
|
48
|
+
end
|
|
47
49
|
return scope if searchable.empty?
|
|
48
50
|
|
|
49
51
|
clauses = searchable.map do |field|
|
|
@@ -63,6 +65,7 @@ module Airview
|
|
|
63
65
|
|
|
64
66
|
field = resource.fields[name.to_sym]
|
|
65
67
|
next unless field
|
|
68
|
+
next unless queryable_field?(scope, field)
|
|
66
69
|
|
|
67
70
|
scope = apply_filter(scope, field, value)
|
|
68
71
|
end
|
|
@@ -82,6 +85,7 @@ module Airview
|
|
|
82
85
|
field = resource.fields[condition["field"].to_s.to_sym]
|
|
83
86
|
next unless field
|
|
84
87
|
next unless field.filterable?
|
|
88
|
+
next unless queryable_field?(scope, field)
|
|
85
89
|
|
|
86
90
|
scope = apply_structured_filter(scope, field, condition["operator"], condition["value"])
|
|
87
91
|
end
|
|
@@ -183,10 +187,19 @@ module Airview
|
|
|
183
187
|
field = resource.fields[sort.to_sym]
|
|
184
188
|
return scope unless field
|
|
185
189
|
return scope unless field.sortable?
|
|
190
|
+
return scope unless queryable_field?(scope, field)
|
|
186
191
|
|
|
187
192
|
scope.order(field.attribute_name => direction)
|
|
188
193
|
end
|
|
189
194
|
|
|
195
|
+
def queryable_field?(scope, field)
|
|
196
|
+
return false if field.display_only?
|
|
197
|
+
|
|
198
|
+
scope.klass.column_names.include?(field.attribute_name.to_s)
|
|
199
|
+
rescue NameError
|
|
200
|
+
false
|
|
201
|
+
end
|
|
202
|
+
|
|
190
203
|
def sanitize_like(value)
|
|
191
204
|
ActiveRecord::Base.sanitize_sql_like(value.to_s)
|
|
192
205
|
end
|
data/lib/airview/resource.rb
CHANGED
|
@@ -11,6 +11,7 @@ module Airview
|
|
|
11
11
|
@label = key.to_s.humanize
|
|
12
12
|
@label_method = :to_s
|
|
13
13
|
@fields = {}
|
|
14
|
+
@stale_fields = []
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def field(name, type:, label: nil, **options)
|
|
@@ -38,6 +39,14 @@ module Airview
|
|
|
38
39
|
fields.values.select(&:default_visible?)
|
|
39
40
|
end
|
|
40
41
|
|
|
42
|
+
def stale_fields
|
|
43
|
+
@stale_fields.dup
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def add_stale_field(field, reason:)
|
|
47
|
+
@stale_fields << { name: field.name.to_sym, label: field.label, reason: }
|
|
48
|
+
end
|
|
49
|
+
|
|
41
50
|
def validate!
|
|
42
51
|
raise ConfigurationError, "Airview resource #{key} must define at least one field" if fields.empty?
|
|
43
52
|
|
|
@@ -18,7 +18,12 @@ module Airview
|
|
|
18
18
|
resource.label_method = definition.label_method.presence&.to_sym || :to_s
|
|
19
19
|
|
|
20
20
|
definition.field_definitions.visible.order(:position, :name).each do |field|
|
|
21
|
-
|
|
21
|
+
if field_schema_backed?(resource.model_class, field)
|
|
22
|
+
add_field(resource, field)
|
|
23
|
+
else
|
|
24
|
+
resource.add_stale_field(field, reason: stale_reason(resource.model_class, field))
|
|
25
|
+
log_stale_field(resource, field)
|
|
26
|
+
end
|
|
22
27
|
end
|
|
23
28
|
|
|
24
29
|
add_missing_virtual_fields(resource, definition)
|
|
@@ -57,6 +62,56 @@ module Airview
|
|
|
57
62
|
)
|
|
58
63
|
end
|
|
59
64
|
end
|
|
65
|
+
|
|
66
|
+
def field_schema_backed?(model_class, field)
|
|
67
|
+
case field.field_type.to_sym
|
|
68
|
+
when :belongs_to
|
|
69
|
+
belongs_to_schema_backed?(model_class, field)
|
|
70
|
+
when :has_many
|
|
71
|
+
association = model_class.reflect_on_association(field.name.to_sym)
|
|
72
|
+
association&.macro == :has_many
|
|
73
|
+
when :attachment
|
|
74
|
+
attachment_names(model_class).include?(field.name.to_s)
|
|
75
|
+
else
|
|
76
|
+
model_class.column_names.include?(field.name.to_s)
|
|
77
|
+
end
|
|
78
|
+
rescue NameError
|
|
79
|
+
false
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def belongs_to_schema_backed?(model_class, field)
|
|
83
|
+
association_name = field.association_name.presence || field.name
|
|
84
|
+
association = model_class.reflect_on_association(association_name.to_sym)
|
|
85
|
+
return false unless association&.macro == :belongs_to
|
|
86
|
+
|
|
87
|
+
model_class.column_names.include?(association.foreign_key.to_s)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def attachment_names(model_class)
|
|
91
|
+
return [] unless model_class.respond_to?(:attachment_reflections)
|
|
92
|
+
|
|
93
|
+
model_class.attachment_reflections.keys.map(&:to_s)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def stale_reason(model_class, field)
|
|
97
|
+
case field.field_type.to_sym
|
|
98
|
+
when :belongs_to
|
|
99
|
+
"missing belongs_to association or foreign key on #{model_class.name}"
|
|
100
|
+
when :has_many
|
|
101
|
+
"missing has_many association on #{model_class.name}"
|
|
102
|
+
when :attachment
|
|
103
|
+
"missing attachment on #{model_class.name}"
|
|
104
|
+
else
|
|
105
|
+
"missing column on #{model_class.name}"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def log_stale_field(resource, field)
|
|
110
|
+
return unless defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
|
|
111
|
+
|
|
112
|
+
reason = stale_reason(resource.model_class, field)
|
|
113
|
+
Rails.logger.warn("Airview skipped stale field #{field.name.inspect} for #{resource.model}: #{reason}")
|
|
114
|
+
end
|
|
60
115
|
end
|
|
61
116
|
end
|
|
62
117
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Airview
|
|
4
|
+
class ResourceSynchronizer
|
|
5
|
+
attr_reader :definition
|
|
6
|
+
|
|
7
|
+
def initialize(definition)
|
|
8
|
+
@definition = definition
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def sync_missing_fields
|
|
12
|
+
existing_names = definition.field_definitions.map { |field| field.name.to_s }
|
|
13
|
+
position = definition.field_definitions.map(&:position).compact.max.to_i
|
|
14
|
+
added_count = 0
|
|
15
|
+
|
|
16
|
+
SchemaInference.new(definition.model_class).field_attributes.each do |attributes|
|
|
17
|
+
next if existing_names.include?(attributes[:name].to_s)
|
|
18
|
+
|
|
19
|
+
position += 1
|
|
20
|
+
definition.field_definitions.create!(attributes.merge(position:))
|
|
21
|
+
added_count += 1
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
added_count
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lib/airview/version.rb
CHANGED
data/lib/airview.rb
CHANGED
|
@@ -13,6 +13,7 @@ require_relative "airview/resource"
|
|
|
13
13
|
require_relative "airview/query"
|
|
14
14
|
require_relative "airview/model_discovery"
|
|
15
15
|
require_relative "airview/resource_builder"
|
|
16
|
+
require_relative "airview/resource_synchronizer"
|
|
16
17
|
require_relative "airview/schema_inference"
|
|
17
18
|
require_relative "airview/engine" if defined?(Rails)
|
|
18
19
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: airview
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- jacksonriso
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -74,6 +74,7 @@ files:
|
|
|
74
74
|
- lib/airview/query.rb
|
|
75
75
|
- lib/airview/resource.rb
|
|
76
76
|
- lib/airview/resource_builder.rb
|
|
77
|
+
- lib/airview/resource_synchronizer.rb
|
|
77
78
|
- lib/airview/schema_inference.rb
|
|
78
79
|
- lib/airview/version.rb
|
|
79
80
|
- lib/generators/airview/install/install_generator.rb
|