tramway-core 1.17.2.1 → 1.17.2.2

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.
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: {}