chobble-forms 0.6.0 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32610a1903913985762082f5865bd24bfcae7327bf887cafa70c09db7efe9e88
4
- data.tar.gz: 4d0e15de04ab8ceee7fac1fea871d83582caf5bc96e4cc39760ef7e1297c8915
3
+ metadata.gz: 114cd63966175b3b8f30be99441ff3da688526f9e46bc0b08c9add531c93d8eb
4
+ data.tar.gz: 225988209e98465f4c92d14729ad9650878519d1563cea5486f90b3342d8a28e
5
5
  SHA512:
6
- metadata.gz: c70cbe6796e0edba08b2c41c5e476401d4579cc86de865710a772c0f4ef570abacd76f4ec08033d1d405ef887cdf44b52aa5f4e82c07085270c28186f5fb7532
7
- data.tar.gz: d9b8cc2aff3b86e9de10b189a44f2d2a9f651a236b87da01dd0095bc27fb81b8ea034f14d72655ae580fa4cd26a777674c3a2db78225769eca42af134e176208
6
+ metadata.gz: 934333541f43b3fd5f8f0c24468f15a1d755b5567c0c341a856c6fedb67932f2a606d93452741ca26531a107d30cbd21363f1ec27f4acc7059a001edc3ca42ac
7
+ data.tar.gz: 535ab94d5f12ca207fd4c34d198e3938161465112819c0df18ea8cfa7c8f33ab29d8f44e9112aab6a011bf1889e49cf99e527223dadcdcb920f41830dbea7065
@@ -7,23 +7,21 @@ module ChobbleForms
7
7
  module FieldUtils
8
8
  extend T::Sig
9
9
 
10
- sig { params(field: Symbol).returns(String) }
10
+ sig { params(field: Symbol).returns(Symbol) }
11
11
  def self.strip_field_suffix(field)
12
- field.to_s.gsub(/_pass$|_comment$/, "")
12
+ field.to_s.gsub(/_pass$|_comment$/, "").to_sym
13
13
  end
14
14
 
15
- sig { params(field: Symbol, partial: Symbol).returns(T::Array[String]) }
15
+ sig { params(field: Symbol, partial: Symbol).returns(T::Array[Symbol]) }
16
16
  def self.get_composite_fields(field, partial)
17
- fields = T.let([], T::Array[String])
17
+ fields = T.let([], T::Array[Symbol])
18
18
  partial_str = partial.to_s
19
19
 
20
- if partial_str.include?("pass_fail") && !field.to_s.end_with?("_pass")
21
- fields << "#{field}_pass"
22
- end
20
+ fields << :"#{field}_pass" if partial_str.include?("pass_fail") && !field.to_s.end_with?("_pass")
23
21
 
24
22
  if partial_str.include?("comment")
25
23
  base = field.to_s.end_with?("_pass") ? strip_field_suffix(field) : field
26
- fields << "#{base}_comment"
24
+ fields << :"#{base}_comment"
27
25
  end
28
26
 
29
27
  fields
@@ -44,7 +42,7 @@ module ChobbleForms
44
42
  is_pass_field?(field) || is_comment_field?(field)
45
43
  end
46
44
 
47
- sig { params(field: Symbol).returns(String) }
45
+ sig { params(field: Symbol).returns(Symbol) }
48
46
  def self.base_field_name(field)
49
47
  strip_field_suffix(field)
50
48
  end
@@ -53,5 +51,10 @@ module ChobbleForms
53
51
  def self.form_field_label(form, field)
54
52
  I18n.t("forms.#{form}.fields.#{field}")
55
53
  end
54
+
55
+ sig { params(assessment_key: Symbol).returns(Symbol) }
56
+ def self.form_name_from_assessment(assessment_key)
57
+ assessment_key.to_s.gsub(/_assessment$/, "").to_sym
58
+ end
56
59
  end
57
60
  end
