tramway-core 1.17.2.1 → 1.17.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -2
  3. data/app/decorators/tramway/core/application_decorator.rb +0 -1
  4. data/app/decorators/tramway/core/associations/class_helper.rb +1 -0
  5. data/app/decorators/tramway/core/associations/object_helper.rb +1 -1
  6. data/app/decorators/tramway/core/delegating/class_helper.rb +2 -0
  7. data/app/forms/tramway/core/application_form.rb +83 -146
  8. data/app/forms/tramway/core/application_forms/association_object_helpers.rb +31 -0
  9. data/app/forms/tramway/core/application_forms/constant_class_actions.rb +7 -0
  10. data/app/forms/tramway/core/application_forms/constant_object_actions.rb +13 -0
  11. data/app/forms/tramway/core/application_forms/properties_object_helper.rb +23 -0
  12. data/app/forms/tramway/core/extendable_form.rb +3 -70
  13. data/app/forms/tramway/core/extendable_forms_helpers/class_builder.rb +34 -0
  14. data/app/forms/tramway/core/extendable_forms_helpers/ignored_properties_helper.rb +11 -0
  15. data/app/forms/tramway/core/extendable_forms_helpers/more_properties_helper.rb +27 -0
  16. data/app/forms/tramway/core/extendable_forms_helpers/properties_helper.rb +16 -0
  17. data/app/forms/tramway/core/extendable_forms_helpers/submit/class_helpers.rb +18 -0
  18. data/app/forms/tramway/core/extendable_forms_helpers/submit/object_helpers.rb +7 -0
  19. data/app/forms/tramway/core/extendable_forms_helpers/validators.rb +40 -0
  20. data/app/helpers/tramway/core/copy_to_clipboard_helper.rb +6 -10
  21. data/app/helpers/tramway/core/title_helper.rb +17 -22
  22. data/app/models/tramway/core/application_record.rb +38 -40
  23. data/app/uploaders/image_defaults.rb +2 -1
  24. data/app/uploaders/photo_uploader.rb +8 -8
  25. data/config/initializers/plurals.rb +2 -2
  26. data/lib/tramway/collection.rb +4 -6
  27. data/lib/tramway/collections.rb +4 -0
  28. data/lib/tramway/collections/helper.rb +15 -14
  29. data/lib/tramway/core.rb +19 -23
  30. data/lib/tramway/core/engine.rb +4 -8
  31. data/lib/tramway/core/generators.rb +4 -0
  32. data/lib/tramway/core/generators/install_generator.rb +17 -17
  33. data/lib/tramway/core/version.rb +1 -1
  34. data/lib/tramway/error.rb +12 -1
  35. metadata +17 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 63c3cd63ade145dc9d56b1ed79122789322b6956273157b8d81a65ee8b9107af
4
- data.tar.gz: 36e9210fe35bd7e33d218b786354b71a2ad1a316cb33252345a3ae5b49a5b6b3
3
+ metadata.gz: 3c612a0122da3218a86e61b973beff51f378e14352fd424489130039694f82f8
4
+ data.tar.gz: 07d47a9b6e995469f7b500e34b21f705cc24ce1e4aede1e946ace36f5ddebb28
5
5
  SHA512:
6
- metadata.gz: 6f95be747fa6d661b575968a76053a0cee7092460d1ae919aa055f4db7a18b1fa9810a1bd76d5c2af4f667b379a836c95461e7c7060ef9f1aeb16a8f5bfe9515
7
- data.tar.gz: a2e82ebb362b3d275aa4bec8e16c49ad6946dd36af98fb9dc5b09251a0b54178ce8115a5e1fe2cff8b121b99f06ed4d4f4579ee9317cb4cc64f85e19e91a69ca
6
+ metadata.gz: 8b275c112e32864152637a34c283677de289fc2fb5e79123fd15f149656e0d3741c1b7768e06d441004927e4fe5db0f4af2a744a55e6fdc58fe210227e1b7ce7
7
+ data.tar.gz: 350ace536d11005778f241370a3179f5f51f9078d8822ca4e80955aeb0ffb93edbafc64e55d9635d0cba4e4cc4ef8b3fd6f3aa205a7171542b25e6500c82d281
data/README.md CHANGED
@@ -203,8 +203,10 @@ Tramway::Admin.set_singleton_models Organization, project: :organization # now y
203
203
  * models - часто используемые в моделях слова
204
204
  * state_machines - локализация состояний
205
205
 
