tramway-core 1.17.2.1 → 1.17.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -2
  3. data/app/controllers/tramway/core/application_controller.rb +12 -12
  4. data/app/decorators/tramway/core/application_decorator.rb +12 -26
  5. data/app/decorators/tramway/core/associations/class_helper.rb +7 -13
  6. data/app/decorators/tramway/core/associations/object_helper.rb +28 -2
  7. data/app/decorators/tramway/core/attributes/view_helper.rb +26 -0
  8. data/app/decorators/tramway/core/concerns/attributes_decorator_helper.rb +47 -26
  9. data/app/decorators/tramway/core/delegating/class_helper.rb +2 -0
  10. data/app/forms/tramway/core/application_form.rb +96 -145
  11. data/app/forms/tramway/core/application_forms/association_object_helpers.rb +27 -0
  12. data/app/forms/tramway/core/application_forms/constant_class_actions.rb +7 -0
  13. data/app/forms/tramway/core/application_forms/constant_object_actions.rb +20 -0
  14. data/app/forms/tramway/core/application_forms/properties_object_helper.rb +23 -0
  15. data/app/forms/tramway/core/extendable_form.rb +3 -70
  16. data/app/forms/tramway/core/extendable_forms_helpers/class_builder.rb +34 -0
  17. data/app/forms/tramway/core/extendable_forms_helpers/ignored_properties_helper.rb +11 -0
  18. data/app/forms/tramway/core/extendable_forms_helpers/more_properties_helper.rb +27 -0
  19. data/app/forms/tramway/core/extendable_forms_helpers/properties_helper.rb +16 -0
  20. data/app/forms/tramway/core/extendable_forms_helpers/submit/class_helpers.rb +18 -0
  21. data/app/forms/tramway/core/extendable_forms_helpers/submit/object_helpers.rb +7 -0
  22. data/app/forms/tramway/core/extendable_forms_helpers/validators.rb +40 -0
  23. data/app/helpers/tramway/core/application_helper.rb +2 -0
  24. data/app/helpers/tramway/core/copy_to_clipboard_helper.rb +6 -10
  25. data/app/helpers/tramway/core/inputs_helper.rb +93 -0
  26. data/app/helpers/tramway/core/title_helper.rb +17 -22
  27. data/app/models/tramway/core/application_record.rb +38 -40
  28. data/app/uploaders/image_defaults.rb +2 -1
  29. data/app/uploaders/photo_uploader.rb +8 -8
  30. data/app/views/tramway/core/shared/_input.html.haml +26 -0
  31. data/config/initializers/plurals.rb +2 -2
  32. data/lib/tramway/collection.rb +4 -6
  33. data/lib/tramway/collections.rb +4 -0
  34. data/lib/tramway/collections/helper.rb +15 -14
  35. data/lib/tramway/core.rb +22 -22
  36. data/lib/tramway/core/engine.rb +4 -8
  37. data/lib/tramway/core/generators.rb +6 -0
  38. data/lib/tramway/core/generators/install_generator.rb +17 -17
  39. data/lib/tramway/core/version.rb +1 -1
  40. data/lib/tramway/error.rb +12 -1
  41. data/lib/yaml/errors.yml +35 -0
  42. metadata +22 -3
@@ -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
@@ -0,0 +1,26 @@
1
+ - model_class = defined?(record) ? record.model : model_class
2
+ - value = defined?(value) ? value : value_from_params(model_class: model_class, property: property, type: type)
3
+ - form_object = defined?(record) ? record : instance_variable_get("@#{object}_form")
4
+ - input_params = { property: property, object: object, form_object: form_object, value: value }
5
+ - if !type.class.in?([ Symbol, String ]) && type[:input_options]
6
+ - input_params.merge!(options: type[:input_options])
7
+ - type = type[:type]
8
+ - if type.class.in?([ Symbol, String ]) || type&.dig(:input_options)
9
+ - type = type.to_sym
10
+ = form.label form_object.model.class.human_attribute_name property
11
+ - case type
12
+ - when :default
13
+ = form.input property, **default_params(**input_params)
14
+ - when :association
15
+ = form.association property, **association_params(**input_params)
16
+ - when :polymorphic_association
17
+ = form.input property, **polymorphic_association_params(**input_params.merge(value: value))
18
+ - else
19
+ = form.input property, **else_params(**input_params.merge(type: type))
20
+ - else
21
+ - property_value = form_object.model.values.present? && form_object.model.values[property.to_s]
22
+ = render 'tramway/core/shared/input_extended', field: type[:extended_form_property], class_name: :record, value: property_value, f: form
23
+
24
+ - if params[:errors].present? && params[:errors][property]&.first
25
+ .alert.alert-danger
26
+ = params[:errors][property]&.first
@@ -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
@@ -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,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Core
4
+ module Generators
5
+ end
6
+ 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.3'
6
6
  end
7
7
  end
@@ -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("#{Tramway::Core.root}/yaml/errors.yml").with_indifferent_access
23
+ error = @errors.dig(*coordinates)
24
+ options.each do |pair|
25
+ error.gsub!("%{#{pair[0]}}", pair[1].to_s)
26
+ end
27
+ raise error
28
+ end
29
+ end
19
30
  end
@@ -0,0 +1,35 @@
1
+ tramway:
2
+ collections:
3
+ helper:
4
+ collection_list_by:
5
+ there_no_such_collection: "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."
6
+ core:
7
+ title_helper:
8
+ title:
9
+ you_should_set_tramway_core_application: "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"
10
+ application_form:
11
+ initialize:
12
+ polymorphic_class_is_nil: "Polymorphic association class is nil. Maybe, you should write `assocation #{association_name}` after `properties #{association_name}_id, #{association_name}_type`"
13
+ validates:
14
+ you_need_to_set_model_class: 'You need to set `model_class` name while using validations. Just write `self.model_class = YOUR_MODEL_NAME` in the class area.'
15
+ submit:
16
+ looks_like_you_have_method: "Looks like you have method `%{method_name}` in %{model_class}. You should rename it or rename property in %{class_name}"
17
+ params_should_not_be_nil: "ApplicationForm::Params should not be nil"
18
+ model_class:
19
+ there_is_not_model_class: "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."
20
+ concerns:
21
+ attribute_decorator_helper:
22
+ you_should_mount_photo_uploader: "You should mount PhotoUploader to your model. Just add `mount_uploader %{attribute_name}, PhotoUploader` to your model. %{message}"
23
+ associations:
24
+ object_helper:
25
+ please_specify_association_name: "Please, specify `%{association_name}` association class_name in %{object_class} model. For example: `has_many :%{association_name}, class_name: '%{association_class_name}'`"
26
+ class_helper:
27
+ model_does_not_have_association: "Model %{object_class} does not have association named `%{association_name}`"
28
+ application_decorator:
29
+ attributes:
30
+ method_is_reserved_word: "Method `%{attribute_name}` is reserved word. Please, create or delegate method in %{class_name} with another name."
31
+ title:
32
+ please_implement_title: "Please, implement `title` method in a %{class_name} or %{object_class}"
33
+ link:
34
+ method_link_uses_file_attribute: "Method `link` uses `file` attribute of the decorated object. If decorated object doesn't contain `file`, you shouldn't use `link` method."
35
+