formstar 0.1.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
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 38aeef2c7afb9fd595c206197dccbee112de434a90eb9e248ea00ad904aed3c7
|
4
|
+
data.tar.gz: 4c32f1b301bc866674cbf5e72a7fe2b22846e5ab40e71c0d39e63e048b55e74d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bf3e731b37d9f73a377d7c62a85058526b43d3f9f0769833e9d9fd7ad043aeb95f2098a088c2c227f6ff8e8b84e52847ce4f4c83aeb43942736962ce68d3df3f
|
7
|
+
data.tar.gz: 3e0e00422dcdbbfe41b9aa64117c728abcac3c23e7c049d850e1790f380af6ee3f9bb6d9093b2f62c70237dfbe416527299e3c4d9352ebb36582aa94690958ce
|
@@ -0,0 +1,243 @@
|
|
1
|
+
require "after_commit_everywhere"
|
2
|
+
require "active_model"
|
3
|
+
require "active_support"
|
4
|
+
|
5
|
+
module Formstar
|
6
|
+
class Base
|
7
|
+
include ActiveModel::Model
|
8
|
+
include ActiveModel::Attributes
|
9
|
+
include ActiveModel::Validations::Callbacks
|
10
|
+
include AfterCommitEverywhere
|
11
|
+
|
12
|
+
class NoModelError < StandardError; end
|
13
|
+
|
14
|
+
define_model_callbacks :initialize, only: [:after]
|
15
|
+
define_model_callbacks :save, only: [:after]
|
16
|
+
define_model_callbacks :commit, only: [:after]
|
17
|
+
|
18
|
+
attr_reader :form_succeeded
|
19
|
+
attr_reader :form_submitted
|
20
|
+
|
21
|
+
validate :validate_form_model, -> { form_model_defined? && !form_model.nil? }
|
22
|
+
|
23
|
+
def initialize(...)
|
24
|
+
raise NotImplementedError.new("`#{self.class.name}` is abstract and cannot be instantiated directly.") if ["Formstar::Base", "ApplicationForm"].include?(self.class.name)
|
25
|
+
|
26
|
+
@form_succeeded = nil
|
27
|
+
@form_submitted = false
|
28
|
+
|
29
|
+
run_callbacks(:initialize) do
|
30
|
+
super(...)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def submit
|
35
|
+
raise NotImplementedError
|
36
|
+
end
|
37
|
+
|
38
|
+
def succeeded?
|
39
|
+
@form_succeeded
|
40
|
+
end
|
41
|
+
|
42
|
+
def submitted?
|
43
|
+
@form_submitted
|
44
|
+
end
|
45
|
+
|
46
|
+
def form_attributes
|
47
|
+
return @form_attributes unless @form_attributes.nil?
|
48
|
+
|
49
|
+
@form_attributes = {}
|
50
|
+
self.class.form_attribute_names.each do |attr_name|
|
51
|
+
@form_attributes[attr_name] = send(attr_name)
|
52
|
+
end
|
53
|
+
|
54
|
+
@form_attributes
|
55
|
+
end
|
56
|
+
|
57
|
+
def save(**opts)
|
58
|
+
save!(**opts)
|
59
|
+
rescue
|
60
|
+
false
|
61
|
+
end
|
62
|
+
|
63
|
+
def save!(**opts)
|
64
|
+
@form_submitted = true
|
65
|
+
validate!(context: opts[:context]) unless opts[:validate] == false
|
66
|
+
|
67
|
+
perform_submit = -> do
|
68
|
+
run_callbacks(:save) do
|
69
|
+
submit
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
if self.class.config[:submit_within_transaction_enabled]
|
74
|
+
ActiveRecord::Base.transaction do
|
75
|
+
perform_submit.call
|
76
|
+
end
|
77
|
+
else
|
78
|
+
perform_submit.call
|
79
|
+
end
|
80
|
+
|
81
|
+
after_commit { run_callbacks(:commit) }
|
82
|
+
|
83
|
+
@form_succeeded = true
|
84
|
+
rescue => e
|
85
|
+
@form_succeeded = false
|
86
|
+
raise e
|
87
|
+
end
|
88
|
+
|
89
|
+
def model
|
90
|
+
raise NoModelError.new unless form_model_defined?
|
91
|
+
self.form_model
|
92
|
+
end
|
93
|
+
|
94
|
+
def model=(new_model)
|
95
|
+
raise NoModelError.new unless form_model_defined?
|
96
|
+
self.form_model = new_model
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def form_model
|
102
|
+
return nil unless form_model_defined?
|
103
|
+
send(form_model_name)
|
104
|
+
end
|
105
|
+
|
106
|
+
def form_model=(new_model)
|
107
|
+
return nil unless form_model_defined?
|
108
|
+
send("#{form_model_name}=".to_sym, new_model)
|
109
|
+
end
|
110
|
+
|
111
|
+
def validate_form_model
|
112
|
+
promote_form_model_errors(form_model) if form_model&.invalid?
|
113
|
+
end
|
114
|
+
|
115
|
+
def promote_form_model_errors(form_model)
|
116
|
+
form_model.errors.each do |e|
|
117
|
+
errors.add(e.attribute, e.type, message: e.message)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def form_model_name
|
122
|
+
@form_model_name ||= self.class.config[:model].fetch(:name, nil)&.to_sym
|
123
|
+
end
|
124
|
+
|
125
|
+
def form_model_defined?
|
126
|
+
@model_defined ||= !self.class.config[:model].nil? #&&
|
127
|
+
end
|
128
|
+
|
129
|
+
def config
|
130
|
+
self.class.config
|
131
|
+
end
|
132
|
+
|
133
|
+
def respond_to_missing?(name, include_private = false)
|
134
|
+
if form_model_defined? && name.to_sym != self.class.config[:model][:name]
|
135
|
+
form_model.respond_to?(name, include_private)
|
136
|
+
else
|
137
|
+
super
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def method_missing(method, *args, &block)
|
142
|
+
if form_model_defined? && method.to_sym != self.class.config[:model][:name]
|
143
|
+
form_model.send(method, *args, &block)
|
144
|
+
else
|
145
|
+
super
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class << self
|
150
|
+
|
151
|
+
attr_reader :config
|
152
|
+
attr_reader :form_attribute_names
|
153
|
+
|
154
|
+
def inherited(subclass)
|
155
|
+
subclass.instance_variable_set(:@config, self.config.dup)
|
156
|
+
end
|
157
|
+
|
158
|
+
def config
|
159
|
+
@config ||= {
|
160
|
+
model_translation_fallback_enabled: true,
|
161
|
+
model_translation_fallback_class_name: nil,
|
162
|
+
submit_within_transaction_enabled: true,
|
163
|
+
model: nil
|
164
|
+
}
|
165
|
+
end
|
166
|
+
|
167
|
+
def model_translation_fallback(enabled, class_name: nil)
|
168
|
+
config[:model_translation_fallback_enabled] = enabled
|
169
|
+
config[:model_translation_fallback_class_name] = class_name&.safe_constantize
|
170
|
+
end
|
171
|
+
|
172
|
+
def submit_within_transaction(enabled)
|
173
|
+
config[:submit_within_transaction_enabled] = enabled
|
174
|
+
end
|
175
|
+
|
176
|
+
def attr_form(name, ...)
|
177
|
+
form_attribute_names.add(name.to_sym)
|
178
|
+
attribute(name, ...)
|
179
|
+
end
|
180
|
+
|
181
|
+
def with_model(name, class_name: name)
|
182
|
+
name = name.to_sym
|
183
|
+
class_name = class_name.to_s.classify
|
184
|
+
klass = Object.const_get(class_name)
|
185
|
+
|
186
|
+
# Don't accept models that are modules.
|
187
|
+
raise ArgumentError.new("Expected an ActiveRecord model, got `#{class_name}`") unless klass < ActiveRecord::Base
|
188
|
+
|
189
|
+
config[:model] = { name: name, klass: klass }
|
190
|
+
end
|
191
|
+
|
192
|
+
def model_name
|
193
|
+
return @model_name unless @model_name.nil?
|
194
|
+
|
195
|
+
if config[:model]
|
196
|
+
@model_name = ActiveModel::Name.new(config[:model][:klass])
|
197
|
+
@model_name.i18n_key = self.name.underscore
|
198
|
+
else
|
199
|
+
@model_name = ActiveModel::Name.new(self)
|
200
|
+
end
|
201
|
+
|
202
|
+
@model_name
|
203
|
+
end
|
204
|
+
|
205
|
+
def form_attribute_names
|
206
|
+
@form_attribute_names ||= Set.new
|
207
|
+
end
|
208
|
+
|
209
|
+
def i18n_scope
|
210
|
+
:form
|
211
|
+
end
|
212
|
+
|
213
|
+
def human_attribute_name(attribute, options = {})
|
214
|
+
# Base errors for a form will never fall back to the underlying model.
|
215
|
+
# So we can safely always delegate the translation lookup back to active model
|
216
|
+
# which will build up the correct lookup paths.
|
217
|
+
return attribute if attribute.to_sym == :base
|
218
|
+
|
219
|
+
I18n.t!("#{i18n_scope}.attributes.#{model_name.i18n_key}.#{attribute}")
|
220
|
+
rescue I18n::MissingTranslationData => e
|
221
|
+
fallback_value = nil
|
222
|
+
|
223
|
+
if config[:model_translation_fallback_enabled]
|
224
|
+
if config[:model]
|
225
|
+
form_model_klass = config[:model][:klass]
|
226
|
+
else
|
227
|
+
form_model_klass = nil
|
228
|
+
end
|
229
|
+
|
230
|
+
fallback_klass = config[:model_translation_fallback_class_name] || form_model_klass
|
231
|
+
fallback_value = fallback_klass.human_attribute_name(attribute, options) if fallback_klass
|
232
|
+
end
|
233
|
+
|
234
|
+
if fallback_value
|
235
|
+
fallback_value
|
236
|
+
else
|
237
|
+
raise e
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
end
|
data/lib/formstar.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "rails/generators"
|
2
|
+
|
3
|
+
module Formstar
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
7
|
+
|
8
|
+
def copy_application_enum
|
9
|
+
template "app/forms/application_form.rb", "app/forms/application_form.rb"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: formstar
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bevan Holborn
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 2025-01-17 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: rake
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - ">="
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '0'
|
19
|
+
type: :development
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '0'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rspec
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '3.0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: after_commit_everywhere
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.4'
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.4'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: activemodel
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '5.0'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '5.0'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: activesupport
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '5.0'
|
75
|
+
type: :runtime
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '5.0'
|
82
|
+
description: ActiveModel backed Form objects for Ruby on Rails applications
|
83
|
+
executables: []
|
84
|
+
extensions: []
|
85
|
+
extra_rdoc_files: []
|
86
|
+
files:
|
87
|
+
- lib/formstar.rb
|
88
|
+
- lib/formstar/base.rb
|
89
|
+
- lib/formstar/version.rb
|
90
|
+
- lib/generators/formstar/install/install_generator.rb
|
91
|
+
- lib/generators/formstar/install/templates/app/forms/application_form.rb
|
92
|
+
homepage: https://rubygems.org/gems/formstar
|
93
|
+
licenses:
|
94
|
+
- MIT
|
95
|
+
metadata:
|
96
|
+
source_code_uri: https://gitlab.com/BevanHolborn/formstar
|
97
|
+
rdoc_options: []
|
98
|
+
require_paths:
|
99
|
+
- lib
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 2.7.0
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
requirements: []
|
111
|
+
rubygems_version: 3.6.2
|
112
|
+
specification_version: 4
|
113
|
+
summary: ActiveModel backed Form objects for Ruby on Rails applications
|
114
|
+
test_files: []
|