feat: add countries and regions management

- Implement Country and Region models
- Establish relationships between City, Country, and Region
- Update ActiveAdmin setup for managing countries and regions
- Add localization support for cities and countries in multiple languages
- Create necessary migrations to support the new schema

This update allows for better categorization of cities under their respective countries and regions, enhancing geographical structure and support for multilingual features.
This commit is contained in:
songtianlun 2025-01-21 18:27:26 +08:00
parent ac199af963
commit ebaf7a3f34
47 changed files with 1608 additions and 13 deletions

View File

@ -10,7 +10,7 @@ ActiveAdmin.register City do
# #
# Uncomment all parameters which should be permitted for assignment # Uncomment all parameters which should be permitted for assignment
# #
permit_params :name, :country, :latitude, :longitude, :active, :priority, :timezone, :region, :last_weather_fetch, :last_image_generation, :slug permit_params :name, :country_id, :latitude, :longitude, :active, :priority, :timezone, :last_weather_fetch, :last_image_generation, :slug
# #
# or # or
# #
@ -24,11 +24,13 @@ ActiveAdmin.register City do
selectable_column selectable_column
id_column id_column
column :name column :name
column :slug column :country
column :region do |city|
city.region
end
column :latitude column :latitude
column :longitude column :longitude
column :active column :active
column :created_at
actions actions
end end
@ -39,7 +41,6 @@ ActiveAdmin.register City do
f.inputs do f.inputs do
f.input :active f.input :active
f.input :name f.input :name
f.input :country, as: :String
f.input :latitude f.input :latitude
f.input :longitude f.input :longitude
f.input :priority f.input :priority

36
app/admin/countries.rb Normal file
View File

@ -0,0 +1,36 @@
ActiveAdmin.register Country do
# See permitted parameters documentation:
# https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
#
# Uncomment all parameters which should be permitted for assignment
#
permit_params :name, :code, :region_id
#
# or
#
# permit_params do
# permitted = [:name, :code, :slug, :region_id]
# permitted << :other if params[:action] == 'create' && current_user.admin?
# permitted
# end
index do
selectable_column
id_column
column :name
column :code
column :region
column :cities_count do |country|
country.cities.count
end
actions
end
form do |f|
f.inputs do
f.input :region
f.input :name
f.input :code
end
f.actions
end
end

29
app/admin/regions.rb Normal file
View File

@ -0,0 +1,29 @@
ActiveAdmin.register Region do
# See permitted parameters documentation:
# https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
#
# Uncomment all parameters which should be permitted for assignment
#
permit_params :name, :code
#
# or
#
# permit_params do
# permitted = [:name, :code, :slug]
# permitted << :other if params[:action] == 'create' && current_user.admin?
# permitted
# end
index do
selectable_column
id_column
column :name
column :code
column :countries_count do |region|
region.countries.count
end
column :cities_count do |region|
region.cities.count
end
actions
end
end

View File

@ -1,4 +1,11 @@
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has. # Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
allow_browser versions: :modern allow_browser versions: :modern
before_action :set_locale
private
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
end end

View File

@ -1,6 +1,7 @@
class City < ApplicationRecord class City < ApplicationRecord
extend FriendlyId extend FriendlyId
friendly_id :name, use: :slugged friendly_id :name, use: :slugged
belongs_to :country
has_many :weather_arts, dependent: :destroy has_many :weather_arts, dependent: :destroy
@ -8,6 +9,20 @@ class City < ApplicationRecord
validates :latitude, presence: true validates :latitude, presence: true
validates :longitude, presence: true validates :longitude, presence: true
delegate :region, to: :country
def to_s
name
end
def localized_name
I18n.t("cities.#{name.parameterize.underscore}")
end
def full_name
"#{name}, #{country}"
end
def should_generate_new_friendly_id? def should_generate_new_friendly_id?
name_changed? || super name_changed? || super
end end

26
app/models/country.rb Normal file
View File

@ -0,0 +1,26 @@
class Country < ApplicationRecord
extend FriendlyId
friendly_id :name, use: :slugged
belongs_to :region
has_many :cities, dependent: :restrict_with_error
validates :name, presence: true
validates :code, presence: true, uniqueness: true
def to_s
name
end
def localized_name
I18n.t("countries.#{code}")
end
def self.ransackable_attributes(auth_object = nil)
[ "code", "created_at", "id", "id_value", "name", "region_id", "slug", "updated_at" ]
end
def self.ransackable_associations(auth_object = nil)
[ "cities", "region" ]
end
end

