tramway-core 1.17.1 → 1.17.2.3
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/README.md +83 -2
- data/app/assets/javascripts/tramway/core/application.js +1 -1
- data/app/controllers/tramway/core/application_controller.rb +8 -12
- data/app/decorators/tramway/core/application_decorator.rb +16 -28
- data/app/decorators/tramway/core/associations/class_helper.rb +13 -13
- data/app/decorators/tramway/core/associations/object_helper.rb +31 -3
- data/app/decorators/tramway/core/attributes/view_helper.rb +26 -0
- data/app/decorators/tramway/core/concerns/attributes_decorator_helper.rb +47 -26
- data/app/decorators/tramway/core/delegating/class_helper.rb +9 -0
- data/app/forms/tramway/core/application_form.rb +83 -171
- data/app/forms/tramway/core/application_forms/association_object_helpers.rb +31 -0
- data/app/forms/tramway/core/application_forms/constant_class_actions.rb +7 -0
- data/app/forms/tramway/core/application_forms/constant_object_actions.rb +13 -0
- data/app/forms/tramway/core/application_forms/properties_object_helper.rb +23 -0
- data/app/forms/tramway/core/extendable_form.rb +3 -70
- data/app/forms/tramway/core/extendable_forms_helpers/class_builder.rb +34 -0
- data/app/forms/tramway/core/extendable_forms_helpers/ignored_properties_helper.rb +11 -0
- data/app/forms/tramway/core/extendable_forms_helpers/more_properties_helper.rb +27 -0
- data/app/forms/tramway/core/extendable_forms_helpers/properties_helper.rb +16 -0
- data/app/forms/tramway/core/extendable_forms_helpers/submit/class_helpers.rb +18 -0
- data/app/forms/tramway/core/extendable_forms_helpers/submit/object_helpers.rb +7 -0
- data/app/forms/tramway/core/extendable_forms_helpers/validators.rb +40 -0
- data/app/helpers/tramway/core/copy_to_clipboard_helper.rb +6 -10
- data/app/helpers/tramway/core/title_helper.rb +17 -22
- data/app/models/tramway/core/application_record.rb +38 -40
- data/app/uploaders/image_defaults.rb +2 -1
- data/app/uploaders/photo_uploader.rb +8 -8
- data/config/initializers/plurals.rb +2 -2
- data/lib/tramway/collection.rb +4 -6
- data/lib/tramway/collections.rb +4 -0
- data/lib/tramway/collections/helper.rb +15 -14
- data/lib/tramway/core.rb +22 -22
- data/lib/tramway/core/engine.rb +4 -8
- data/lib/tramway/core/generators.rb +4 -0
- data/lib/tramway/core/generators/install_generator.rb +17 -17
- data/lib/tramway/core/version.rb +1 -1
- data/lib/tramway/error.rb +12 -1
- data/lib/yaml/errors.yml +35 -0
- metadata +20 -3
@@ -1,204 +1,116 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
raise Tramway::Error.new(plugin: :core, method: :initialize, message: 'Polymorphic association class is nil. Maybe, you should write `assocation #{association_name}` after `properties #{association_name}_id, #{association_name}_type`')
|
18
|
-
else
|
19
|
-
super association_class.constantize.find value
|
20
|
-
end
|
21
|
-
end
|
22
|
-
else
|
23
|
-
self.class.send(:define_method, "#{association}=") do |value|
|
24
|
-
super class_name.find value
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
delegating object
|
3
|
+
class Tramway::Core::ApplicationForm < ::Reform::Form
|
4
|
+
include Tramway::Core::ApplicationForms::AssociationObjectHelpers
|
5
|
+
include Tramway::Core::ApplicationForms::ConstantObjectActions
|
6
|
+
include Tramway::Core::ApplicationForms::PropertiesObjectHelper
|
7
|
+
|
8
|
+
def initialize(object = nil)
|
9
|
+
object ||= self.class.model_class.new
|
10
|
+
super(object).tap do
|
11
|
+
@@model_class = object.class
|
12
|
+
@@enumerized_attributes = object.class.try :enumerized_attributes
|
13
|
+
@@associations ||= []
|
14
|
+
|
15
|
+
self.class.full_class_name_associations&.each do |association, class_name|
|
16
|
+
define_association_method association, class_name
|
30
17
|
end
|
31
|
-
end
|
32
18
|
|
33
|
-
|
34
|
-
if params
|
35
|
-
if validate params
|
36
|
-
begin
|
37
|
-
save.tap do
|
38
|
-
# self.class.remove_validations_from_model!
|
39
|
-
end
|
40
|
-
rescue StandardError => e
|
41
|
-
# self.class.remove_validations_from_model!
|
42
|
-
error = Tramway::Error.new(plugin: :core, method: :submit, message: "Looks like you have method `#{e.name.to_s.gsub('=', '')}` in #{@@model_class}. You should rename it or rename property in #{self.class}")
|
43
|
-
raise error.message
|
44
|
-
end
|
45
|
-
else
|
46
|
-
association_error = false
|
47
|
-
@@associations.each do |association|
|
48
|
-
if errors.details[association] == [{ error: :blank }]
|
49
|
-
model.send("#{association}=", send(association))
|
50
|
-
association_error = true
|
51
|
-
end
|
52
|
-
end
|
53
|
-
(association_error && save).tap do
|
54
|
-
# self.class.remove_validations_from_model!
|
55
|
-
end
|
56
|
-
end
|
57
|
-
else
|
58
|
-
# self.class.remove_validations_from_model!
|
59
|
-
error = Tramway::Error.new(plugin: :core, method: :submit, message: 'ApplicationForm::Params should not be nil')
|
60
|
-
raise error.message
|
61
|
-
end
|
19
|
+
delegating object
|
62
20
|
end
|
21
|
+
end
|
63
22
|
|
64
|
-
|
65
|
-
|
23
|
+
def submit(params)
|
24
|
+
if params
|
25
|
+
validate(params) ? save : collecting_associations_errors
|
26
|
+
else
|
27
|
+
Tramway::Error.raise_error(:tramway, :core, :application_form, :submit, :params_should_not_be_nil)
|
66
28
|
end
|
29
|
+
end
|
67
30
|
|
68
|
-
|
69
|
-
|
70
|
-
|
31
|
+
def model_name
|
32
|
+
@@model_class.model_name
|
33
|
+
end
|
71
34
|
|
72
|
-
|
73
|
-
|
74
|
-
end
|
35
|
+
class << self
|
36
|
+
include Tramway::Core::ApplicationForms::ConstantClassActions
|
75
37
|
|
76
|
-
|
77
|
-
@form_properties_additional = args
|
78
|
-
end
|
38
|
+
delegate :defined_enums, to: :model_class
|
79
39
|
|
80
|
-
def
|
81
|
-
|
40
|
+
def association(property)
|
41
|
+
properties property
|
42
|
+
@@associations = ((defined?(@@associations) && @@associations) || []) + [property]
|
43
|
+
end
|
82
44
|
|
83
|
-
|
84
|
-
|
85
|
-
@form_properties = YAML.load_file(yaml_config_file_path).deep_symbolize_keys
|
86
|
-
@form_properties.deep_merge! @form_properties_additional if @form_properties_additional
|
87
|
-
@form_properties
|
88
|
-
else
|
89
|
-
[]
|
90
|
-
end
|
45
|
+
def associations(*properties)
|
46
|
+
properties.each { |property| association property }
|
91
47
|
end
|
92
48
|
|
93
|
-
def
|
49
|
+
def full_class_name_associations
|
50
|
+
@@associations&.reduce({}) do |hash, association|
|
51
|
+
options = @@model_class.reflect_on_all_associations(:belongs_to).select do |a|
|
52
|
+
a.name == association.to_sym
|
53
|
+
end.first&.options
|
94
54
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
object.send method
|
55
|
+
if options&.dig(:polymorphic)
|
56
|
+
hash.merge! association => @@model_class.send("#{association}_type").values
|
57
|
+
elsif options
|
58
|
+
hash.merge!(association => (options[:class_name] || association.to_s.camelize).constantize)
|
100
59
|
end
|
60
|
+
hash
|
101
61
|
end
|
102
62
|
end
|
103
63
|
|
104
|
-
def
|
105
|
-
|
106
|
-
hash.merge! property.first => model.values[property.first.to_s]
|
107
|
-
end
|
64
|
+
def full_class_name_association(association_name)
|
65
|
+
full_class_name_associations[association_name]
|
108
66
|
end
|
109
67
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
def association(property)
|
114
|
-
properties property
|
115
|
-
@@associations ||= []
|
116
|
-
@@associations << property
|
117
|
-
end
|
118
|
-
|
119
|
-
def associations(*properties)
|
120
|
-
properties.each do |property|
|
121
|
-
association property
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def full_class_name_associations
|
126
|
-
@@associations&.reduce({}) do |hash, association|
|
127
|
-
options = @@model_class.reflect_on_all_associations(:belongs_to).select do |a|
|
128
|
-
a.name == association.to_sym
|
129
|
-
end.first&.options
|
130
|
-
|
131
|
-
if options
|
132
|
-
if options[:polymorphic]
|
133
|
-
hash.merge! association => @@model_class.send("#{association}_type").values
|
134
|
-
else
|
135
|
-
class_name = options[:class_name] || association.to_s.camelize
|
136
|
-
hash.merge!(association => class_name.constantize)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
hash
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
def full_class_name_association(association_name)
|
144
|
-
full_class_name_associations[association_name]
|
145
|
-
end
|
146
|
-
|
147
|
-
def enumerized_attributes
|
148
|
-
@@enumerized_attributes
|
149
|
-
end
|
68
|
+
def reflect_on_association(*args)
|
69
|
+
@@model_class.reflect_on_association(*args)
|
70
|
+
end
|
150
71
|
|
151
|
-
|
152
|
-
|
153
|
-
|
72
|
+
def enumerized_attributes
|
73
|
+
@@enumerized_attributes
|
74
|
+
end
|
154
75
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
end
|
76
|
+
def model_class
|
77
|
+
if defined?(@@model_class) && @@model_class
|
78
|
+
@@model_class
|
79
|
+
else
|
80
|
+
model_class_name ||= name.to_s.sub(/Form$/, '')
|
81
|
+
begin
|
82
|
+
@@model_class = model_class_name.constantize
|
83
|
+
rescue StandardError
|
84
|
+
Tramway::Error.raise_error :tramway, :core, :application_form, :model_class, :there_is_not_model_class,
|
85
|
+
name: name, model_class_name: model_class_name
|
166
86
|
end
|
167
87
|
end
|
88
|
+
end
|
168
89
|
|
169
|
-
|
170
|
-
|
171
|
-
|
90
|
+
def model_class=(name)
|
91
|
+
@@model_class = name
|
92
|
+
end
|
172
93
|
|
173
|
-
|
174
|
-
|
94
|
+
def validates(attribute, **options)
|
95
|
+
if !defined?(@@model_class) || @@model_class.nil?
|
96
|
+
Tramway::Error.raise_error(:tramway, :core, :application_form, :validates, :you_need_to_set_model_class)
|
175
97
|
end
|
98
|
+
@@model_class.validates attribute, **options
|
99
|
+
end
|
100
|
+
end
|
176
101
|
|
177
|
-
|
178
|
-
if !defined?(@@model_class) || @@model_class.nil?
|
179
|
-
error = Tramway::Error.new(plugin: :core, method: :validates, message: 'You need to set `model_class` name while using validations. Just write `self.model_class = YOUR_MODEL_NAME` in the class area.')
|
180
|
-
raise error.message
|
181
|
-
end
|
182
|
-
@@model_class.validates attribute, **options
|
183
|
-
# @@validations ||= {}
|
184
|
-
# @@validations.deep_merge! attribute => options
|
185
|
-
end
|
102
|
+
private
|
186
103
|
|
187
|
-
|
188
|
-
|
189
|
-
#
|
190
|
-
# return unless defined? @@validations
|
191
|
-
# @@validations&.each do |validation|
|
192
|
-
# @@model_class.class_eval do
|
193
|
-
# _validators.except validation[0]
|
194
|
-
#
|
195
|
-
# binding.pry
|
196
|
-
# _validate_callbacks.each do |callback|
|
197
|
-
# callback.raw_filter.attributes.delete validation[0]
|
198
|
-
# end
|
199
|
-
# end
|
200
|
-
# end
|
201
|
-
# end
|
104
|
+
def collecting_associations_errors
|
105
|
+
@@associations.each do |association|
|
106
|
+
model.send("#{association}=", send(association)) if errors.details[association] == [{ error: :blank }]
|
202
107
|
end
|
203
108
|
end
|
109
|
+
|
110
|
+
def save
|
111
|
+
super
|
112
|
+
rescue StandardError => e
|
113
|
+
Tramway::Error.raise_error :tramway, :core, :application_form, :submit, :looks_like_you_have_method,
|
114
|
+
method_name: e.name.to_s.gsub('=', ''), model_class: @@model_class, class_name: self.class
|
115
|
+
end
|
204
116
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tramway::Core::ApplicationForms::AssociationObjectHelpers
|
4
|
+
def associations
|
5
|
+
@@associations
|
6
|
+
end
|
7
|
+
|
8
|
+
def define_association_method(association, class_name)
|
9
|
+
if class_name.is_a? Array
|
10
|
+
define_polymorphic_association association, class_name
|
11
|
+
else
|
12
|
+
self.class.send(:define_method, "#{association}=") do |value|
|
13
|
+
super class_name.find value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def define_polymorphic_association(association, _class_name)
|
19
|
+
self.class.send(:define_method, "#{association}=") do |value|
|
20
|
+
association_class = value.split('_')[0..-2].join('_').camelize
|
21
|
+
association_class = association_class.constantize if association_class.is_a? String
|
22
|
+
if association_class.nil?
|
23
|
+
Tramway::Error.raise_error :tramway, :core, :application_form, :initialize, :polymorphic_class_is_nil,
|
24
|
+
association_name: association
|
25
|
+
else
|
26
|
+
super association_class.find value.split('_')[-1]
|
27
|
+
send "#{association}_type=", association_class.to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tramway::Core::ApplicationForms::ConstantObjectActions
|
4
|
+
def delegating(object)
|
5
|
+
%i[to_key errors].each { |method| self.class.send(:define_method, method) { object.send method } }
|
6
|
+
end
|
7
|
+
|
8
|
+
def build_errors; end
|
9
|
+
|
10
|
+
def attributes
|
11
|
+
properties.reduce({}) { |hash, property| hash.merge! property.first => model.values[property.first.to_s] }
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tramway::Core::ApplicationForms::PropertiesObjectHelper
|
4
|
+
def form_properties(**args)
|
5
|
+
@form_properties = args
|
6
|
+
end
|
7
|
+
|
8
|
+
def form_properties_additional(**args)
|
9
|
+
@form_properties_additional = args
|
10
|
+
end
|
11
|
+
|
12
|
+
def properties
|
13
|
+
return @form_properties if @form_properties
|
14
|
+
|
15
|
+
yaml_config_file_path = Rails.root.join('app', 'forms', "#{self.class.name.underscore}.yml")
|
16
|
+
|
17
|
+
return [] unless File.exist? yaml_config_file_path
|
18
|
+
|
19
|
+
@form_properties = YAML.load_file(yaml_config_file_path).deep_symbolize_keys
|
20
|
+
@form_properties.deep_merge! @form_properties_additional if @form_properties_additional
|
21
|
+
@form_properties
|
22
|
+
end
|
23
|
+
end
|
@@ -2,80 +2,13 @@
|
|
2
2
|
|
3
3
|
class Tramway::Core::ExtendableForm
|
4
4
|
class << self
|
5
|
+
include Tramway::Core::ExtendableFormsHelpers::ClassBuilder
|
6
|
+
|
5
7
|
def new(name, simple_properties: {}, **more_properties)
|
6
8
|
if Object.const_defined? name
|
7
9
|
name.constantize
|
8
10
|
else
|
9
|
-
|
10
|
-
properties(*simple_properties.keys) if simple_properties.keys.any?
|
11
|
-
|
12
|
-
define_method 'submit' do |params|
|
13
|
-
model.values ||= {}
|
14
|
-
extended_params = params.except(*simple_properties.keys).except(*jsonb_ignored_properties(more_properties))
|
15
|
-
params.each do |key, value|
|
16
|
-
method_name = "#{key}="
|
17
|
-
send method_name, value if respond_to?(method_name)
|
18
|
-
end
|
19
|
-
model.values = extended_params.permit!.to_h.reduce(model.values) do |hash, pair|
|
20
|
-
hash.merge! pair[0] => pair[1]
|
21
|
-
end
|
22
|
-
super params
|
23
|
-
end
|
24
|
-
|
25
|
-
define_method 'properties' do
|
26
|
-
hash = simple_properties.each_with_object({}) do |property, h|
|
27
|
-
h.merge! property[0] => property[1] unless model.class.state_machines.keys.include?(property[0])
|
28
|
-
end
|
29
|
-
more_properties.reduce(hash) do |h, property|
|
30
|
-
h.merge! property[0] => {
|
31
|
-
extended_form_property: property[1][:object]
|
32
|
-
}
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
more_properties.each do |property|
|
37
|
-
define_method property[0] do
|
38
|
-
model.values[property[0]] if model.values
|
39
|
-
end
|
40
|
-
|
41
|
-
case property[1][:object].field_type
|
42
|
-
when 'file'
|
43
|
-
field = property[1][:object]
|
44
|
-
define_method "#{property[0]}=" do |value|
|
45
|
-
file_instance = property[1][:association_model].find_or_create_by "#{model.class.name.underscore}_id" => model.id, "#{field.class.name.underscore}_id" => field.id
|
46
|
-
file_instance.file = value
|
47
|
-
file_instance.save!
|
48
|
-
end
|
49
|
-
else
|
50
|
-
next unless property[1][:validates].present?
|
51
|
-
|
52
|
-
define_method "#{property[0]}=" do |value|
|
53
|
-
property[1][:validates].each do |pair|
|
54
|
-
case pair[0].to_s
|
55
|
-
when 'presence'
|
56
|
-
validator_object = "#{pair[0].to_s.camelize}Validator".constantize.new(attributes: :not_blank)
|
57
|
-
if pair[1] == 'true' && !validator_object.send(:valid?, value)
|
58
|
-
model.errors.add property[0],
|
59
|
-
I18n.t("activerecord.errors.models.#{model.class.name.underscore}.attributes.default.#{pair[0]}", value: value)
|
60
|
-
end
|
61
|
-
when 'inclusion'
|
62
|
-
in_array = pair[1][:in]
|
63
|
-
unless value.in? in_array
|
64
|
-
model.errors.add property[0],
|
65
|
-
I18n.t("activerecord.errors.models.#{model.class.name.underscore}.attributes.default.#{pair[0]}", value: value)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
define_method :jsonb_ignored_properties do |properties|
|
74
|
-
properties.map do |property|
|
75
|
-
property[0].to_s if property[1][:object].field_type == 'file'
|
76
|
-
end.compact
|
77
|
-
end
|
78
|
-
end)
|
11
|
+
build_form_class name, simple_properties, more_properties
|
79
12
|
end
|
80
13
|
end
|
81
14
|
end
|