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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +83 -2
  3. data/app/assets/javascripts/tramway/core/application.js +1 -1
  4. data/app/controllers/tramway/core/application_controller.rb +8 -12
  5. data/app/decorators/tramway/core/application_decorator.rb +16 -28
  6. data/app/decorators/tramway/core/associations/class_helper.rb +13 -13
  7. data/app/decorators/tramway/core/associations/object_helper.rb +31 -3
  8. data/app/decorators/tramway/core/attributes/view_helper.rb +26 -0
  9. data/app/decorators/tramway/core/concerns/attributes_decorator_helper.rb +47 -26
  10. data/app/decorators/tramway/core/delegating/class_helper.rb +9 -0
  11. data/app/forms/tramway/core/application_form.rb +83 -171
  12. data/app/forms/tramway/core/application_forms/association_object_helpers.rb +31 -0
  13. data/app/forms/tramway/core/application_forms/constant_class_actions.rb +7 -0
  14. data/app/forms/tramway/core/application_forms/constant_object_actions.rb +13 -0
  15. data/app/forms/tramway/core/application_forms/properties_object_helper.rb +23 -0
  16. data/app/forms/tramway/core/extendable_form.rb +3 -70
  17. data/app/forms/tramway/core/extendable_forms_helpers/class_builder.rb +34 -0
  18. data/app/forms/tramway/core/extendable_forms_helpers/ignored_properties_helper.rb +11 -0
  19. data/app/forms/tramway/core/extendable_forms_helpers/more_properties_helper.rb +27 -0
  20. data/app/forms/tramway/core/extendable_forms_helpers/properties_helper.rb +16 -0
  21. data/app/forms/tramway/core/extendable_forms_helpers/submit/class_helpers.rb +18 -0
  22. data/app/forms/tramway/core/extendable_forms_helpers/submit/object_helpers.rb +7 -0
  23. data/app/forms/tramway/core/extendable_forms_helpers/validators.rb +40 -0
  24. data/app/helpers/tramway/core/copy_to_clipboard_helper.rb +6 -10
  25. data/app/helpers/tramway/core/title_helper.rb +17 -22
  26. data/app/models/tramway/core/application_record.rb +38 -40
  27. data/app/uploaders/image_defaults.rb +2 -1
  28. data/app/uploaders/photo_uploader.rb +8 -8
  29. data/config/initializers/plurals.rb +2 -2
  30. data/lib/tramway/collection.rb +4 -6
  31. data/lib/tramway/collections.rb +4 -0
  32. data/lib/tramway/collections/helper.rb +15 -14
  33. data/lib/tramway/core.rb +22 -22
  34. data/lib/tramway/core/engine.rb +4 -8
  35. data/lib/tramway/core/generators.rb +4 -0
  36. data/lib/tramway/core/generators/install_generator.rb +17 -17
  37. data/lib/tramway/core/version.rb +1 -1
  38. data/lib/tramway/error.rb +12 -1
  39. data/lib/yaml/errors.yml +35 -0
  40. metadata +20 -3
@@ -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
@@ -9,37 +9,37 @@ 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
31
+ end
33
32
 
34
- attr_reader :application
33
+ def root
34
+ File.dirname __dir__
35
35
  end
36
+
37
+ attr_reader :application
36
38
  end
37
39
  end
38
40
 
39
41
  # HACK: FIXME
40
42
 
41
- module ActiveModel
42
- class Errors
43
- def merge!(*args); end
44
- end
43
+ class ActiveModel::Errors
44
+ def merge!(*args); end
45
45
  end