@@ -7,7 +7,35 @@ module ChobbleForms
7
7
  module Helpers
8
8
  extend T::Sig
9
9
 
10
- sig { params(field: Symbol, local_assigns: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
10
+ SelectOption = T.type_alias {
11
+ [String, T.any(String, Integer)]
12
+ }
13
+
14
+ LocalAssignValue = T.type_alias {
15
+ T.any(
16
+ String,
17
+ Symbol,
18
+ Integer,
19
+ Float,
20
+ T::Boolean,
21
+ T::Array[SelectOption],
22
+ T::Hash[Symbol, T.untyped]
23
+ )
24
+ }
25
+
26
+ FieldSetupResult = T.type_alias {
27
+ {
28
+ form_object: T.untyped,
29
+ i18n_base: String,
30
+ value: T.untyped,
31
+ prefilled: T::Boolean,
32
+ field_label: String,
33
+ field_hint: T.nilable(String),
34
+ field_placeholder: T.nilable(String)
35
+ }
36
+ }
37
+
38
+ sig { params(field: Symbol, local_assigns: T::Hash[Symbol, LocalAssignValue]).returns(FieldSetupResult) }
11
39
  def form_field_setup(field, local_assigns)
12
40
  validate_local_assigns(local_assigns)
13
41
  validate_form_context
@@ -22,6 +50,7 @@ module ChobbleForms
22
50
  sig { params(form_object: T.untyped, field: Symbol).returns([T.untyped, T::Boolean]) }
23
51
  def get_field_value_and_prefilled_status(form_object, field)
24
52
  return [nil, false] unless form_object&.object
53
+
25
54
  model = form_object.object
26
55
  resolved = resolve_field_value(model, field)
27
56
  [resolved[:value], resolved[:prefilled]]
@@ -30,6 +59,7 @@ module ChobbleForms
30
59
  sig { params(form: T.untyped, comment_field: Symbol, base_field_label: String).returns(T::Hash[Symbol, T.untyped]) }
31
60
  def comment_field_options(form, comment_field, base_field_label)
32
61
  raise ArgumentError, "form_object required" unless form
62
+
33
63
  model = form.object
34
64
 
35
65
  comment_value, comment_prefilled =
@@ -81,21 +111,16 @@ module ChobbleForms
81
111
  rows
82
112
  step
83
113
  type
84
- ], T::Array[Symbol])
114
+ ].freeze, T::Array[Symbol])
85
115
 
86
- sig { params(local_assigns: T::Hash[Symbol, T.untyped]).void }
116
+ sig { params(local_assigns: T::Hash[Symbol, LocalAssignValue]).void }
87
117
  def validate_local_assigns(local_assigns)
88
- if local_assigns[:field]&.respond_to?(:to_s) &&
89
- local_assigns[:field].to_s.match?(/^[A-Z]/)
90
- raise ArgumentError, "Field names must be snake_case symbols, not class names. Use :field, not Field."
91
- end
92
-
93
118
  locally_assigned_keys = local_assigns.keys
94
119
  disallowed_keys = locally_assigned_keys - ALLOWED_LOCAL_ASSIGNS
95
120
 
96
- if disallowed_keys.any?
97
- raise ArgumentError, "local_assigns contains #{disallowed_keys.inspect}"
98
- end
121
+ return unless disallowed_keys.any?
122
+
123
+ raise ArgumentError, "local_assigns contains #{disallowed_keys.inspect}"
99
124
  end
100
125
 
101
126
  sig { void }
@@ -109,7 +134,9 @@ module ChobbleForms
109
134
  sig { params(field: Symbol).returns(T::Hash[Symbol, T.nilable(String)]) }
110
135
  def build_field_translations(field)
111
136
  i18n_base = T.unsafe(instance_variable_get(:@_current_i18n_base))