206
- ## Contributing
207
- Contribution directions go here.
206
+ ## Contributors
207
+
208
+ * [Pavel Kalashnikov](https://github.com/kalashnikovisme)
209
+ * [moshinaan](https://github.com/moshinaan)
208
210
 
209
211
  ## License
210
212
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -65,7 +65,6 @@ class Tramway::Core::ApplicationDecorator
65
65
  end
66
66
  end
67
67
 
68
-
69
68
  def link
70
69
  if object.try :file
71
70
  object.file.url
@@ -25,6 +25,7 @@ module Tramway::Core::Associations::ClassHelper
25
25
  decorate_association association_name
26
26
  end
27
27
  end
28
+
28
29
  def define_main_association_method(association_name, decorator)
29
30
  define_method association_name do
30
31
  association = object.class.reflect_on_association(association_name)
@@ -6,7 +6,7 @@ module Tramway::Core::Associations::ObjectHelper
6
6
  object.send(association.name).class
7
7
  else
8
8
  unless association.options[:class_name]
9
- error = Tramway::Error.new(plugin: :core, method: :decorate_association, message: "Please, specify `#{association_name}` association class_name in #{object.class} model. For example: `has_many :#{association_name}, class_name: '#{association_name.to_s.singularize.camelize}'`")
9
+ error = Tramway::Error.new(plugin: :core, method: :decorate_association, message: "Please, specify `#{association.name}` association class_name in #{object.class} model. For example: `has_many :#{association.name}, class_name: '#{association.name.to_s.singularize.camelize}'`")
10
10
  raise error.message
11
11
  end
12
12
  association.options[:class_name]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Tramway::Core::Delegating::ClassHelper
2
4
  def delegate_attributes(*attributes)
3
5
  attributes.each do |attr|
@@ -1,179 +1,116 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tramway::Core
4
- class ApplicationForm < ::Reform::Form
5
- def initialize(object = nil)
6
- object ||= self.class.model_class.new
7
- super(object).tap do
8
- @@model_class = object.class
9
- @@enumerized_attributes = object.class.try :enumerized_attributes
10
- @@associations ||= []
11
-
12
- self.class.full_class_name_associations.each do |association, class_name|
13
- if class_name.is_a? Array
14
- self.class.send(:define_method, "#{association}=") do |value|
15
- association_class = value.split('_')[0..-2].join('_').camelize
16
- association_class = association_class.constantize if association_class.is_a? String
17
- if association_class.nil?
18
- 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`')
19
- else
20
- super association_class.find value.split('_')[-1]
21
- send "#{association}_type=", association_class.to_s
22
- end
23
- end
24
- else
25
- self.class.send(:define_method, "#{association}=") do |value|
26
- super class_name.find value
27
- end
28
- end
29
- end
30
-
31
- 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
32
17
  end
33
- end
34
18
 
35
- def submit(params)
36
- if params
37
- if validate params
38
- begin
39
- save
40
- rescue StandardError => e
41
- 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}")
42
- raise error.message
43
- end
44
- else
45
- @@associations.each do |association|
46
- if errors.details[association] == [{ error: :blank }]
47
- model.send("#{association}=", send(association))
48
- end
49
- end
50
- end
51
- else
52
- error = Tramway::Error.new(plugin: :core, method: :submit, message: 'ApplicationForm::Params should not be nil')
53
- raise error.message
54
- end
19
+ delegating object
55
20
  end
21
+ end
56
22
 
57
- def model_name
58
- @@model_class.model_name
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)
59
28
  end
29
+ end
60
30
 
61
- def associations
62
- @@associations
63
- end
31
+ def model_name
32
+ @@model_class.model_name
33
+ end
64
34
 
65
- def form_properties(**args)
66
- @form_properties = args
67
- end
35
+ class << self
36
+ include Tramway::Core::ApplicationForms::ConstantClassActions
68
37
 
69
- def form_properties_additional(**args)
70
- @form_properties_additional = args
71
- end
38
+ delegate :defined_enums, to: :model_class
72
39
 
73
- def properties
74
- return @form_properties if @form_properties
40
+ def association(property)
41
+ properties property
42
+ @@associations = ((defined?(@@associations) && @@associations) || []) + [property]
43
+ end
75
44
 
76
- yaml_config_file_path = Rails.root.join('app', 'forms', "#{self.class.name.underscore}.yml")
77
- if File.exist? yaml_config_file_path
78
- @form_properties = YAML.load_file(yaml_config_file_path).deep_symbolize_keys
79
- @form_properties.deep_merge! @form_properties_additional if @form_properties_additional
80
- @form_properties
81
- else
82
- []
83
- end
45
+ def associations(*properties)
46
+ properties.each { |property| association property }
84
47
  end
85
48
 
86
- def build_errors; end
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
87
54
 
88
- def delegating(object)
89
- methods = %i[to_key errors]
90
- methods.each do |method|
91
- self.class.send(:define_method, method) do
92
- object.send method
55
+ if options&.dig(:polymorphic)
56
+ hash.merge! association => @@model_class.send("#{association}_type").values
57
+ elsif options.present?
58
+ hash.merge!(association => (options[:class_name] || association.to_s.camelize).constantize)
93
59
  end
60
+ hash
94
61
  end
95
62
  end
96
63
 
97
- def attributes
98
- properties.reduce({}) do |hash, property|
99
- hash.merge! property.first => model.values[property.first.to_s]
100
- end
64
+ def full_class_name_association(association_name)
65
+ full_class_name_associations[association_name]
101
66
  end
102
67
 
103
- class << self
104
- delegate :defined_enums, to: :model_class
105
-
106
- def association(property)
107
- properties property
108
- @@associations ||= []
109
- @@associations << property
110
- end
68
+ def reflect_on_association(*args)
69
+ @@model_class.reflect_on_association(*args)
70
+ end
111
71
 
112
- def associations(*properties)
113
- properties.each do |property|
114
- association property
115
- end
116
- end
72
+ def enumerized_attributes
73
+ @@enumerized_attributes
74
+ end
117
75
 
118
- def full_class_name_associations
119
- @@associations&.reduce({}) do |hash, association|
120
- options = @@model_class.reflect_on_all_associations(:belongs_to).select do |a|
121
- a.name == association.to_sym
122
- end.first&.options
123
-
124
- if options
125
- if options[:polymorphic]
126
- hash.merge! association => @@model_class.send("#{association}_type").values
127
- else
128
- class_name = options[:class_name] || association.to_s.camelize
129
- hash.merge!(association => class_name.constantize)
130
- end
131
- end
132
- hash
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
133
86
  end
134
87
  end
88
+ end
135
89
 
136
- def full_class_name_association(association_name)
137
- full_class_name_associations[association_name]
138
- end
139
-
140
- def enumerized_attributes
141
- @@enumerized_attributes
142
- end
143
-
144
- def reflect_on_association(*args)
145
- @@model_class.reflect_on_association(*args)
146
- end
147
-
148
- def model_class
149
- if defined?(@@model_class) && @@model_class
150
- @@model_class
151
- else
152
- model_class_name ||= name.to_s.sub(/Form$/, '')
153
- begin
154
- @@model_class = model_class_name.constantize
155
- rescue StandardError
156
- error = Tramway::Error.new(plugin: :core, method: :model_class, message: "There is not model class name for #{name}. Should be #{model_class_name} or you can use another class to initialize form object or just initialize form with object.")
157
- raise error.message
158
- end
159
- end
160
- end
90
+ def model_class=(name)
91
+ @@model_class = name
92
+ end
161
93
 
162
- def model_class=(name)
163
- @@model_class = name
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)
164
97
  end
98
+ @@model_class.validates attribute, **options
99
+ end
100
+ end
165
101
 
166
- def validation_group_class
167
- ActiveModel
168
- end
102
+ private
169
103
 
170
- def validates(attribute, **options)
171
- if !defined?(@@model_class) || @@model_class.nil?
172
- 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.')
173
- raise error.message
174
- end
175
- @@model_class.validates attribute, **options
176
- end
104
+ def collecting_associations_errors
105
+ @@associations.each do |association|
106
+ model.send("#{association}=", send(association)) if errors.details[association] == [{ error: :blank }]
177
107
  end
178
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
179
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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Core::ApplicationForms::ConstantClassActions
4
+ def validation_group_class
5
+ ActiveModel
6
+ end
7
+ 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
- Object.const_set(name, Class.new(::Tramway::Core::ApplicationForm) do
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) && model.errors.empty?
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
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Core::ExtendableFormsHelpers::ClassBuilder
4
+ def build_form_class(name, simple_properties, more_properties)
5
+ Object.const_set(name, Class.new(::Tramway::Core::ApplicationForm) do
6
+ properties(*simple_properties.keys) if simple_properties.keys.any?
7
+
8
+ include Tramway::Core::ExtendableFormsHelpers::Submit::ObjectHelpers
9
+ include Tramway::Core::ExtendableFormsHelpers::Validators
10
+ extend Tramway::Core::ExtendableFormsHelpers::Submit::ClassHelpers
11
+ extend Tramway::Core::ExtendableFormsHelpers::PropertiesHelper
12
+ extend Tramway::Core::ExtendableFormsHelpers::MorePropertiesHelper
13
+ extend Tramway::Core::ExtendableFormsHelpers::IgnoredPropertiesHelper
14
+
15
+ define_submit_method simple_properties, more_properties
16
+ define_properties_method simple_properties, more_properties
17
+ define_ignored_properties_method
18
+
19
+ more_properties.each do |property|
20
+ define_property_method property[0]
21
+
22
+ case property[1][:object].field_type
23
+ when 'file'
24
+ field = property[1][:object]
25
+ define_file_property_assignment_method property field
26
+ else
27
+ next unless property[1][:validates].present?
28
+
29
+ define_assignment_method property
30
+ end
31
+ end
32
+ end)
33
+ end
34
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Core::ExtendableFormsHelpers::IgnoredPropertiesHelper
4
+ def define_ignored_properties_method
5
+ define_method :jsonb_ignored_properties do |properties|
6
+ properties.map do |property|
7
+ property[0].to_s if property[1][:object].field_type == 'file'
8
+ end.compact
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Core::ExtendableFormsHelpers::MorePropertiesHelper
4
+ def define_property_method(property_name)
5
+ define_method property_name do
6
+ model.values[property_name] if model.values
7
+ end
8
+ end
9
+
10
+ def define_assignment_method(property)
11
+ define_method "#{property[0]}=" do |value|
12
+ property[1][:validates].each do |pair|
13
+ make_validates property[0], pair, value
14
+ end
15
+ end
16
+ end
17
+
18
+ def define_file_property_assignment_method(property, field)
19
+ define_method "#{property[0]}=" do |value|
20
+ file_instance = property[1][:association_model].find_or_create_by(
21
+ "#{model.class.name.underscore}_id" => model.id, "#{field.class.name.underscore}_id" => field.id
22
+ )
23
+ file_instance.file = value
24
+ file_instance.save!
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Core::ExtendableFormsHelpers::PropertiesHelper
4
+ def define_properties_method(simple_properties, more_properties)
5
+ define_method 'properties' do
6
+ hash = simple_properties.each_with_object({}) do |property, h|
7
+ h.merge! property[0] => property[1] unless model.class.state_machines.keys.include?(property[0])
8
+ end
9
+ more_properties.reduce(hash) do |h, property|
10
+ h.merge! property[0] => {
11
+ extended_form_property: property[1][:object]
12
+ }
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Core::ExtendableFormsHelpers::Submit::ClassHelpers
4
+ def define_submit_method(simple_properties, more_properties)
5
+ define_method 'submit' do |params|
6
+ model.values ||= {}
7
+ extended_params = extended(simple_properties, more_properties, params)
8
+ params.each do |key, value|
9
+ method_name = "#{key}="
10
+ send method_name, value if respond_to?(method_name)
11
+ end
12
+ model.values = extended_params.reduce(model.values) do |hash, pair|
13
+ hash.merge! pair[0] => pair[1]
14
+ end
15
+ super(params) && model.errors.empty?
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Core::ExtendableFormsHelpers::Submit::ObjectHelpers
4
+ def extended(simple_properties, more_properties, params)
5
+ params.except(*simple_properties.keys).except(*jsonb_ignored_properties(more_properties)).permit!.to_h
6
+ end
7
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Core::ExtendableFormsHelpers::Validators
4
+ def make_validates(property_name, validation, value)
5
+ case validation[0].to_s
6
+ when 'presence'
7
+ presence_validator property_name, validation, value
8
+ when 'inclusion'
9
+ inclusion_validator property_name, validation, value
10
+ end
11
+ end
12
+
13
+ def presence_validator(property_name, validation, value)
14
+ validator_object = PresenceValidator.new(attributes: :not_blank)
15
+ return if validation[1] == 'false'
16
+ return if validation[1] == 'true' && validator_object.send(:valid?, value)
17
+
18
+ model.errors.add(
19
+ property_name,
20
+ I18n.t(
21
+ "activerecord.errors.models.#{model.class.name.underscore}.attributes.default.#{validation[0]}",
22
+ value: value
23
+ )
24
+ )
25
+ end
26
+
27
+ def inclusion_validator(property_name, validation, value)
28
+ in_array = validation[1][:in]
29
+
30
+ return if value.in? in_array
31
+
32
+ model.errors.add(
33
+ property_name,
34
+ I18n.t(
35
+ "activerecord.errors.models.#{model.class.name.underscore}.attributes.default.#{validation[0]}",
36
+ value: value
37
+ )
38
+ )
39
+ end
40
+ end
@@ -1,15 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tramway
4
- module Core
5
- module CopyToClipboardHelper
6
- def copy_to_clipboard(id)
7
- button_tag class: 'btn btn-info clipboard-btn',
8
- data: { clipboard_action: 'copy', clipboard_target: "##{id}" },
9
- style: 'margin-left: 15px' do
10
- fa_icon 'copy'
11
- end
12
- end
3
+ module Tramway::Core::CopyToClipboardHelper
4
+ def copy_to_clipboard(id)
5
+ button_tag class: 'btn btn-info clipboard-btn',
6
+ data: { clipboard_action: 'copy', clipboard_target: "##{id}" },
7
+ style: 'margin-left: 15px' do
8
+ fa_icon 'copy'
13
9
  end
14
10
  end
15
11
  end
@@ -1,29 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tramway
4
- module Core
5
- module TitleHelper
6
- def title(page_title = default_title)
7
- if @application.present?
8
- title_text = "#{page_title} | #{@application.try(:title) || @application.public_name}"
9
- content_for(:title) { title_text }
10
- else
11
- error = Tramway::Error.new(plugin: :core, method: :title, message: 'You should set Tramway::Core::Application class using `::Tramway::Core.initialize_application model_class: #{model_class_name}` in config/initializers/tramway.rb OR maybe you don\'t have any records of application model')
12
- raise error.message
13
- end
14
- end
3
+ module Tramway::Core::TitleHelper
4
+ def title(page_title = default_title)
5
+ if @application.present?
6
+ title_text = "#{page_title} | #{@application.try(:title) || @application.public_name}"
7
+ content_for(:title) { title_text }
8
+ else
9
+ Tramway::Error.raise_error(:tramway, :core, :title_helper, :title, :you_should_set_tramway_core_application)
10
+ end
11
+ end
15
12
 
16
- def default_title
17
- t('.title')
18
- end
13
+ def default_title
14
+ t('.title')
15
+ end
19
16
 
20
- def page_title(action, model_name)
21
- if I18n.locale == :ru
22
- t("helpers.actions.#{action}") + ' ' + genitive(model_name)
23
- else
24
- t("helpers.actions.#{action}") + ' ' + model_name.model_name.human.downcase
25
- end
26
- end
17
+ def page_title(action, model_name)
18
+ if I18n.locale == :ru
19
+ t("helpers.actions.#{action}") + ' ' + genitive(model_name)
20
+ else
21
+ t("helpers.actions.#{action}") + ' ' + model_name.model_name.human.downcase
27
22
  end
28
23
  end
29
24
  end
@@ -2,52 +2,50 @@
2
2
 
3
3
  require 'carrierwave/orm/activerecord' if defined?(CarrierWave::Mount)
4
4
 
5
- module Tramway
6
- module Core
7
- class ApplicationRecord < ActiveRecord::Base
8
- self.abstract_class = true
9
- audited
10
- extend ::Enumerize
11
-
12
- state_machine :state, initial: :active do
13
- state :active
14
- state :removed
15
-
16
- event :remove do
17
- transition active: :remove
18
- end
19
- end
5
+ class Tramway::Core::ApplicationRecord < ActiveRecord::Base
6
+ self.abstract_class = true
7
+ audited
8
+ extend ::Enumerize
20
9
 
21
- scope :active, -> { where state: :active }
22
- scope :created_by_user, ->(user_id) { joins(:audits).where('audits.action = \'create\' AND audits.user_id = ?', user_id) }
23
- scope :admin_scope, ->(_arg) { all }
10
+ state_machine :state, initial: :active do
11
+ state :active
12
+ state :removed
24
13
 
25
- include ::PgSearch::Model
14
+ event :remove do
15
+ transition active: :remove
16
+ end
17
+ end
26
18
 
27
- def creator
28
- audits.where(action: :create).first.user
29
- end
19
+ scope :active, -> { where state: :active }
20
+ scope :created_by_user, lambda { |user_id|
21
+ joins(:audits).where('audits.action = \'create\' AND audits.user_id = ?', user_id)
22
+ }
23
+ scope :admin_scope, ->(_arg) { all }
30
24
 
31
- # FIXME: detect inhertited locales
32
- class << self
33
- def human_attribute_name(attribute_name, *_args)
34
- excepted_attributes = %w[created_at updated_at state]
35
- if attribute_name.to_s.in? excepted_attributes
36
- I18n.t "activerecord.attributes.tramway/core/application_record.#{attribute_name}"
37
- else
38
- super attribute_name
39
- end
40
- end
41
-
42
- def search_by(*attributes, **associations)
43
- pg_search_scope :full_text_search, against: attributes, associated_against: associations
44
- end
45
- end
25
+ include ::PgSearch::Model
46
26
 
47
- # FIXME: detect inhertited locales
48
- def human_state_name
49
- I18n.t "activerecord.state_machines.tramway/core/application_record.state.states.#{state}"
27
+ def creator
28
+ audits.where(action: :create).first.user
29
+ end
30
+
31
+ # FIXME: detect inhertited locales
32
+ class << self
33
+ def human_attribute_name(attribute_name, *_args)
34
+ excepted_attributes = %w[created_at updated_at state]
35
+ if attribute_name.to_s.in? excepted_attributes
36
+ I18n.t "activerecord.attributes.tramway/core/application_record.#{attribute_name}"
37
+ else
38
+ super attribute_name
50
39
  end
51
40
  end
41
+
42
+ def search_by(*attributes, **associations)
43
+ pg_search_scope :full_text_search, against: attributes, associated_against: associations
44
+ end
45
+ end
46
+
47
+ # FIXME: detect inhertited locales
48
+ def human_state_name
49
+ I18n.t "activerecord.state_machines.tramway/core/application_record.state.states.#{state}"
52
50
  end
53
51
  end
@@ -4,7 +4,8 @@ module ImageDefaults
4
4
  include CarrierWave::MiniMagick
5
5
 
6
6
  def default_url
7
- "/images/fallback/#{model.class.model_name.to_s.underscore}/" << [mounted_as, version_name].compact.join('_') << '.gif'
7
+ "/images/fallback/#{model.class.model_name.to_s.underscore}/" <<
8
+ [mounted_as, version_name].compact.join('_') << '.gif'
8
9
  end
9
10
 
10
11
  def extension_white_list
@@ -44,14 +44,14 @@ class PhotoUploader < ApplicationUploader
44
44
  before :cache, :capture_size
45
45
 
46
46
  def capture_size(file)
47
- if version_name.blank?
48
- if file.path.nil?
49
- img = ::MiniMagick::Image.read(file.file)
50
- @width = img[:width]
51
- @height = img[:height]
52
- else
53
- @width, @height = `identify -format "%wx %h" #{file.path}`.split(/x/).map(&:to_i)
54
- end
47
+ return unless version_name.blank?
48
+
49
+ if file.path.nil?
50
+ img = ::MiniMagick::Image.read(file.file)
51
+ @width = img[:width]
52
+ @height = img[:height]
53
+ else
54
+ @width, @height = `identify -format "%wx %h" #{file.path}`.split(/x/).map(&:to_i)
55
55
  end
56
56
  end
57
57
  end
@@ -6,7 +6,7 @@
6
6
  plural: {
7
7
  keys: %i[zero one few many],
8
8
  rule: lambda do |n|
9
- if n == 0
9
+ if n.zero?
10
10
  :zero
11
11
  elsif n % 10 == 1 && n % 100 != 11
12
12
  # 1, 21, 31, 41, 51, 61...
@@ -14,7 +14,7 @@
14
14
  elsif [2, 3, 4].include?(n % 10) && ![12, 13, 14].include?(n % 100)
15
15
  # 2-4, 22-24, 32-34...
16
16
  :few
17
- elsif n % 10 == 0 || ![5, 6, 7, 8, 9].include?(n % 10) || ![11, 12, 13, 14].include?(n % 100)
17
+ elsif n % 10.zero? || ![5, 6, 7, 8, 9].include?(n % 10) || ![11, 12, 13, 14].include?(n % 100)
18
18
  # 0, 5-20, 25-30, 35-40...
19
19
  :many
20
20
  end
@@ -1,11 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tramway
4
- class Collection
5
- class << self
6
- def list
7
- raise 'Please add collection to list method'
8
- end
3
+ class Tramway::Collection
4
+ class << self
5
+ def list
6
+ raise 'Please add collection to list method'
9
7
  end
10
8
  end
11
9
  end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Collections
4
+ end
@@ -1,20 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tramway
4
- module Collections
5
- module Helper
6
- def collection_list_by(name:)
7
- begin
8
- require name # needed to load class name with collection
9
- rescue LoadError
10
- raise "No such file #{name}. You should create file in the `lib/#{name}.rb` or elsewhere you want"
11
- end
12
- unless ::Tramway::Collection.descendants.map(&:to_s).include?(name.camelize)
13
- raise "There no such collection named #{name.camelize}. Please create class with self method `list` and extended of `Tramway::Collection`. You should reload your server after creating this collection."
14
- end
3
+ require 'tramway/collections'
15
4
 
16
- name.camelize.constantize.list
17
- end
5
+ module Tramway::Collections::Helper
6
+ def collection_list_by(name:)
7
+ begin
8
+ require name # needed to load class name with collection
9
+ rescue LoadError
10
+ raise "No such file #{name}. You should create file in the `lib/#{name}.rb` or elsewhere you want"
18
11
  end
12
+ unless ::Tramway::Collection.descendants.map(&:to_s).include?(name.camelize)
13
+ ::Tramway::Error.raise_error(
14
+ :tramway, :collections, :helper, :collection_list_by, :there_no_such_collection,
15
+ name_camelize: name.camelize
16
+ )
17
+ end
18
+
19
+ name.camelize.constantize.list
19
20
  end
20
21
  end
data/lib/tramway/core.rb CHANGED
@@ -9,37 +9,33 @@ require 'reform'
9
9
  require 'pg_search'
10
10
  require 'validators/presence_validator'
11
11
 
12
- module Tramway
13
- module Core
14
- class << self
15
- def initialize_application(**options)
16
- @application ||= Tramway::Core::Application.new
17
- options.each do |attr, value|
18
- @application.send "#{attr}=", value
19
- end
12
+ module Tramway::Core
13
+ class << self
14
+ def initialize_application(**options)
15
+ @application ||= Tramway::Core::Application.new
16
+ options.each do |attr, value|
17
+ @application.send "#{attr}=", value
20
18
  end
19
+ end
21
20
 
22
- def application_object
23
- if @application&.model_class.present?
24
- begin
25
- @application.model_class.first
26
- rescue StandardError
27
- nil
28
- end
29
- else
30
- @application
21
+ def application_object
22
+ if @application&.model_class.present?
23
+ begin
24
+ @application.model_class.first
25
+ rescue StandardError
26
+ nil
31
27
  end
28
+ else
29
+ @application
32
30
  end
33
-
34
- attr_reader :application
35
31
  end
32
+
33
+ attr_reader :application
36
34
  end
37
35
  end
38
36
 
39
37
  # HACK: FIXME
40
38
 
41
- module ActiveModel
42
- class Errors
43
- def merge!(*args); end
44
- end
39
+ class ActiveModel::Errors
40
+ def merge!(*args); end
45
41
  end
@@ -5,14 +5,10 @@ require 'tramway/core/application'
5
5
  require 'simple_form'
6
6
  require 'enumerize'
7
7
 
8
- module Tramway
9
- module Core
10
- class Engine < ::Rails::Engine
11
- isolate_namespace Tramway::Core
8
+ class Tramway::Core::Engine < ::Rails::Engine
9
+ isolate_namespace Tramway::Core
12
10
 
13
- config.before_initialize do
14
- config.i18n.load_path += Dir["#{config.root}/config/locales/**/*.yml"]
15
- end
16
- end
11
+ config.before_initialize do
12
+ config.i18n.load_path += Dir["#{config.root}/config/locales/**/*.yml"]
17
13
  end
18
14
  end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Core::Generators
4
+ end
@@ -1,27 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rails/generators'
4
+ require 'tramway/core/generators'
4
5
 
5
- module Tramway
6
- module Core
7
- module Generators
8
- class InstallGenerator < ::Rails::Generators::Base
9
- source_root File.expand_path('templates', __dir__)
6
+ class Tramway::Core::Generators::InstallGenerator < ::Rails::Generators::Base
7
+ source_root File.expand_path('templates', __dir__)
10
8
 
11
- def run_other_generators
12
- generate 'audited:install'
13
- end
9
+ def run_other_generators
10
+ generate 'audited:install'
11
+ end
14
12
 
15
- def self.next_migration_number(path)
16
- next_migration_number = current_migration_number(path) + 1
17
- ActiveRecord::Migration.next_migration_number next_migration_number
18
- end
13
+ def self.next_migration_number(path)
14
+ next_migration_number = current_migration_number(path) + 1
15
+ ActiveRecord::Migration.next_migration_number next_migration_number
16
+ end
19
17
 
20
- def copy_initializer
21
- copy_file "/#{File.dirname __dir__}/generators/templates/initializers/simple_form.rb", 'config/initializers/simple_form.rb'
22
- copy_file "/#{File.dirname __dir__}/generators/templates/initializers/simple_form_bootstrap.rb", 'config/initializers/simple_form_bootstrap.rb'
23
- end
24
- end
18
+ def copy_initializer
19
+ simple_form_files = %w[simple_form simple_form_bootstrap]
20
+ simple_form_files.each do |file|
21
+ copy_file(
22
+ "/#{File.dirname __dir__}/generators/templates/initializers/#{file}.rb",
23
+ "config/initializers/#{file}.rb"
24
+ )
25
25
  end
26
26
  end
27
27
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Tramway
4
4
  module Core
5
- VERSION = '1.17.2.1'
5
+ VERSION = '1.17.2.2'
6
6
  end
7
7
  end
data/lib/tramway/error.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  class Tramway::Error < RuntimeError
4
4
  def initialize(*args, plugin: nil, method: nil, message: nil)
5
- @properties ||= {}
5
+ @properties = {}
6
6
  @properties[:plugin] = plugin
7
7
  @properties[:method] = method
8
8
  @properties[:message] = message
@@ -16,4 +16,15 @@ class Tramway::Error < RuntimeError
16
16
  def properties
17
17
  @properties ||= {}
18
18
  end
19
+
20
+ class << self
21
+ def raise_error(*coordinates, **options)
22
+ @errors ||= YAML.load_file('..', '..', 'yaml', 'errors.yml').with_indifferent_access
23
+ error = @errors.dig(*coordinates)
24
+ options.each do |pair|
25
+ error.gsub!("%{#{pair[0]}}", pair[1])
26
+ end
27
+ raise error
28
+ end
29
+ end
19
30
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tramway-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.17.2.1
4
+ version: 1.17.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pavel Kalashnikov
8
+ - moshiaan
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2020-03-17 00:00:00.000000000 Z
12
+ date: 2020-03-19 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: audited
@@ -360,7 +361,18 @@ files:
360
361
  - app/decorators/tramway/core/concerns/attributes_decorator_helper.rb
361
362
  - app/decorators/tramway/core/delegating/class_helper.rb
362
363
  - app/forms/tramway/core/application_form.rb
364
+ - app/forms/tramway/core/application_forms/association_object_helpers.rb
365
+ - app/forms/tramway/core/application_forms/constant_class_actions.rb
366
+ - app/forms/tramway/core/application_forms/constant_object_actions.rb
367
+ - app/forms/tramway/core/application_forms/properties_object_helper.rb
363
368
  - app/forms/tramway/core/extendable_form.rb
369
+ - app/forms/tramway/core/extendable_forms_helpers/class_builder.rb
370
+ - app/forms/tramway/core/extendable_forms_helpers/ignored_properties_helper.rb
371
+ - app/forms/tramway/core/extendable_forms_helpers/more_properties_helper.rb
372
+ - app/forms/tramway/core/extendable_forms_helpers/properties_helper.rb
373
+ - app/forms/tramway/core/extendable_forms_helpers/submit/class_helpers.rb
374
+ - app/forms/tramway/core/extendable_forms_helpers/submit/object_helpers.rb
375
+ - app/forms/tramway/core/extendable_forms_helpers/validators.rb
364
376
  - app/forms/tramway/core/extended_application_form.rb
365
377
  - app/forms/tramway/core/form_creator.rb
366
378
  - app/helpers/tramway/core/copy_to_clipboard_helper.rb
@@ -397,10 +409,12 @@ files:
397
409
  - lib/string.rb
398
410
  - lib/tasks/tramway/core_tasks.rake
399
411
  - lib/tramway/collection.rb
412
+ - lib/tramway/collections.rb
400
413
  - lib/tramway/collections/helper.rb
401
414
  - lib/tramway/core.rb
402
415
  - lib/tramway/core/application.rb
403
416
  - lib/tramway/core/engine.rb
417
+ - lib/tramway/core/generators.rb
404
418
  - lib/tramway/core/generators/install_generator.rb
405
419
  - lib/tramway/core/generators/templates/initializers/simple_form.rb
406
420
  - lib/tramway/core/generators/templates/initializers/simple_form_bootstrap.rb
@@ -408,7 +422,7 @@ files:
408
422
  - lib/tramway/error.rb
409
423
  - lib/tramway/helpers/class_name_helpers.rb
410
424
  - lib/validators/presence_validator.rb
411
- homepage: https://github.com/kalashnikovisme/tramway-core
425
+ homepage: https://github.com/purple-magic/tramway-core
412
426
  licenses:
413
427
  - MIT
414
428
  metadata: {}