28
app/models/region.rb Normal file
View File

@ -0,0 +1,28 @@
class Region < ApplicationRecord
extend FriendlyId
friendly_id :name, use: :slugged
has_many :countries, dependent: :restrict_with_error
has_many :cities, through: :countries
validates :name, presence: true
validates :code, presence: true, uniqueness: true
def to_s
name
end
def localized_name
I18n.t("regions.#{code}")
end
# 模型中允许被搜索的关联
def self.ransackable_associations(auth_object = nil)
[ "countries", "cities" ]
end
# 允许被搜索的属性列表
def self.ransackable_attributes(auth_object = nil)
[ "code", "created_at", "id", "id_value", "name", "slug", "updated_at" ]
end
end

View File

@ -0,0 +1,118 @@
en:
cities:
# Australia
sydney: 'Sydney'
melbourne: 'Melbourne'
# Bangladesh
dhaka: 'Dhaka'
# Brazil
rio_de_janeiro: 'Rio de Janeiro'
# Canada
toronto: 'Toronto'
# China
shanghai: 'Shanghai'
beijing: 'Beijing'
shenzhen: 'Shenzhen'
guangzhou: 'Guangzhou'
chengdu: 'Chengdu'
tianjin: 'Tianjin'
wuhan: 'Wuhan'
dongguan: 'Dongguan'
chongqing: 'Chongqing'
xian: "Xi'an"
hangzhou: 'Hangzhou'
foshan: 'Foshan'
nanjing: 'Nanjing'
hong_kong: 'Hong Kong'
shenyang: 'Shenyang'
zhengzhou: 'Zhengzhou'
qingdao: 'Qingdao'
suzhou: 'Suzhou'
changsha: 'Changsha'
jinan: 'Jinan'
kunming: 'Kunming'
harbin: 'Harbin'
shijiazhuang: 'Shijiazhuang'
hefei: 'Hefei'
dalian: 'Dalian'
xiamen: 'Xiamen'
nanning: 'Nanning'
changchun: 'Changchun'
taiyuan: 'Taiyuan'
new_taipei_city: 'New Taipei City'
guiyang: 'Guiyang'
wuxi: 'Wuxi'
shantou: 'Shantou'
urumqi: 'Ürümqi'
zhongshan: 'Zhongshan'
ningbo: 'Ningbo'
fuzhou: 'Fuzhou'
nanchang: 'Nanchang'
# Democratic Republic of the Congo
kinshasa: 'Kinshasa'
# Egypt
alexandria: 'Alexandria'
# France
paris: 'Paris'
# Germany
frankfurt: 'Frankfurt'
berlin: 'Berlin'
# India
mumbai: 'Mumbai'
bengaluru: 'Bengaluru'
# Japan
tokyo: 'Tokyo'
yokohama: 'Yokohama'
# Mexico
mexico_city: 'Mexico City'
# Nigeria
lagos: 'Lagos'
# Pakistan
lahore: 'Lahore'
# Russia
moscow: 'Moscow'
sankt_petersburg: 'Sankt Petersburg'
# Saudi Arabia
riyadh: 'Riyadh'
# Singapore
singapore: 'Singapore'
# South Korea
seoul: 'Seoul'
# Thailand
bangkok: 'Bangkok'
# Turkey
istanbul: 'İstanbul'
ankara: 'Ankara'
# United Kingdom
london: 'London'
# United States
san_francisco: 'San Francisco'
chicago: 'Chicago'
new_york_city: 'New York City'
los_angeles: 'Los Angeles'
# Vietnam
ho_chi_minh_city: 'Ho Chi Minh City'
hanoi: 'Hanoi'

View File