112
- fields_key = "#{i18n_base}.fields.#{field}"
137
+
138
+ field_without_suffix = FieldUtils.strip_field_suffix(field)
139
+ fields_key = "#{i18n_base}.fields.#{field_without_suffix}"
113
140
  field_label = t(fields_key, raise: true)
114
141
 
115
142
  base_parts = i18n_base.split(".")
@@ -124,33 +151,33 @@ module ChobbleForms
124
151
  }
125
152
  end
126
153
 
127
- sig { params(field_translations: T::Hash[Symbol, T.nilable(String)], value: T.untyped, prefilled: T::Boolean).returns(T::Hash[Symbol, T.untyped]) }
154
+ sig { params(field_translations: T::Hash[Symbol, T.nilable(String)], value: T.untyped, prefilled: T::Boolean).returns(FieldSetupResult) }
128
155
  def build_field_setup_result(field_translations, value, prefilled)
129
156
  form_obj = T.unsafe(instance_variable_get(:@_current_form))
130
157
  i18n_base = T.unsafe(instance_variable_get(:@_current_i18n_base))
131
158
 
132
- {
133
- form_object: form_obj,
134
- i18n_base: i18n_base,
135
- value:,
136
- prefilled:
137
- }.merge(field_translations)
159
+ T.cast(
160
+ {
161
+ form_object: form_obj,
162
+ i18n_base: i18n_base,
163
+ value:,
164
+ prefilled:
165
+ }.merge(field_translations),
166
+ FieldSetupResult
167
+ )
138
168
  end
139
169
 
140
- sig { params(model: T.untyped, field: Symbol).returns(T::Hash[Symbol, T.untyped]) }
170
+ sig { params(model: T.untyped, field: Symbol).returns({value: T.untyped, prefilled: T::Boolean}) }
141
171
  def resolve_field_value(model, field)
142
172
  field_str = field.to_s
143
173
 
144
- if field_str.include?("password")
145
- return {value: nil, prefilled: false}
146
- end
174
+ return {value: nil, prefilled: false} if field_str.include?("password")
147
175
 
148
176
  current_value = model.send(field) if model.respond_to?(field)
149
177
 
150
- if defined?(InspectionsController::NOT_COPIED_FIELDS) &&
151
- InspectionsController::NOT_COPIED_FIELDS.include?(field_str)
152
- return {value: current_value, prefilled: false}
153
- end
178
+ # Check if this field should not be prefilled based on excluded fields list
179
+ excluded_fields = T.unsafe(instance_variable_get(:@_excluded_prefill_fields))
180
+ return {value: current_value, prefilled: false} if excluded_fields&.include?(field)
154
181
 
155
182
  prev_inspection = T.unsafe(instance_variable_get(:@previous_inspection))
156
183
  previous_value = extract_previous_value(prev_inspection, model, field)
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module ChobbleForms
5
- VERSION = "0.6.0"
5
+ VERSION = "0.7.0"
6
6
  end
@@ -8,6 +8,7 @@
8
8
  # url: Form submission URL (defaults to model's update path)
9
9
  # method: HTTP method (defaults to :patch for models, :post for scoped forms)
10
10
  # local: Use standard form submission instead of Turbo (defaults to false)
11
+ # excluded_prefill_fields: Array of field symbols that should not be prefilled
11
12
 
12
13
  if model
13
14
  url ||= url_for(model)
@@ -52,6 +53,11 @@ end %>
52
53
  <% @_current_form = form %>
53
54
  <% @_current_i18n_base = i18n_base %>
54
55
 
56
+ <% # Set excluded prefill fields if provided %>
57
+ <% if local_assigns[:excluded_prefill_fields] %>
58
+ <% @_excluded_prefill_fields = excluded_prefill_fields %>
59
+ <% end %>
60
+
55
61
  <%= yield form %>
56
62
 
57
63
  <% if model && model.respond_to?(:errors) && model.errors.any? %>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chobble-forms
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chobble.com
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-08-13 00:00:00.000000000 Z
11
+ date: 2025-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails