rankmi-localization 0.1.6
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.
- checksums.yaml +7 -0
- data/README.md +25 -0
- data/Rakefile +40 -0
- data/app/controllers/concerns/country_locale.rb +29 -0
- data/app/models/concerns/countriable.rb +48 -0
- data/app/models/rankmi_localization/application_record.rb +34 -0
- data/app/models/rankmi_localization/country.rb +42 -0
- data/app/models/rankmi_localization/location.rb +95 -0
- data/db/migrate/20241126054133_create_or_update_locations_on_rankmi_localization.rb +85 -0
- data/db/migrate/20241202212837_create_countries_on_rankmi_localization.rb +19 -0
- data/lib/generators/rankmi_localization/install/install_generator.rb +42 -0
- data/lib/generators/rankmi_localization/install/templates/README.md +4 -0
- data/lib/generators/rankmi_localization/install/templates/rankmi_localization_initializer.rb +6 -0
- data/lib/rankmi_localization/configuration.rb +19 -0
- data/lib/rankmi_localization/engine.rb +13 -0
- data/lib/rankmi_localization/migration.rb +21 -0
- data/lib/rankmi_localization/railtie.rb +27 -0
- data/lib/rankmi_localization/version.rb +5 -0
- data/lib/rankmi_localization.rb +29 -0
- data/lib/tasks/auto_annotate_models.rake +58 -0
- data/lib/tasks/populate_countries.rake +19 -0
- data/lib/tasks/run_spec_migrations.rake +15 -0
- data/lib/tasks/spec_migrations.rake +25 -0
- metadata +89 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 788eabef0fae27b076f9824737c577751baa5d8bee4034a0e1ace9d2aecdc18b
|
|
4
|
+
data.tar.gz: '0109095f825a8a2e8bf0f28ec2739b233206ed27a09ba3c8d579cd97a4cf56c5'
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 8cb4ea2088f0317b51ab81f0d1aa791996a77a3c01488313130066f05b1fd1a591f2a8cbe06958d0b9a8825c5f4bdfe5787456732bf8bc69786b1fc4d0299edd
|
|
7
|
+
data.tar.gz: 37091f2194cbe03fa99cb750c2f046c79f97dedf7c823c0a0e7c37e71a9941db268da89e7a7ecff50ab9e2f53bdf7ebfd0ca1190cd4acd7b5382bb1139c40715
|
data/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Step 1:
|
|
2
|
+
|
|
3
|
+
Run `matrix start databases` to create necessary databases to run this project
|
|
4
|
+
|
|
5
|
+
# Step 2:
|
|
6
|
+
|
|
7
|
+
Run `matrix local shell` and then run the following commands
|
|
8
|
+
|
|
9
|
+
```shell
|
|
10
|
+
bundle exec rake db:create
|
|
11
|
+
bundle exec rake db:setup
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
# Step 3:
|
|
15
|
+
|
|
16
|
+
You are all set!!
|
|
17
|
+
|
|
18
|
+
If you want to run specs, feel free to run then using matrix
|
|
19
|
+
`matrix local test`
|
|
20
|
+
|
|
21
|
+
## More info
|
|
22
|
+
|
|
23
|
+
If you create new environment variables and you intend to use them on Github Actions (this project doesn't use Drone, c'mon, everybody is tired of that red ribbon)
|
|
24
|
+
|
|
25
|
+
Then you need to create the variables at the .env.test file too, because GH Actions consume them!
|
data/Rakefile
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'annotate'
|
|
5
|
+
|
|
6
|
+
APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
|
|
7
|
+
load 'rails/tasks/engine.rake'
|
|
8
|
+
load 'rails/tasks/statistics.rake'
|
|
9
|
+
|
|
10
|
+
require 'bundler/gem_tasks'
|
|
11
|
+
require 'rspec/core/rake_task'
|
|
12
|
+
|
|
13
|
+
Dir[File.join(__dir__, 'lib', 'tasks', '*.rake')].each { |file| load file }
|
|
14
|
+
|
|
15
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
16
|
+
|
|
17
|
+
if ENV['RACK_ENV'] == 'development' || ENV['RAILS_ENV'] == 'development'
|
|
18
|
+
require 'rubocop/rake_task'
|
|
19
|
+
RuboCop::RakeTask.new
|
|
20
|
+
task default: %i[spec rubocop]
|
|
21
|
+
else
|
|
22
|
+
task default: %i[spec]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
namespace :db do
|
|
26
|
+
desc 'Run migrations and annotate models for the dummy app'
|
|
27
|
+
task migrate_and_annotate: [:migrate] do
|
|
28
|
+
Dir.chdir('spec/dummy') do
|
|
29
|
+
# Check if there are any model files before running annotate
|
|
30
|
+
model_dir = File.join(Dir.pwd, 'app/models')
|
|
31
|
+
sh 'bundle exec annotate' if Dir.exist?(model_dir) && Dir[File.join(model_dir,
|
|
32
|
+
'**/*.rb')].any?
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Run this task automatically after db:migrate for the gem
|
|
38
|
+
Rake::Task['db:migrate'].enhance do
|
|
39
|
+
Rake::Task['db:migrate_and_annotate'].invoke
|
|
40
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# callback para controlar locale según el country del usuario
|
|
4
|
+
module CountryLocale
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
included do
|
|
7
|
+
around_action :switch_locale
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
COUNTRY_LOCALE = {
|
|
11
|
+
cl: 'es-cl',
|
|
12
|
+
mx: 'es-mx',
|
|
13
|
+
pe: 'es-pe',
|
|
14
|
+
ar: 'es-ar'
|
|
15
|
+
}.with_indifferent_access
|
|
16
|
+
|
|
17
|
+
def switch_locale(&action)
|
|
18
|
+
if current_user&.id
|
|
19
|
+
locale = locale_by_country(current_user&.country&.downcase)
|
|
20
|
+
I18n.with_locale(locale, &action)
|
|
21
|
+
else
|
|
22
|
+
I18n.with_locale('es-cl', &action)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def locale_by_country(country)
|
|
27
|
+
COUNTRY_LOCALE[country] || I18n.default_locale
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# == Schema Information
|
|
4
|
+
#
|
|
5
|
+
# Table name: countries
|
|
6
|
+
#
|
|
7
|
+
# id :bigint not null, primary key
|
|
8
|
+
# code :string(4) not null
|
|
9
|
+
# name :string(255) not null
|
|
10
|
+
# nationality :string(255)
|
|
11
|
+
# created_at :datetime not null
|
|
12
|
+
# updated_at :datetime not null
|
|
13
|
+
#
|
|
14
|
+
# Indexes
|
|
15
|
+
#
|
|
16
|
+
# index_countries_on_code (code) UNIQUE
|
|
17
|
+
# index_countries_on_name (name) UNIQUE
|
|
18
|
+
#
|
|
19
|
+
module Countriable
|
|
20
|
+
extend ActiveSupport::Concern
|
|
21
|
+
|
|
22
|
+
included do
|
|
23
|
+
after_initialize :ensure_countriable_setup
|
|
24
|
+
setup_countriable
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def ensure_countriable_setup
|
|
28
|
+
self.class.setup_countriable unless self.class.reflect_on_association(:country_model)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class_methods do
|
|
32
|
+
def setup_countriable
|
|
33
|
+
foreign_key = column_names.include?('country_code') ? :country_code : :country
|
|
34
|
+
return unless foreign_key.to_s.in?(column_names)
|
|
35
|
+
|
|
36
|
+
belongs_to(:country_model,
|
|
37
|
+
class_name: 'Country',
|
|
38
|
+
optional: true,
|
|
39
|
+
primary_key: :code,
|
|
40
|
+
foreign_key: foreign_key,
|
|
41
|
+
inverse_of: name.demodulize.underscore.pluralize.to_sym)
|
|
42
|
+
|
|
43
|
+
validates(foreign_key,
|
|
44
|
+
inclusion: { in: ::ISO3166::Country.countries.map(&:alpha2) },
|
|
45
|
+
allow_blank: true)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# == Schema Information
|
|
4
|
+
#
|
|
5
|
+
# Table name: countries
|
|
6
|
+
#
|
|
7
|
+
# id :bigint not null, primary key
|
|
8
|
+
# code :string(4) not null
|
|
9
|
+
# name :string(255) not null
|
|
10
|
+
# nationality :string(255)
|
|
11
|
+
# created_at :datetime not null
|
|
12
|
+
# updated_at :datetime not null
|
|
13
|
+
#
|
|
14
|
+
# Indexes
|
|
15
|
+
#
|
|
16
|
+
# index_countries_on_code (code) UNIQUE
|
|
17
|
+
# index_countries_on_name (name) UNIQUE
|
|
18
|
+
#
|
|
19
|
+
module RankmiLocalization
|
|
20
|
+
class ApplicationRecord < ActiveRecord::Base
|
|
21
|
+
self.abstract_class = true
|
|
22
|
+
|
|
23
|
+
# establish_connection(:rankmi_localization)
|
|
24
|
+
# for some reason, command above doesn't work, we will use the command below for now
|
|
25
|
+
establish_connection Rails.configuration.database_configuration[Rails.env]['rankmi_localization']
|
|
26
|
+
connects_to database: { writing: :rankmi_localization, reading: :rankmi_localization }
|
|
27
|
+
# Override table name inference to exclude the module name
|
|
28
|
+
def self.table_name
|
|
29
|
+
return super if abstract_class?
|
|
30
|
+
|
|
31
|
+
@table_name ||= name.demodulize.underscore.pluralize
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# == Schema Information
|
|
4
|
+
#
|
|
5
|
+
# Table name: countries
|
|
6
|
+
#
|
|
7
|
+
# id :bigint not null, primary key
|
|
8
|
+
# code :string(4) not null
|
|
9
|
+
# name :string(255) not null
|
|
10
|
+
# nationality :string(255)
|
|
11
|
+
# created_at :datetime not null
|
|
12
|
+
# updated_at :datetime not null
|
|
13
|
+
#
|
|
14
|
+
# Indexes
|
|
15
|
+
#
|
|
16
|
+
# index_countries_on_code (code) UNIQUE
|
|
17
|
+
# index_countries_on_name (name) UNIQUE
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
module RankmiLocalization
|
|
21
|
+
class Country < RankmiLocalization::ApplicationRecord
|
|
22
|
+
# Validations
|
|
23
|
+
validates :code,
|
|
24
|
+
presence: true,
|
|
25
|
+
uniqueness: true,
|
|
26
|
+
length: { is: 2 },
|
|
27
|
+
format: { with: /\A[A-Z]{2}\z/ }
|
|
28
|
+
validates :name,
|
|
29
|
+
presence: true,
|
|
30
|
+
length: { maximum: 255 }
|
|
31
|
+
validates :code,
|
|
32
|
+
inclusion: { in: ::ISO3166::Country.countries.map(&:alpha2) },
|
|
33
|
+
allow_blank: true
|
|
34
|
+
|
|
35
|
+
# Callbacks
|
|
36
|
+
before_validation { code.upcase! if code.present? }
|
|
37
|
+
|
|
38
|
+
def self.[](code)
|
|
39
|
+
::ISO3166::Country[code]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# == Schema Information
|
|
4
|
+
#
|
|
5
|
+
# Table name: countries
|
|
6
|
+
#
|
|
7
|
+
# id :bigint not null, primary key
|
|
8
|
+
# code :string(4) not null
|
|
9
|
+
# name :string(255) not null
|
|
10
|
+
# nationality :string(255)
|
|
11
|
+
# created_at :datetime not null
|
|
12
|
+
# updated_at :datetime not null
|
|
13
|
+
#
|
|
14
|
+
# Indexes
|
|
15
|
+
#
|
|
16
|
+
# index_countries_on_code (code) UNIQUE
|
|
17
|
+
# index_countries_on_name (name) UNIQUE
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
module RankmiLocalization
|
|
21
|
+
class Location < RankmiLocalization::ApplicationRecord
|
|
22
|
+
# Associations
|
|
23
|
+
belongs_to :parent, class_name: 'Location', optional: true, inverse_of: :children
|
|
24
|
+
has_many :children,
|
|
25
|
+
class_name: 'Location',
|
|
26
|
+
foreign_key: :parent_id,
|
|
27
|
+
inverse_of: :parent,
|
|
28
|
+
dependent: :destroy
|
|
29
|
+
|
|
30
|
+
# Validations
|
|
31
|
+
validates :name, presence: true
|
|
32
|
+
|
|
33
|
+
# Constants
|
|
34
|
+
DIVISIONS = {
|
|
35
|
+
ar: { pais: 0, provincia: 1, departamento: 2 },
|
|
36
|
+
cl: { pais: 0, region: 1, provincia: 2, comuna: 3 },
|
|
37
|
+
pe: { pais: 0, departamento: 1, provincia: 2, distrito: 3 },
|
|
38
|
+
mx: { pais: 0, estado: 1, municipio: 2, ciudad: 3, colonia: 4 }
|
|
39
|
+
}.freeze
|
|
40
|
+
|
|
41
|
+
COUNTRIES = {
|
|
42
|
+
ar: 'Argentina',
|
|
43
|
+
cl: 'Chile',
|
|
44
|
+
pe: 'Perú',
|
|
45
|
+
mx: 'México'
|
|
46
|
+
}.freeze
|
|
47
|
+
|
|
48
|
+
# Scopes
|
|
49
|
+
scope :divisions_for,
|
|
50
|
+
lambda { |division, country: :cl, code: nil|
|
|
51
|
+
unscoped do
|
|
52
|
+
country_root = Location.country(country)
|
|
53
|
+
level = DIVISIONS.dig(country, division)
|
|
54
|
+
return Location.none unless country || level
|
|
55
|
+
|
|
56
|
+
tree = all.preload(children: [children: [children: :children]])
|
|
57
|
+
.where("locations.path LIKE '?/%' AND locations.deep_level = ?",
|
|
58
|
+
country_root.id,
|
|
59
|
+
level)
|
|
60
|
+
|
|
61
|
+
if code.present?
|
|
62
|
+
nodes = tree.where(code: code)
|
|
63
|
+
node = nodes[0]
|
|
64
|
+
|
|
65
|
+
parent_node = nodes
|
|
66
|
+
while node&.parent.present?
|
|
67
|
+
nodes = parent_node
|
|
68
|
+
parent_node = {
|
|
69
|
+
id: node.parent.id,
|
|
70
|
+
name: node.parent.name,
|
|
71
|
+
children: nodes
|
|
72
|
+
}
|
|
73
|
+
node = node.parent
|
|
74
|
+
end
|
|
75
|
+
tree = parent_node
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
tree
|
|
79
|
+
end
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Class methods
|
|
83
|
+
def self.country(country)
|
|
84
|
+
Rails.cache.fetch("Location::Country::#{country.upcase}") do
|
|
85
|
+
find_by(name: COUNTRIES[country.downcase.to_sym],
|
|
86
|
+
deep_level: deep_level_by_country(country, :pais),
|
|
87
|
+
parent_id: nil)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def self.deep_level_by_country(country, division)
|
|
92
|
+
DIVISIONS.dig(country.downcase.to_sym, division.downcase.to_sym)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
class CreateOrUpdateLocationsOnRankmiLocalization < RankmiLocalization::Migration
|
|
5
|
+
def up
|
|
6
|
+
if table_exists?(:locations)
|
|
7
|
+
add_column(:locations, :code, :string) unless column_exists?(:locations, :code)
|
|
8
|
+
add_column(:locations, :deep_level, :integer) unless column_exists?(:locations, :deep_level)
|
|
9
|
+
unless column_exists?(:locations,
|
|
10
|
+
:extra_vacation_days)
|
|
11
|
+
add_column(:locations,
|
|
12
|
+
:extra_vacation_days,
|
|
13
|
+
:decimal,
|
|
14
|
+
default: '0.0')
|
|
15
|
+
end
|
|
16
|
+
unless column_exists?(:locations,
|
|
17
|
+
:extreme_zone)
|
|
18
|
+
add_column(:locations,
|
|
19
|
+
:extreme_zone,
|
|
20
|
+
:boolean,
|
|
21
|
+
null: false,
|
|
22
|
+
default: false)
|
|
23
|
+
end
|
|
24
|
+
add_column(:locations, :lre_code, :string) unless column_exists?(:locations, :lre_code)
|
|
25
|
+
add_column(:locations, :name, :string, null: false, default: '') unless column_exists?(
|
|
26
|
+
:locations, :name
|
|
27
|
+
)
|
|
28
|
+
add_column(:locations, :parent_id, :bigint) unless column_exists?(:locations, :parent_id)
|
|
29
|
+
add_column(:locations, :path, :string) unless column_exists?(:locations, :path)
|
|
30
|
+
unless column_exists?(:locations, :created_at)
|
|
31
|
+
add_column(:locations,
|
|
32
|
+
:created_at,
|
|
33
|
+
:datetime,
|
|
34
|
+
precision: 6,
|
|
35
|
+
null: false,
|
|
36
|
+
default: lambda {
|
|
37
|
+
'CURRENT_TIMESTAMP'
|
|
38
|
+
})
|
|
39
|
+
end
|
|
40
|
+
unless column_exists?(:locations, :updated_at)
|
|
41
|
+
add_column(:locations,
|
|
42
|
+
:updated_at,
|
|
43
|
+
:datetime,
|
|
44
|
+
precision: 6,
|
|
45
|
+
null: false,
|
|
46
|
+
default: lambda {
|
|
47
|
+
'CURRENT_TIMESTAMP'
|
|
48
|
+
})
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
add_index(:locations, :parent_id, name: 'index_locations_on_parent_id') unless index_exists?(
|
|
52
|
+
:locations,
|
|
53
|
+
:parent_id,
|
|
54
|
+
name: 'index_locations_on_parent_id'
|
|
55
|
+
)
|
|
56
|
+
else
|
|
57
|
+
create_table(:locations) do |t|
|
|
58
|
+
t.string(:code)
|
|
59
|
+
t.datetime(:created_at, precision: 6, null: false, default: -> { 'CURRENT_TIMESTAMP' })
|
|
60
|
+
t.integer(:deep_level)
|
|
61
|
+
t.decimal(:extra_vacation_days, null: false, default: '0.0')
|
|
62
|
+
t.boolean(:extreme_zone, null: false, default: false)
|
|
63
|
+
t.string(:lre_code)
|
|
64
|
+
t.string(:name, null: false, default: '')
|
|
65
|
+
t.bigint(:parent_id)
|
|
66
|
+
t.string(:path)
|
|
67
|
+
t.datetime(:updated_at, precision: 6, null: false, default: -> { 'CURRENT_TIMESTAMP' })
|
|
68
|
+
t.index(:parent_id, name: 'index_locations_on_parent_id')
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def down
|
|
74
|
+
return unless table_exists?(:locations)
|
|
75
|
+
|
|
76
|
+
remove_index(:locations, name: 'index_locations_on_parent_id') if index_exists?(
|
|
77
|
+
:locations,
|
|
78
|
+
:parent_id,
|
|
79
|
+
name: 'index_locations_on_parent_id'
|
|
80
|
+
)
|
|
81
|
+
drop_table(:locations)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateCountriesOnRankmiLocalization < RankmiLocalization::Migration
|
|
4
|
+
def up
|
|
5
|
+
create_table(:countries) do |t|
|
|
6
|
+
t.string(:code, null: false, limit: 4)
|
|
7
|
+
t.string(:name, null: false, limit: 255)
|
|
8
|
+
t.string(:nationality, limit: 255)
|
|
9
|
+
t.timestamps
|
|
10
|
+
|
|
11
|
+
t.index(:code, unique: true)
|
|
12
|
+
t.index(:name, unique: true)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def down
|
|
17
|
+
drop_table(:countries)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
|
|
5
|
+
module RankmiLocalization
|
|
6
|
+
module Generators
|
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
|
8
|
+
source_root File.expand_path('templates', __dir__)
|
|
9
|
+
|
|
10
|
+
def copy_initializer
|
|
11
|
+
template('rankmi_localization_initializer.rb', 'config/initializers/rankmi_localization.rb')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# def copy_migrations_to_spec_folder
|
|
15
|
+
# migrations_path = File.expand_path('../../../../db/migrate', __dir__)
|
|
16
|
+
# destination = 'spec/db_setup'
|
|
17
|
+
|
|
18
|
+
# Dir.glob("#{migrations_path}/*.rb").each do |migration|
|
|
19
|
+
# migration_name = migration.split('_', 4).last # Extract migration name without timestamp
|
|
20
|
+
# timestamp = Time.zone.now.strftime('%Y%m%d%H%M%S')
|
|
21
|
+
# new_name = "#{timestamp}_#{migration_name}"
|
|
22
|
+
|
|
23
|
+
# copy_file(migration, File.join(destination, new_name))
|
|
24
|
+
# sleep(1) # Ensure unique timestamp for each file
|
|
25
|
+
# end
|
|
26
|
+
# end
|
|
27
|
+
|
|
28
|
+
def copy_migrations_to_spec_folder
|
|
29
|
+
migrations_path = File.expand_path('../../../../db/migrate', __dir__)
|
|
30
|
+
destination = 'spec/db_setup'
|
|
31
|
+
|
|
32
|
+
Dir.glob("#{migrations_path}/*.rb").each do |migration|
|
|
33
|
+
copy_file(migration, File.join(destination, File.basename(migration)))
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def install_notes
|
|
38
|
+
readme('README.md')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RankmiLocalization
|
|
4
|
+
class Configuration
|
|
5
|
+
attr_reader :sync_tables
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
self.sync_tables = true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def sync_tables=(value)
|
|
12
|
+
@sync_tables = Rails.env.production? || value
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def validate!
|
|
16
|
+
true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails'
|
|
4
|
+
|
|
5
|
+
module RankmiLocalization
|
|
6
|
+
class Engine < ::Rails::Engine
|
|
7
|
+
isolate_namespace RankmiLocalization
|
|
8
|
+
|
|
9
|
+
# initializer 'rankmi_localization.load_migrations' do
|
|
10
|
+
# Rails.application.config.paths['db/migrate'] << root.join('db/migrate').to_s
|
|
11
|
+
# end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_record'
|
|
4
|
+
|
|
5
|
+
module RankmiLocalization
|
|
6
|
+
class Migration < ActiveRecord::Migration[6.0]
|
|
7
|
+
def exec_migration(conn, direction)
|
|
8
|
+
return unless using_gem_database?
|
|
9
|
+
|
|
10
|
+
super
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def using_gem_database?
|
|
16
|
+
current_database = ActiveRecord::Base.connection_config[:database]
|
|
17
|
+
target_database = Rails.application.config.database_configuration[Rails.env]['rankmi_localization']['database']
|
|
18
|
+
current_database == target_database
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RankmiLocalization
|
|
4
|
+
class Railtie < ::Rails::Railtie
|
|
5
|
+
railtie_name :rankmi_localization
|
|
6
|
+
|
|
7
|
+
rake_tasks do
|
|
8
|
+
Dir.glob("#{File.expand_path(__dir__)}/lib/tasks/**/*.rake").each do |f|
|
|
9
|
+
next if File.basename(f) == 'auto_annotate_models.rake'
|
|
10
|
+
|
|
11
|
+
load f
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Define aliases after Rails initialization
|
|
16
|
+
config.to_prepare do
|
|
17
|
+
unless Object.const_defined?(:Country)
|
|
18
|
+
Object.const_set(:Country,
|
|
19
|
+
RankmiLocalization::Country)
|
|
20
|
+
end
|
|
21
|
+
unless Object.const_defined?(:Location)
|
|
22
|
+
Object.const_set(:Location,
|
|
23
|
+
RankmiLocalization::Location)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rankmi_localization/engine'
|
|
4
|
+
require 'rankmi_localization/configuration'
|
|
5
|
+
require 'rankmi_localization/version'
|
|
6
|
+
require 'rankmi_localization/migration'
|
|
7
|
+
require 'rankmi_localization/railtie' if defined?(Rails)
|
|
8
|
+
|
|
9
|
+
module RankmiLocalization
|
|
10
|
+
class Error < StandardError; end
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
def configure
|
|
14
|
+
Rails.logger.debug { "RankmiLocalization: Configuring with #{block_given? ? 'block' : 'no block'}" }
|
|
15
|
+
yield(configuration) if block_given?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def reset
|
|
19
|
+
Rails.logger.debug('RankmiLocalization: Resetting configuration')
|
|
20
|
+
@configuration = nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def configuration
|
|
24
|
+
@configuration ||= Configuration.new
|
|
25
|
+
Rails.logger.debug { "RankmiLocalization: Current configuration -> #{@configuration.inspect}" }
|
|
26
|
+
@configuration
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
if Rails.env.development? || Rails.env.test?
|
|
4
|
+
require 'annotate'
|
|
5
|
+
task set_annotation_options: :environment do
|
|
6
|
+
Annotate.set_defaults(
|
|
7
|
+
'active_admin' => 'false',
|
|
8
|
+
'additional_file_patterns' => ['app/models/**/*.rb'], # Include all nested files
|
|
9
|
+
'routes' => 'false',
|
|
10
|
+
'models' => 'true',
|
|
11
|
+
'position_in_routes' => 'before',
|
|
12
|
+
'position_in_class' => 'before',
|
|
13
|
+
'position_in_test' => 'before',
|
|
14
|
+
'position_in_fixture' => 'before',
|
|
15
|
+
'position_in_factory' => 'before',
|
|
16
|
+
'position_in_serializer' => 'before',
|
|
17
|
+
'show_foreign_keys' => 'true',
|
|
18
|
+
'show_complete_foreign_keys' => 'false',
|
|
19
|
+
'show_indexes' => 'true',
|
|
20
|
+
'simple_indexes' => 'false',
|
|
21
|
+
'model_dir' => 'app/models',
|
|
22
|
+
'root_dir' => '',
|
|
23
|
+
'include_version' => 'false',
|
|
24
|
+
'require' => '',
|
|
25
|
+
'exclude_models' => 'true',
|
|
26
|
+
'exclude_tests' => 'false',
|
|
27
|
+
'exclude_fixtures' => 'false',
|
|
28
|
+
'exclude_factories' => 'false',
|
|
29
|
+
'exclude_serializers' => 'false',
|
|
30
|
+
'exclude_scaffolds' => 'true',
|
|
31
|
+
'exclude_controllers' => 'true',
|
|
32
|
+
'exclude_helpers' => 'true',
|
|
33
|
+
'exclude_sti_subclasses' => 'false',
|
|
34
|
+
'ignore_model_sub_dir' => 'false',
|
|
35
|
+
'ignore_columns' => nil,
|
|
36
|
+
'ignore_routes' => nil,
|
|
37
|
+
'ignore_unknown_models' => 'false',
|
|
38
|
+
'hide_limit_column_types' => 'integer,bigint,boolean',
|
|
39
|
+
'hide_default_column_types' => 'json,jsonb,hstore',
|
|
40
|
+
'skip_on_db_migrate' => 'false',
|
|
41
|
+
'format_bare' => 'true',
|
|
42
|
+
'format_rdoc' => 'false',
|
|
43
|
+
'format_yard' => 'false',
|
|
44
|
+
'format_markdown' => 'false',
|
|
45
|
+
'sort' => 'false',
|
|
46
|
+
'force' => 'false',
|
|
47
|
+
'frozen' => 'false',
|
|
48
|
+
'classified_sort' => 'true',
|
|
49
|
+
'trace' => 'false',
|
|
50
|
+
'wrapper_open' => nil,
|
|
51
|
+
'wrapper_close' => nil,
|
|
52
|
+
'with_comment' => 'true',
|
|
53
|
+
'exclude' => ['app/models/concerns/**/*']
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
Annotate.load_tasks
|
|
58
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :db do
|
|
4
|
+
desc 'Populate countries table with all countries in the world'
|
|
5
|
+
task populate_countries: :environment do
|
|
6
|
+
countries_data = ISO3166::Country.all
|
|
7
|
+
|
|
8
|
+
countries_data.each do |country|
|
|
9
|
+
country_record = Country.find_or_initialize_by(code: country.alpha2)
|
|
10
|
+
country_record.assign_attributes(
|
|
11
|
+
name: country.name,
|
|
12
|
+
nationality: country.nationality || 'N/A'
|
|
13
|
+
)
|
|
14
|
+
country_record.save
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
puts 'Countries table has been successfully populated!' unless Rails.env.test?
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :db do
|
|
4
|
+
desc 'Run migrations from spec/db_setup before tests'
|
|
5
|
+
task spec_migrate: :environment do
|
|
6
|
+
migrations_path = Rails.root.join('spec/db_setup')
|
|
7
|
+
puts("Running migrations from: #{migrations_path}")
|
|
8
|
+
|
|
9
|
+
ActiveRecord::MigrationContext.new(migrations_path.to_s, ActiveRecord::SchemaMigration).migrate
|
|
10
|
+
puts("Migrations successfully applied from #{migrations_path}")
|
|
11
|
+
rescue StandardError => e
|
|
12
|
+
puts("Error while running migrations: #{e.message}")
|
|
13
|
+
exit(1)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :db do
|
|
4
|
+
desc 'Create and migrate rankmi_localization test database'
|
|
5
|
+
task spec_rankmi_localization: :environment do
|
|
6
|
+
if Rails.env.test?
|
|
7
|
+
# Create and migrate primary database
|
|
8
|
+
ActiveRecord::Base.establish_connection(Rails.configuration.database_configuration['test']['primary'])
|
|
9
|
+
ActiveRecord::Tasks::DatabaseTasks.create_current
|
|
10
|
+
ActiveRecord::MigrationContext.new('db/migrate', ActiveRecord::SchemaMigration).migrate
|
|
11
|
+
|
|
12
|
+
# Create and migrate payroll database
|
|
13
|
+
ActiveRecord::Base.establish_connection(Rails.configuration.database_configuration['test']['payroll'])
|
|
14
|
+
ActiveRecord::Tasks::DatabaseTasks.create_current
|
|
15
|
+
ActiveRecord::MigrationContext.new('db/migrate', ActiveRecord::SchemaMigration).migrate
|
|
16
|
+
|
|
17
|
+
# Create and migrate rankmi_localization database
|
|
18
|
+
ActiveRecord::Base.establish_connection(Rails.configuration.database_configuration['test']['rankmi_localization'])
|
|
19
|
+
ActiveRecord::Tasks::DatabaseTasks.create(
|
|
20
|
+
Rails.configuration.database_configuration['test']['rankmi_localization']
|
|
21
|
+
)
|
|
22
|
+
ActiveRecord::MigrationContext.new('db/migrate', ActiveRecord::SchemaMigration).migrate
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rankmi-localization
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.6
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Pedro Naponoceno
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2025-03-27 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rails
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 6.0.3.3
|
|
20
|
+
- - "<"
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: '6.2'
|
|
23
|
+
type: :runtime
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - ">="
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: 6.0.3.3
|
|
30
|
+
- - "<"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '6.2'
|
|
33
|
+
description: One DB to find them
|
|
34
|
+
email:
|
|
35
|
+
- pedro.naponoceno@rankmi.com
|
|
36
|
+
executables: []
|
|
37
|
+
extensions: []
|
|
38
|
+
extra_rdoc_files: []
|
|
39
|
+
files:
|
|
40
|
+
- README.md
|
|
41
|
+
- Rakefile
|
|
42
|
+
- app/controllers/concerns/country_locale.rb
|
|
43
|
+
- app/models/concerns/countriable.rb
|
|
44
|
+
- app/models/rankmi_localization/application_record.rb
|
|
45
|
+
- app/models/rankmi_localization/country.rb
|
|
46
|
+
- app/models/rankmi_localization/location.rb
|
|
47
|
+
- db/migrate/20241126054133_create_or_update_locations_on_rankmi_localization.rb
|
|
48
|
+
- db/migrate/20241202212837_create_countries_on_rankmi_localization.rb
|
|
49
|
+
- lib/generators/rankmi_localization/install/install_generator.rb
|
|
50
|
+
- lib/generators/rankmi_localization/install/templates/README.md
|
|
51
|
+
- lib/generators/rankmi_localization/install/templates/rankmi_localization_initializer.rb
|
|
52
|
+
- lib/rankmi_localization.rb
|
|
53
|
+
- lib/rankmi_localization/configuration.rb
|
|
54
|
+
- lib/rankmi_localization/engine.rb
|
|
55
|
+
- lib/rankmi_localization/migration.rb
|
|
56
|
+
- lib/rankmi_localization/railtie.rb
|
|
57
|
+
- lib/rankmi_localization/version.rb
|
|
58
|
+
- lib/tasks/auto_annotate_models.rake
|
|
59
|
+
- lib/tasks/populate_countries.rake
|
|
60
|
+
- lib/tasks/run_spec_migrations.rake
|
|
61
|
+
- lib/tasks/spec_migrations.rake
|
|
62
|
+
homepage: https://github.com/
|
|
63
|
+
licenses:
|
|
64
|
+
- MIT
|
|
65
|
+
metadata:
|
|
66
|
+
homepage_uri: https://github.com/
|
|
67
|
+
source_code_uri: https://github.com/
|
|
68
|
+
changelog_uri: https://github.com//blob/master/CHANGELOG.md
|
|
69
|
+
rubygems_mfa_required: 'true'
|
|
70
|
+
post_install_message:
|
|
71
|
+
rdoc_options: []
|
|
72
|
+
require_paths:
|
|
73
|
+
- lib
|
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
|
+
requirements:
|
|
76
|
+
- - ">="
|
|
77
|
+
- !ruby/object:Gem::Version
|
|
78
|
+
version: 2.7.8
|
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - ">="
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
version: '0'
|
|
84
|
+
requirements: []
|
|
85
|
+
rubygems_version: 3.1.6
|
|
86
|
+
signing_key:
|
|
87
|
+
specification_version: 4
|
|
88
|
+
summary: One DB to rule them all
|
|
89
|
+
test_files: []
|