@ -0,0 +1,118 @@
zh-CN:
cities:
# Australia
sydney: '悉尼'
melbourne: '墨尔本'
# Bangladesh
dhaka: '达卡'
# Brazil
rio_de_janeiro: '里约热内卢'
# Canada
toronto: '多伦多'
# China
shanghai: '上海'
beijing: '北京'
shenzhen: '深圳'
guangzhou: '广州'
chengdu: '成都'
tianjin: '天津'
wuhan: '武汉'
dongguan: '东莞'
chongqing: '重庆'
xian: '西安'
hangzhou: '杭州'
foshan: '佛山'
nanjing: '南京'
hong_kong: '香港'
shenyang: '沈阳'
zhengzhou: '郑州'
qingdao: '青岛'
suzhou: '苏州'
changsha: '长沙'
jinan: '济南'
kunming: '昆明'
harbin: '哈尔滨'
shijiazhuang: '石家庄'
hefei: '合肥'
dalian: '大连'
xiamen: '厦门'
nanning: '南宁'
changchun: '长春'
taiyuan: '太原'
new_taipei_city: '新北市'
guiyang: '贵阳'
wuxi: '无锡'
shantou: '汕头'
urumqi: '乌鲁木齐'
zhongshan: '中山'
ningbo: '宁波'
fuzhou: '福州'
nanchang: '南昌'
# Democratic Republic of the Congo
kinshasa: '金沙萨'
# Egypt
alexandria: '亚历山大'
# France
paris: '巴黎'
# Germany
frankfurt: '法兰克福'
berlin: '柏林'
# India
mumbai: '孟买'
bengaluru: '班加罗尔'
# Japan
tokyo: '东京'
yokohama: '横滨'
# Mexico
mexico_city: '墨西哥城'
# Nigeria
lagos: '拉各斯'
# Pakistan
lahore: '拉合尔'
# Russia
moscow: '莫斯科'
sankt_petersburg: '圣彼得堡'
# Saudi Arabia
riyadh: '利雅得'
# Singapore
singapore: '新加坡'
# South Korea
seoul: '首尔'
# Thailand
bangkok: '曼谷'
# Turkey
istanbul: '伊斯坦布尔'
ankara: '安卡拉'
# United Kingdom
london: '伦敦'
# United States
san_francisco: '旧金山'
chicago: '芝加哥'
new_york_city: '纽约'
los_angeles: '洛杉矶'
# Vietnam
ho_chi_minh_city: '胡志明市'
hanoi: '河内'

View File

@ -0,0 +1,55 @@
en:
countries:
# East Asia
CN: 'China'
JP: 'Japan'
KR: 'South Korea'
TW: 'Taiwan'
HK: 'Hong Kong'
# South Asia
IN: 'India'
PK: 'Pakistan'
BD: 'Bangladesh'
# Southeast Asia
ID: 'Indonesia'
VN: 'Vietnam'
TH: 'Thailand'
MM: 'Myanmar'
SG: 'Singapore'
# Middle East
TR: 'Turkey'
IR: 'Iran'
SA: 'Saudi Arabia'
IQ: 'Iraq'
# Africa
NG: 'Nigeria'
EG: 'Egypt'
CD: 'Democratic Republic of the Congo'
TZ: 'Tanzania'
ZA: 'South Africa'
KE: 'Kenya'
AO: 'Angola'
ML: 'Mali'
CI: 'Ivory Coast'
# Europe
RU: 'Russia'
GB: 'United Kingdom'
DE: 'Germany'
# North America
US: 'United States'
MX: 'Mexico'
# South America
BR: 'Brazil'
PE: 'Peru'
CO: 'Colombia'
CL: 'Chile'
# Oceania
AU: 'Australia'

View File

@ -0,0 +1,55 @@
zh-CN:
countries:
# East Asia
CN: '中国'
JP: '日本'
KR: '韩国'
TW: '台湾'
HK: '香港'
# South Asia
IN: '印度'
PK: '巴基斯坦'
BD: '孟加拉国'
# Southeast Asia
ID: '印度尼西亚'
VN: '越南'
TH: '泰国'
MM: '缅甸'
SG: '新加坡'
# Middle East
TR: '土耳其'
IR: '伊朗'
SA: '沙特阿拉伯'
IQ: '伊拉克'
# Africa
NG: '尼日利亚'
EG: '埃及'
CD: '刚果民主共和国'
TZ: '坦桑尼亚'
ZA: '南非'
KE: '肯尼亚'
AO: '安哥拉'
ML: '马里'
CI: '科特迪瓦'
# Europe
RU: '俄罗斯'
GB: '英国'
DE: '德国'
# North America
US: '美国'
MX: '墨西哥'
# South America
BR: '巴西'
PE: '秘鲁'
CO: '哥伦比亚'
CL: '智利'
# Oceania
AU: '澳大利亚'

