eac_rails_remotes 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ad2ac8698baa47735671800fe9a737b2c0fe5330e73964dd4156acceae7c2019
4
+ data.tar.gz: e3e71fc55d8a5f2cb6b28aa2ac44643ae29d15550bc4778c00341873bbb7ec10
5
+ SHA512:
6
+ metadata.gz: 69fdf3ebfa1841ca012def980872fad6e83e7efde4a5d9793890e1836fd6f63145c0b3c4a88a3cea5076e21a23dcabf21a3fcf1333766ba82482e2159670acf0
7
+ data.tar.gz: ce03870632e332c6366f5b33e8eb296d066af6f871033c5a204dea29362a08ddfb2a57e336b9a387711ec1707ac7c138b91ffc209c6e1e918aa138a446cfa17f
@@ -0,0 +1,2 @@
1
+ //= require_tree .
2
+ //= require eac_active_scaffold
@@ -0,0 +1 @@
1
+ @import 'eac_active_scaffold';
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacRailsRemotes
4
+ class InstancesController < ApplicationController
5
+ before_action :localize_options
6
+
7
+ active_scaffold :'eac_rails_remotes/instance' do |conf|
8
+ conf.actions.exclude :create, :update
9
+ conf.columns[:export_status].form_ui = :select
10
+ conf.columns[:entity].form_ui = :select
11
+ conf.actions.swap :search, :field_search
12
+ conf.field_search.columns = :entity, :export_status
13
+ end
14
+
15
+ private
16
+
17
+ def localize_options
18
+ active_scaffold_config.columns[:export_status].options = {
19
+ options: ::EacRailsRemotes::Instance.lists.export_status.options
20
+ }
21
+ active_scaffold_config.columns[:entity].options = {
22
+ options: ::EacRailsRemotes::Instance.select(:entity).order(entity: :asc).distinct
23
+ .pluck(:entity)
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EacRailsRemotes
6
+ class Instance < ::ActiveRecord::Base
7
+ self.table_name = 'eac_rails_remotes_instances'
8
+ enable_listable
9
+ lists.add_integer :export_status, :new_data, :ok, :error
10
+
11
+ validates :source, presence: true
12
+ validates :entity, presence: true
13
+ validates :code, presence: true, uniqueness: { scope: %i[source entity] }
14
+ validates :data, presence: true
15
+ validates :export_status, presence: true, inclusion: { in: lists.export_status.values }
16
+
17
+ belongs_to :target, polymorphic: true, optional: true
18
+
19
+ scope :pendent, lambda {
20
+ where.not(export_status: EXPORT_STATUS_OK)
21
+ }
22
+
23
+ def to_s
24
+ "#{source}|#{entity}|#{code}"
25
+ end
26
+
27
+ def export
28
+ Rails.logger.info("Exporting #{self}")
29
+ t = target || entity_class.new
30
+ t.attributes = target_attributes
31
+ if t.save
32
+ update!(export_status: EXPORT_STATUS_OK, export_message: '', target: t)
33
+ else
34
+ update!(export_status: EXPORT_STATUS_ERROR,
35
+ export_message: target_export_message(t))
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def target_attributes
42
+ Hash[EacRubyUtils::Yaml.load(data).map { |k, v| target_attribute(k, v) }]
43
+ end
44
+
45
+ def target_attribute(attr, value)
46
+ a = entity_association_class(attr)
47
+ return [attr, value] unless a
48
+
49
+ ri = self.class.find_by(source: source, entity: a.klass.name, code: value)
50
+ [a.name, ri ? ri.target : nil]
51
+ end
52
+
53
+ # @return [ActiveRecord::Reflection::BelongsToReflection, nil]
54
+ def entity_association_class(attribute)
55
+ entity_class.reflect_on_all_associations(:belongs_to)
56
+ .find { |x| x.foreign_key.to_sym == attribute.to_sym }
57
+ end
58
+
59
+ def entity_class
60
+ entity.constantize
61
+ end
62
+
63
+ def target_export_message(target)
64
+ "ATTRIBUTES: #{target.attributes}\nERRORS: #{target.errors.messages}\n"
65
+ end
66
+
67
+ class << self
68
+ def import(record)
69
+ ri = where(source: record[:source], entity: record[:entity], code: record[:code])
70
+ .first_or_initialize
71
+ ri.data = record[:data].to_yaml
72
+ ri.export_status = EXPORT_STATUS_NEW_DATA
73
+ ri.save!
74
+ ri
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,20 @@
1
+ ---
2
+ en:
3
+ activerecord:
4
+ models:
5
+ eac_rails_remotes/instance:
6
+ one: Remote instance
7
+ other: Remote instances
8
+ eac_ruby_utils:
9
+ listable:
10
+ remote_instance:
11
+ export_status:
12
+ error:
13
+ label: Error
14
+ description: Failed export.
15
+ new_data:
16
+ label: Novo registro
17
+ description: Record was imported, but not exported yet.
18
+ ok:
19
+ label: Ok
20
+ description: Successful export.
@@ -0,0 +1,20 @@
1
+ ---
2
+ pt-BR:
3
+ activerecord:
4
+ models:
5
+ eac_rails_remotes/instance:
6
+ one: Instância remota
7
+ other: Instâncias remotas
8
+ eac_ruby_utils:
9
+ listable:
10
+ eac_rails_remotes/instance:
11
+ export_status:
12
+ error:
13
+ label: Erro
14
+ description: Exportação mal-sucedida.
15
+ new_data:
16
+ label: Novo registro
17
+ description: Registro foi importado, mas não exportado.
18
+ ok:
19
+ label: Ok
20
+ description: Exportação bem-sucedida.
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ ::EacRailsRemotes::Engine.routes.draw do
4
+ resources(:instances, concerns: active_scaffold)
5
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateEacRailsRemotesInstances < ActiveRecord::Migration[5.2]
4
+ def change
5
+ create_table :eac_rails_remotes_instances do |t|
6
+ t.string :source
7
+ t.string :entity
8
+ t.string :code
9
+ t.references :target, polymorphic: true
10
+ t.text :data
11
+ t.integer :export_status
12
+ t.text :export_message
13
+
14
+ t.timestamps null: false
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency 'eac_active_scaffold/engine'
4
+ require_dependency 'eac_rails_utils/engine_helper'
5
+
6
+ module EacRailsRemotes
7
+ class Engine < ::Rails::Engine
8
+ include ::EacRailsUtils::EngineHelper
9
+ isolate_namespace ::EacRailsRemotes
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacRailsRemotes
4
+ class ExportAll
5
+ def perform
6
+ ::EacRailsRemotes::Instance.pendent.each(&:export)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacRailsRemotes
4
+ class ImportFile
5
+ def initialize(file)
6
+ @file = file
7
+ end
8
+
9
+ def perform
10
+ @counter = Counter.new
11
+ YAML.load_file(@file).each do |r|
12
+ @counter.add_found(r[:source], r[:entity])
13
+ ::EacRailsRemotes::Instance.import(r)
14
+ end
15
+ @counter.show_counts
16
+ end
17
+
18
+ private
19
+
20
+ def init_counts
21
+ @initial_counts = current_counts
22
+ @counts = Hash[@initial_counts.keys.map { |k| [k, 0] }]
23
+ end
24
+
25
+ class Counter
26
+ def initialize
27
+ @initial_counts = current_counts
28
+ @counts = ActiveSupport::HashWithIndifferentAccess.new
29
+ end
30
+
31
+ def add_found(source, entity)
32
+ @counts[entity_to_s(source, entity)] ||= 0
33
+ @counts[entity_to_s(source, entity)] += 1
34
+ end
35
+
36
+ def show_counts
37
+ Rails.logger.info('Counts')
38
+ counts_to_show.each do |l, es|
39
+ Rails.logger.info(" * #{l}:")
40
+ es.each do |e, c|
41
+ Rails.logger.info(" * #{e}: #{c}")
42
+ end
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def counts_to_show
49
+ {
50
+ 'Initial' => initial_counts,
51
+ 'Found' => found_counts,
52
+ 'New' => new_counts,
53
+ 'Final' => current_counts
54
+ }
55
+ end
56
+
57
+ def entity_to_s(source, entity = nil)
58
+ if source.is_a?(::EacRailsRemotes::Instance)
59
+ entity = source.entity
60
+ source = source.source
61
+ elsif source.is_a?(Hash)
62
+ entity = source[:entity]
63
+ source = source[:source]
64
+ end
65
+ "#{source}|#{entity}"
66
+ end
67
+
68
+ def entity_to_h(entity)
69
+ if entity.is_a?(String)
70
+ m = /\A([^\|]+)\|([^\|]+)\z/.match(entity)
71
+ return { source: m[1], entity: m[2] } if m
72
+
73
+ raise "Entity pattern no matched: \"#{entity}\""
74
+ elsif entity.is_a?(::EacRailsRemotes::Instance)
75
+ return { source: entity.source, entity: entity.entity }
76
+ elsif entity.is_a?(Hash)
77
+ return entity
78
+ end
79
+ raise "Entity class not mapped: #{entity}|#{entity.class}"
80
+ end
81
+
82
+ def initial_counts
83
+ Hash[@counts.keys.map { |e, _c| [e, initial_count(e)] }]
84
+ end
85
+
86
+ def found_counts
87
+ @counts
88
+ end
89
+
90
+ def new_counts
91
+ Hash[@counts.keys.map { |e| [e, current_count(e) - initial_count(e)] }]
92
+ end
93
+
94
+ def initial_count(entity)
95
+ @initial_counts[entity_to_s(entity)] ||= 0
96
+ @initial_counts[entity_to_s(entity)]
97
+ end
98
+
99
+ def current_counts
100
+ r = ActiveSupport::HashWithIndifferentAccess.new
101
+ current_entities.each do |e|
102
+ r[entity_to_s(e)] = current_count(e)
103
+ end
104
+ r
105
+ end
106
+
107
+ def current_count(entity)
108
+ entity = entity_to_h(entity)
109
+ ::EacRailsRemotes::Instance.where(source: entity[:source], entity: entity[:entity]).count
110
+ end
111
+
112
+ def current_entities
113
+ ::EacRailsRemotes::Instance.select(:source, :entity).distinct
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacRailsRemotes
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EacRailsRemotes
6
+ require_sub __FILE__
7
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :eac_rails_remotes do
4
+ desc 'Import content from file'
5
+ task :import_file, [:file] => :environment do |_t, args|
6
+ ::EacRailsRemotes::ImportFile.new(args.file).perform
7
+ end
8
+
9
+ desc 'Export pending remote instances'
10
+ task export_all: :environment do |_t, _args|
11
+ ::EacRailsRemotes::Instance.new.perform
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eac_rails_remotes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Put here the authors
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-05-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: eac_active_scaffold
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.2.3
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.2.3
33
+ - !ruby/object:Gem::Dependency
34
+ name: eac_rails_utils
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.17'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 0.17.1
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '0.17'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 0.17.1
53
+ - !ruby/object:Gem::Dependency
54
+ name: eac_ruby_utils
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '0.117'
60
+ type: :runtime
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '0.117'
67
+ - !ruby/object:Gem::Dependency
68
+ name: eac_rails_gem_support
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '0.7'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '0.7'
81
+ - !ruby/object:Gem::Dependency
82
+ name: eac_ruby_gem_support
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '0.5'
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 0.5.1
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '0.5'
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: 0.5.1
101
+ description:
102
+ email:
103
+ executables: []
104
+ extensions: []
105
+ extra_rdoc_files: []
106
+ files:
107
+ - app/assets/javascripts/eac_rails_remotes/application.js
108
+ - app/assets/stylesheets/eac_rails_remotes/application.scss
109
+ - app/controllers/eac_rails_remotes/instances_controller.rb
110
+ - app/models/eac_rails_remotes/instance.rb
111
+ - config/locales/en.yml
112
+ - config/locales/pt-BR.yml
113
+ - config/routes.rb
114
+ - db/migrate/20230521002623_create_eac_rails_remotes_instances.rb
115
+ - lib/eac_rails_remotes.rb
116
+ - lib/eac_rails_remotes/engine.rb
117
+ - lib/eac_rails_remotes/export_all.rb
118
+ - lib/eac_rails_remotes/import_file.rb
119
+ - lib/eac_rails_remotes/version.rb
120
+ - lib/tasks/eac_rails_remotes.rake
121
+ homepage:
122
+ licenses: []
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubygems_version: 3.1.6
140
+ signing_key:
141
+ specification_version: 4
142
+ summary: Put here de description.
143
+ test_files: []