View File

@ -0,0 +1,15 @@
en:
regions:
AS: 'Asia'
SA: 'South Asia'
SEA: 'Southeast Asia'
EA: 'East Asia'
ME: 'Middle East'
AF: 'Africa'
NA: 'North Africa'
SSA: 'Sub-Saharan Africa'
EU: 'Europe'
NAM: 'North America'
SAM: 'South America'
CAM: 'Central America'
OC: 'Oceania'

View File

@ -0,0 +1,15 @@
zh-CN:
regions:
AS: '亚洲'
SA: '南亚'
SEA: '东南亚'
EA: '东亚'
ME: '中东'
AF: '非洲'
NA: '北非'
SSA: '撒哈拉以南非洲'
EU: '欧洲'
NAM: '北美洲'
SAM: '南美洲'
CAM: '中美洲'
OC: '大洋洲'

View File

@ -0,0 +1,13 @@
class CreateRegions < ActiveRecord::Migration[8.0]
def change
create_table :regions do |t|
t.string :name
t.string :code
t.string :slug
t.timestamps
end
add_index :regions, :code, unique: true
add_index :regions, :slug, unique: true
end
end

View File

@ -0,0 +1,14 @@
class CreateCountries < ActiveRecord::Migration[8.0]
def change
create_table :countries do |t|
t.string :name
t.string :code
t.string :slug
t.references :region, null: false, foreign_key: true
t.timestamps
end
add_index :countries, :code, unique: true
add_index :countries, :slug, unique: true
end
end

View File

@ -0,0 +1,5 @@
class AddCountryToCities < ActiveRecord::Migration[8.0]
def change
add_reference :cities, :country, null: false, foreign_key: true
end
end

View File

@ -0,0 +1,6 @@
class RemoveGeographicFieldsFromCities < ActiveRecord::Migration[8.0]
def change
remove_column :cities, :region, :string
remove_column :cities, :country, :string
end
end

30
db/schema.rb generated
View File

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2025_01_19_032348) do ActiveRecord::Schema[8.0].define(version: 2025_01_21_020653) do
create_table "active_admin_comments", force: :cascade do |t| create_table "active_admin_comments", force: :cascade do |t|
t.string "namespace" t.string "namespace"
t.text "body" t.text "body"
@ -67,21 +67,33 @@ ActiveRecord::Schema[8.0].define(version: 2025_01_19_032348) do
create_table "cities", force: :cascade do |t| create_table "cities", force: :cascade do |t|
t.string "name" t.string "name"
t.string "country"
t.float "latitude" t.float "latitude"
t.float "longitude" t.float "longitude"
t.boolean "active" t.boolean "active"
t.integer "priority" t.integer "priority"
t.string "timezone" t.string "timezone"
t.string "region"
t.datetime "last_weather_fetch" t.datetime "last_weather_fetch"
t.datetime "last_image_generation" t.datetime "last_image_generation"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.string "slug" t.string "slug"
t.integer "country_id", null: false
t.index ["country_id"], name: "index_cities_on_country_id"
t.index ["slug"], name: "index_cities_on_slug", unique: true t.index ["slug"], name: "index_cities_on_slug", unique: true
end end
create_table "countries", force: :cascade do |t|
t.string "name"
t.string "code"
t.string "slug"
t.integer "region_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["code"], name: "index_countries_on_code", unique: true
t.index ["region_id"], name: "index_countries_on_region_id"
t.index ["slug"], name: "index_countries_on_slug", unique: true
end
create_table "friendly_id_slugs", force: :cascade do |t| create_table "friendly_id_slugs", force: :cascade do |t|
t.string "slug", null: false t.string "slug", null: false
t.integer "sluggable_id", null: false t.integer "sluggable_id", null: false
@ -93,6 +105,16 @@ ActiveRecord::Schema[8.0].define(version: 2025_01_19_032348) do
t.index ["sluggable_type", "sluggable_id"], name: "index_friendly_id_slugs_on_sluggable_type_and_sluggable_id" t.index ["sluggable_type", "sluggable_id"], name: "index_friendly_id_slugs_on_sluggable_type_and_sluggable_id"
end end
create_table "regions", force: :cascade do |t|
t.string "name"
t.string "code"
t.string "slug"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["code"], name: "index_regions_on_code", unique: true
t.index ["slug"], name: "index_regions_on_slug", unique: true
end
create_table "weather_arts", force: :cascade do |t| create_table "weather_arts", force: :cascade do |t|
t.integer "city_id", null: false t.integer "city_id", null: false
t.date "weather_date" t.date "weather_date"
@ -114,5 +136,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_01_19_032348) do
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "cities", "countries"
add_foreign_key "countries", "regions"
add_foreign_key "weather_arts", "cities" add_foreign_key "weather_arts", "cities"
end end

View File

@ -9,15 +9,150 @@
# end # end
AdminUser.create!(email: 'admin@example.com', password: 'password', password_confirmation: 'password') if Rails.env.development? AdminUser.create!(email: 'admin@example.com', password: 'password', password_confirmation: 'password') if Rails.env.development?
WeatherArt.delete_all
City.delete_all
Country.delete_all
Region.delete_all
# 创建区域
regions = Region.create!([
{
name: 'Asia',
code: 'AS'
},
{
name: 'South Asia',
code: 'SA'
},
{
name: 'Southeast Asia',
code: 'SEA'
},
{
name: 'East Asia',
code: 'EA'
},
{
name: 'Middle East',
code: 'ME'
},
{
name: 'Africa',
code: 'AF'
},
{
name: 'North Africa',
code: 'NA'
},
{
name: 'Sub-Saharan Africa',
code: 'SSA'
},
{
name: 'Europe',
code: 'EU'
},
{
name: 'North America',
code: 'NAM'
},
{
name: 'South America',
code: 'SAM'
},
{
name: 'Central America',
code: 'CAM'
},
{
name: 'Oceania',
code: 'OC'
}
])
asia = Region.find_by(code: 'AS')
south_asia = Region.find_by(code: 'SA')
africa = Region.find_by(code: 'AF')
europe = Region.find_by(code: 'EU')
north_america = Region.find_by(code: 'NAM')
south_america = Region.find_by(code: 'SAM')
oceania = Region.find_by(code: 'OC')
# 创建所有国家
Country.create!([
# East Asia
{ name: 'China', code: 'CN', region: asia },
{ name: 'Japan', code: 'JP', region: asia },
{ name: 'South Korea', code: 'KR', region: asia },
{ name: 'Taiwan', code: 'TW', region: asia },
{ name: 'Hong Kong', code: 'HK', region: asia },
# South Asia
{ name: 'India', code: 'IN', region: south_asia },
{ name: 'Pakistan', code: 'PK', region: south_asia },
{ name: 'Bangladesh', code: 'BD', region: south_asia },
# Southeast Asia
{ name: 'Indonesia', code: 'ID', region: asia },
{ name: 'Vietnam', code: 'VN', region: asia },
{ name: 'Thailand', code: 'TH', region: asia },
{ name: 'Myanmar', code: 'MM', region: asia },
{ name: 'Singapore', code: 'SG', region: asia },
{ name: 'Bangladesh', code: 'BD', region: asia },
# Middle East
{ name: 'Turkey', code: 'TR', region: asia },
{ name: 'Iran', code: 'IR', region: asia },
{ name: 'Saudi Arabia', code: 'SA', region: asia },
{ name: 'Iraq', code: 'IQ', region: asia },
# Africa
{ name: 'Nigeria', code: 'NG', region: africa },
{ name: 'Egypt', code: 'EG', region: africa },
{ name: 'Democratic Republic of the Congo', code: 'CD', region: africa },
{ name: 'Tanzania', code: 'TZ', region: africa },
{ name: 'South Africa', code: 'ZA', region: africa },
{ name: 'Kenya', code: 'KE', region: africa },
{ name: 'Angola', code: 'AO', region: africa },
{ name: 'Mali', code: 'ML', region: africa },
{ name: 'Ivory Coast', code: 'CI', region: africa },
{ name: 'Egypt', code: 'EGY', region: africa },
# Europe
{ name: 'Russia', code: 'RU', region: europe },
{ name: 'United Kingdom', code: 'GB', region: europe },
{ name: 'Germany', code: 'DE', region: europe },
{ name: 'France', code: 'FRA', region: europe},
# North America
{ name: 'United States', code: 'US', region: north_america },
{ name: 'Mexico', code: 'MX', region: north_america },
{ name: 'Canada', code: 'CA', region: north_america },
# South America
{ name: 'Brazil', code: 'BR', region: south_america },
{ name: 'Peru', code: 'PE', region: south_america },
{ name: 'Colombia', code: 'CO', region: south_america },
{ name: 'Chile', code: 'CL', region: south_america },
{ name: 'Brazil', code: 'BZ', region: south_america },
# Oceania
{ name: 'Australia', code: 'AU', region: oceania }
])
# 创建城市
Dir[Rails.root.join('db/seeds/cities/*.rb')].sort.each do |file|
require file
end
china = Country.find_by(code: 'CHN')
guangzhou = City.create!( guangzhou = City.create!(
name: 'Guangzhou', name: 'Guangzhou',
country: 'China',
latitude: 23.1291, latitude: 23.1291,
longitude: 113.2644, longitude: 113.2644,
active: true,
priority: 50, priority: 50,
country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
region: 'Asia', active: true,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
) )

View File

@ -0,0 +1,26 @@
australia = Country.find_by code: 'AU'
City.create!([
{
name: 'Sydney',
latitude: -33.8688,
longitude: 151.2093,
country: australia,
timezone: 'Australia/Sydney',
active: true,
priority: 80,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Melbourne',
latitude: -37.8136,
longitude: 144.9631,
country: australia,
timezone: 'Australia/Melbourne',
active: true,
priority: 75,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

View File

@ -0,0 +1,15 @@
bangladesh = Country.find_by code: 'BD'
City.create!([
{
name: 'Dhaka',
latitude: 23.8103,
longitude: 90.4125,
country: bangladesh,
timezone: 'Asia/Dhaka',
active: true,
priority: 85,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

15
db/seeds/cities/brazil.rb Normal file
View File

@ -0,0 +1,15 @@
brazil = Country.find_by code: 'BZ'
City.create!([
{
name: 'Rio de Janeiro',
latitude: -22.9068,
longitude: -43.1729,
country: brazil,
timezone: 'America/Sao_Paulo',
active: true,
priority: 80,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

12
db/seeds/cities/canada.rb Normal file
View File

@ -0,0 +1,12 @@
canada = Country.find_by code: 'CA'
City.create!(
name: 'Toronto',
latitude: 43.6532,
longitude: -79.3832,
priority: 50,
country: canada,
timezone: 'America/Toronto',
active: true,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
)

422
db/seeds/cities/china.rb Normal file
View File

@ -0,0 +1,422 @@
china = Country.find_by code: 'CN'
City.create!([
{
name: 'Shanghai',
latitude: 31.2304,
longitude: 121.4737,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Beijing',
latitude: 39.9042,
longitude: 116.4074,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Shenzhen',
latitude: 22.5431,
longitude: 114.0579,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Guangzhou',
latitude: 23.1291,
longitude: 113.2644,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Chengdu',
latitude: 30.5728,
longitude: 104.0668,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Tianjin',
latitude: 39.3434,
longitude: 117.3616,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Wuhan',
latitude: 30.5928,
longitude: 114.3055,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Dongguan',
latitude: 23.0208,
longitude: 113.7518,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Chongqing',
latitude: 29.4316,
longitude: 106.9123,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: "Xi'an",
latitude: 34.3416,
longitude: 108.9398,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Hangzhou',
latitude: 30.2741,
longitude: 120.1551,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Foshan',
latitude: 23.0219,
longitude: 113.1216,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Nanjing',
latitude: 32.0603,
longitude: 118.7969,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Hong Kong',
latitude: 22.3193,
longitude: 114.1694,
country: china,
timezone: 'Asia/Hong_Kong',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Shenyang',
latitude: 41.8057,
longitude: 123.4315,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Zhengzhou',
latitude: 34.7472,
longitude: 113.6249,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Qingdao',
latitude: 36.0671,
longitude: 120.3826,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Suzhou',
latitude: 31.2990,
longitude: 120.5853,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Changsha',
latitude: 28.2282,
longitude: 112.9388,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Jinan',
latitude: 36.6512,
longitude: 117.1201,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Kunming',
latitude: 25.0389,
longitude: 102.7183,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Harbin',
latitude: 45.8038,
longitude: 126.5340,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Shijiazhuang',
latitude: 38.0428,
longitude: 114.5149,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Hefei',
latitude: 31.8206,
longitude: 117.2272,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Dalian',
latitude: 38.9140,
longitude: 121.6147,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Xiamen',
latitude: 24.4798,
longitude: 118.0819,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Nanning',
latitude: 22.8170,
longitude: 108.3665,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Changchun',
latitude: 43.8171,
longitude: 125.3235,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Taiyuan',
latitude: 37.8706,
longitude: 112.5489,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'New Taipei City',
latitude: 25.0120,
longitude: 121.4657,
country: china,
timezone: 'Asia/Taipei',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Guiyang',
latitude: 26.6470,
longitude: 106.6302,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Wuxi',
latitude: 31.4914,
longitude: 120.3119,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Shantou',
latitude: 23.3535,
longitude: 116.6822,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Ürümqi',
latitude: 43.8256,
longitude: 87.6168,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Zhongshan',
latitude: 22.5415,
longitude: 113.3926,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Ningbo',
latitude: 29.8683,
longitude: 121.5440,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Fuzhou',
latitude: 26.0745,
longitude: 119.2965,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Nanchang',
latitude: 28.6820,
longitude: 115.8579,
country: china,
timezone: 'Asia/Shanghai',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

15
db/seeds/cities/egypt.rb Normal file
View File

@ -0,0 +1,15 @@
egypt = Country.find_by code: 'EGY'
City.create!([
{
name: 'Alexandria',
latitude: 31.2001,
longitude: 29.9187,
country: egypt,
timezone: 'Africa/Cairo',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

15
db/seeds/cities/france.rb Normal file
View File

@ -0,0 +1,15 @@
france = Country.find_by code: 'FRA'
City.create!([
{
name: 'Paris',
latitude: 48.8566,
longitude: 2.3522,
country: france,
timezone: 'Europe/Paris',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

View File

@ -0,0 +1,26 @@
germany = Country.find_by code: 'DE'
City.create!([
{
name: 'Frankfurt',
latitude: 50.1109,
longitude: 8.6821,
country: germany,
timezone: 'Europe/Berlin',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Berlin',
latitude: 52.5200,
longitude: 13.4050,
country: germany,
timezone: 'Europe/Berlin',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

26
db/seeds/cities/india.rb Normal file
View File

@ -0,0 +1,26 @@
india = Country.find_by code: 'IN'
City.create!([
{
name: 'Mumbai',
latitude: 19.0760,
longitude: 72.8777,
country: india,
timezone: 'Asia/Kolkata',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Bengaluru',
latitude: 12.9716,
longitude: 77.5946,
country: india,
timezone: 'Asia/Kolkata',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

26
db/seeds/cities/japan.rb Normal file
View File

@ -0,0 +1,26 @@
japan = Country.find_by 1
City.create!([
{
name: 'Tokyo',
latitude: 35.6762,
longitude: 139.6503,
country: japan,
timezone: 'Asia/Tokyo',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Yokohama',
latitude: 35.4437,
longitude: 139.6380,
country: japan,
timezone: 'Asia/Tokyo',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

15
db/seeds/cities/mexico.rb Normal file
View File

@ -0,0 +1,15 @@
mexico = Country.find_by 1
City.create!([
{
name: 'Mexico City',
latitude: 19.4326,
longitude: -99.1332,
country: mexico,
timezone: 'America/Mexico_City',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

View File

@ -0,0 +1,15 @@
nigeria = Country.find_by 1
City.create!([
{
name: 'Lagos',
latitude: 6.5244,
longitude: 3.3792,
country: nigeria,
timezone: 'Africa/Lagos',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

View File

@ -0,0 +1,15 @@
pakistan = Country.find_by 1
City.create!([
{
name: 'Lahore',
latitude: 31.5204,
longitude: 74.3587,
country: pakistan,
timezone: 'Asia/Karachi',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

26
db/seeds/cities/russia.rb Normal file
View File

@ -0,0 +1,26 @@
russia = Country.find_by 1
City.create!([
{
name: 'Moscow',
latitude: 55.7558,
longitude: 37.6173,
country: russia,
timezone: 'Europe/Moscow',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Sankt Petersburg',
latitude: 59.9311,
longitude: 30.3609,
country: russia,
timezone: 'Europe/Moscow',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

View File

@ -0,0 +1,15 @@
saudi_arabia = Country.find_by 1
City.create!([
{
name: 'Riyadh',
latitude: 24.7136,
longitude: 46.6753,
country: saudi_arabia,
timezone: 'Asia/Riyadh',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

View File

@ -0,0 +1,15 @@
singapore = Country.find_by 1
City.create!([
{
name: 'Singapore',
latitude: 1.3521,
longitude: 103.8198,
country: singapore,
timezone: 'Asia/Singapore',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

View File

@ -0,0 +1,15 @@
south_korea = Country.find_by 1
City.create!([
{
name: 'Seoul',
latitude: 37.5665,
longitude: 126.9780,
country: south_korea,
timezone: 'Asia/Seoul',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

View File

@ -0,0 +1,15 @@
thailand = Country.find_by 1
City.create!([
{
name: 'Bangkok',
latitude: 13.7563,
longitude: 100.5018,
country: thailand,
timezone: 'Asia/Bangkok',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

26
db/seeds/cities/turkey.rb Normal file
View File

@ -0,0 +1,26 @@
turkey = Country.find_by 1
City.create!([
{
name: 'İstanbul',
latitude: 41.0082,
longitude: 28.9784,
country: turkey,
timezone: 'Europe/Istanbul',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Ankara',
latitude: 39.9334,
longitude: 32.8597,
country: turkey,
timezone: 'Europe/Istanbul',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

15
db/seeds/cities/uk.rb Normal file
View File

@ -0,0 +1,15 @@
uk = Country.find_by 1
City.create!([
{
name: 'London',
latitude: 51.5074,
longitude: -0.1278,
country: uk,
timezone: 'Europe/London',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

48
db/seeds/cities/usa.rb Normal file
View File

@ -0,0 +1,48 @@
usa = Country.find_by 1
City.create!([
{
name: 'San Francisco',
latitude: 37.7749,
longitude: -122.4194,
country: usa,
timezone: 'America/Los_Angeles',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Chicago',
latitude: 41.8781,
longitude: -87.6298,
country: usa,
timezone: 'America/Chicago',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'New York City',
latitude: 40.7128,
longitude: -74.0060,
country: usa,
timezone: 'America/New_York',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Los Angeles',
latitude: 34.0522,
longitude: -118.2437,
country: usa,
timezone: 'America/Los_Angeles',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

View File

@ -0,0 +1,26 @@
vietnam = Country.find_by 1
City.create!([
{
name: 'Ho Chi Minh City',
latitude: 10.8231,
longitude: 106.6297,
country: vietnam,
timezone: 'Asia/Ho_Chi_Minh',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
},
{
name: 'Hanoi',
latitude: 21.0285,
longitude: 105.8542,
country: vietnam,
timezone: 'Asia/Ho_Chi_Minh',
active: true,
priority: 100,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
}
])

View File

@ -9,7 +9,6 @@
# active: false # active: false
# priority: 1 # priority: 1
# timezone: MyString # timezone: MyString
# population: 1
# region: MyString # region: MyString
# last_weather_fetch: 2025-01-19 10:28:26 # last_weather_fetch: 2025-01-19 10:28:26
# last_image_generation: 2025-01-19 10:28:26 # last_image_generation: 2025-01-19 10:28:26
@ -23,7 +22,6 @@
# active: false # active: false
# priority: 1 # priority: 1
# timezone: MyString # timezone: MyString
# population: 1
# region: MyString # region: MyString
# last_weather_fetch: 2025-01-19 10:28:26 # last_weather_fetch: 2025-01-19 10:28:26
# last_image_generation: 2025-01-19 10:28:26 # last_image_generation: 2025-01-19 10:28:26

13
test/fixtures/countries.yml vendored Normal file
View File

@ -0,0 +1,13 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
#one:
# name: MyString
# code: MyString
# slug: MyString
# region: one
#
#two:
# name: MyString
# code: MyString
# slug: MyString
# region: two

11
test/fixtures/regions.yml vendored Normal file
View File

@ -0,0 +1,11 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
#one:
# name: MyString
# code: MyString
# slug: MyString
#
#two:
# name: MyString
# code: MyString
# slug: MyString

View File

@ -0,0 +1,7 @@
require "test_helper"
class CountryTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end

View File

@ -0,0 +1,7 @@
require "test_helper"
class RegionTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end