feat: add batch weather art generation jobs

- Created BatchGenerateWeatherArtsJob to process eligible
  cities and generate weather art.
- Introduced GenerateWeatherArtJob for generating weather
  art and image attachment.
- Added AiService for obtaining prompts and generating
  images with OpenAI API.
- Implemented WeatherService to fetch current weather
  data from the QWeather API.
- Updated Gemfile with necessary gems (whenever,
  ruby-openai, httparty, down, aws-sdk-s3).

This commit introduces a system to create and store
weather art images for various cities based on current
weather conditions, leveraging external APIs for data
and image generation.
This commit is contained in:
songtianlun 2025-01-22 16:50:00 +08:00
parent 6e387d1a8c
commit d728d7f50e
37 changed files with 361 additions and 83 deletions

View File

@ -45,6 +45,12 @@ gem "devise", "~> 4.9"
gem "activeadmin", "~> 3.2" gem "activeadmin", "~> 3.2"
gem "friendly_id", "~> 5.5" gem "friendly_id", "~> 5.5"
gem "whenever", "~> 1.0"
gem "ruby-openai", "~> 7.3"
gem "httparty", "~> 0.22.0"
gem "down", "~> 5.4"
gem "aws-sdk-s3", "~> 1.177"
group :development, :test do group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem "debug", platforms: %i[ mri windows ], require: "debug/prelude" gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"

View File

@ -88,6 +88,22 @@ GEM
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
ruby2_keywords (>= 0.0.2) ruby2_keywords (>= 0.0.2)
ast (2.4.2) ast (2.4.2)
aws-eventstream (1.3.0)
aws-partitions (1.1035.0)
aws-sdk-core (3.215.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.96.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.177.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.11.0)
aws-eventstream (~> 1, >= 1.0.2)
base64 (0.2.0) base64 (0.2.0)
bcrypt (3.1.20) bcrypt (3.1.20)
bcrypt_pbkdf (1.1.1) bcrypt_pbkdf (1.1.1)
@ -110,6 +126,7 @@ GEM
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0) regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2) xpath (~> 3.2)
chronic (0.10.2)
concurrent-ruby (1.3.5) concurrent-ruby (1.3.5)
connection_pool (2.5.0) connection_pool (2.5.0)
crass (1.0.6) crass (1.0.6)
@ -127,11 +144,22 @@ GEM
responders responders
warden (~> 1.2.3) warden (~> 1.2.3)
dotenv (3.1.7) dotenv (3.1.7)
down (5.4.2)
addressable (~> 2.8)
drb (2.2.1) drb (2.2.1)
ed25519 (1.3.0) ed25519 (1.3.0)
erubi (1.13.1) erubi (1.13.1)
et-orbi (1.2.11) et-orbi (1.2.11)
tzinfo tzinfo
event_stream_parser (1.0.0)
faraday (2.12.2)
faraday-net_http (>= 2.0, < 3.5)
json
logger
faraday-multipart (1.1.0)
multipart-post (~> 2.0)
faraday-net_http (3.4.0)
net-http (>= 0.5.0)
formtastic (5.0.0) formtastic (5.0.0)
actionpack (>= 6.0.0) actionpack (>= 6.0.0)
formtastic_i18n (0.7.0) formtastic_i18n (0.7.0)
@ -145,6 +173,10 @@ GEM
has_scope (0.8.2) has_scope (0.8.2)
actionpack (>= 5.2) actionpack (>= 5.2)
activesupport (>= 5.2) activesupport (>= 5.2)
httparty (0.22.0)
csv
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
i18n (1.14.6) i18n (1.14.6)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
inherited_resources (1.14.0) inherited_resources (1.14.0)
@ -159,6 +191,7 @@ GEM
jbuilder (2.13.0) jbuilder (2.13.0)
actionview (>= 5.0.0) actionview (>= 5.0.0)
activesupport (>= 5.0.0) activesupport (>= 5.0.0)
jmespath (1.6.2)
jquery-rails (4.6.0) jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3) rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0) railties (>= 4.2.0)
@ -204,6 +237,11 @@ GEM
mini_mime (1.1.5) mini_mime (1.1.5)
minitest (5.25.4) minitest (5.25.4)
msgpack (1.7.5) msgpack (1.7.5)
multi_xml (0.7.1)
bigdecimal (~> 3.1)
multipart-post (2.4.1)
net-http (0.6.0)
uri
net-imap (0.5.5) net-imap (0.5.5)
date date
net-protocol net-protocol
@ -335,6 +373,10 @@ GEM
rubocop-minitest rubocop-minitest
rubocop-performance rubocop-performance
rubocop-rails rubocop-rails
ruby-openai (7.3.1)
event_stream_parser (>= 0.3.0, < 2.0.0)
faraday (>= 1)
faraday-multipart (>= 1)
ruby-progressbar (1.13.0) ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5) ruby2_keywords (0.0.5)
rubyzip (2.4.1) rubyzip (2.4.1)
@ -407,6 +449,8 @@ GEM
base64 base64
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5) websocket-extensions (0.1.5)
whenever (1.0.0)
chronic (>= 0.6.3)
xpath (3.2.0) xpath (3.2.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
zeitwerk (2.7.1) zeitwerk (2.7.1)
@ -425,13 +469,16 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
activeadmin (~> 3.2) activeadmin (~> 3.2)
aws-sdk-s3 (~> 1.177)
bootsnap bootsnap
brakeman brakeman
capybara capybara
cssbundling-rails cssbundling-rails
debug debug
devise (~> 4.9) devise (~> 4.9)
down (~> 5.4)
friendly_id (~> 5.5) friendly_id (~> 5.5)
httparty (~> 0.22.0)
jbuilder jbuilder
jsbundling-rails jsbundling-rails
kamal kamal
@ -440,6 +487,7 @@ DEPENDENCIES
puma (>= 5.0) puma (>= 5.0)
rails (~> 8.0.1) rails (~> 8.0.1)
rubocop-rails-omakase rubocop-rails-omakase
ruby-openai (~> 7.3)
selenium-webdriver selenium-webdriver
solid_cable solid_cable
solid_cache solid_cache
@ -450,6 +498,7 @@ DEPENDENCIES
turbo-rails turbo-rails
tzinfo-data tzinfo-data
web-console web-console
whenever (~> 1.0)
BUNDLED WITH BUNDLED WITH
2.6.2 2.6.2

View File

@ -21,9 +21,11 @@ ActiveAdmin.register WeatherArt do
permit_params :city_id, :weather_date, :description, :temperature, permit_params :city_id, :weather_date, :description, :temperature,
:feeling_temp, :humidity, :wind_scale, :wind_speed, :feeling_temp, :humidity, :wind_scale, :wind_speed,
:precipitation, :pressure, :visibility, :cloud, :precipitation, :pressure, :visibility, :cloud,
:prompt, :image :prompt, :image, :slug
remove_filter :image_attachment, :image_blob remove_filter :image_attachment, :image_blob
filter :city_id
filter :weather_data
index do index do
selectable_column selectable_column

View File

@ -0,0 +1,34 @@
class BatchGenerateWeatherArtsJob < ApplicationJob
queue_as :default
def perform(*args)
start_time = Time.current
max_duration = 50.minutes
cities_to_process = get_eligible_cities
cities_to_process.each do |city|
break if Time.current - start_time > max_duration
GenerateWeatherArtJob.perform_now(city)
sleep 1.minute # 确保不超过API限制
end
end
private
def get_eligible_cities
City.active
.where(active: true)
.where("last_weather_fetch IS NULL OR last_weather_fetch < ?", Date.today)
# .select { |city| early_morning_in_timezone?(city.timezone) }
end
# def early_morning_in_timezone?(timezone)
# return false if timezone.blank?
# time = Time.current.in_time_zone(timezone)
# time.hour == 2
# end
end

View File

@ -0,0 +1,45 @@
class GenerateWeatherArtJob < ApplicationJob
queue_as :default
def perform(*args)
city = args[0]
return if city.last_weather_fetch&.today?
weather_service = WeatherService.new
ai_service = AiService.new
# 获取天气数据
weather_data = weather_service.get_weather(city.latitude, city.longitude)
return unless weather_data
# 生成提示词
prompt = ai_service.generate_prompt(city, weather_data)
return unless prompt
# 生成图像
image_url = ai_service.generate_image(prompt)
return unless image_url
# 创建天气艺术记录
weather_art = city.weather_arts.create!(
weather_date: Date.today,
**weather_data,
prompt: prompt
)
# 下载并附加图像
tempfile = Down.download(image_url)
weather_art.image.attach(
io: tempfile,
filename: "#{city.country.name}-#{city.name.parameterize}-#{Time.current.strftime('%Y%m%d-%H%M%S')}.png"
)
# 更新城市状态
city.update!(
last_weather_fetch: Time.current,
last_image_generation: Time.current
)
rescue => e
Rails.logger.error "Error generating weather art for #{city.name}: #{e.message}"
end
end

View File

@ -0,0 +1,64 @@
class AiService
def initialize
@client = OpenAI::Client.new(
access_token: Rails.application.credentials.openai.token,
uri_base: Rails.application.credentials.openai.uri,
request_timeout: 240
)
end
def generate_prompt(city, weather_data)
response = @client.chat(
parameters: {
model: "gpt-4",
messages: [{
role: "system",
content: "You are a professional artist creating prompts for DALL-E 3. Create realistic, artistic weather scenes featuring iconic landmarks."
}, {
role: "user",
content: generate_prompt_request(city, weather_data)
}],
temperature: 0.7,
max_tokens: 300
}
)
response.dig("choices", 0, "message", "content")
end
def generate_image(prompt)
response = @client.images.generate(
parameters: {
model: "dall-e-3",
prompt: prompt,
size: "1792x1024",
quality: "standard",
n: 1
}
)
response.dig("data", 0, "url")
end
private
def generate_prompt_request(city, weather_data)
<<~PROMPT
Create a DALL-E 3 prompt for a weather scene in #{city.name}, #{city.country.name}.
Weather conditions:
- Temperature: #{weather_data[:temperature]}°C
- Weather: #{weather_data[:description]}
- Cloud cover: #{weather_data[:cloud]}%
- Time: Early morning
Requirements:
- Feature iconic landmarks or architecture from #{city.name}
- Realistic style
- Weather conditions should be clearly visible
- Atmospheric and artistic composition
Generate a detailed, creative prompt that will produce a beautiful and realistic image.
PROMPT
end
end

View File

@ -0,0 +1,37 @@
# app/services/weather_service.rb
class WeatherService
include HTTParty
base_uri Rails.application.credentials.qweather.uri
def initialize
@api_key = Rails.application.credentials.qweather.token
end
def get_weather(latitude, longitude)
Rails.logger.debug "Get Weather for #{latitude},#{longitude}"
response = self.class.get(
"/weather/now",
headers: {
"X-QW-Api-Key" => "#{@api_key}"
},
query: {
location: "#{longitude},#{latitude}"
})
return nil unless response.success?
data = response["now"]
{
temperature: data["temp"].to_f,
feeling_temp: data["feelsLike"].to_f,
humidity: data["humidity"].to_f,
wind_scale: "#{data['windScale']}",
wind_speed: data["windSpeed"].to_f,
precipitation: data["precip"].to_f,
pressure: data["pressure"].to_f,
visibility: data["vis"].to_f,
cloud: data["cloud"].to_f,
description: data["text"]
}
end
end

View File

@ -1 +1 @@
GwoFK6l/nbuNuzqsSphWsWWAkF3rF3LqQJXbBlMhZqleAE/wXGYzxgansBULOsF+/0hMDNT+AMQdLKPd+J+Oo55LNVHd9Dk6iJ4wtRJm5Ya4czrPTqv4dezNwRFm6soC085fUONQ8hxShenYWSNtUD+X9HmjG3xDYOMk8XHJRdz+TzUqzk8+sTee1xFTP3ZFTF1HYHE+3csz22rA0KBekDbSL+HK/rlKvNK3UJK/LM71V1BmaPSBC50X+D7TkGZGatMRLPwM3C3m/6PPvB838zeH7fm2maPx2/Y4zPZhTarUg3/U+R0wGfGbSCdMMBy/A+04C7KxadTn4Ivk3zXI3zloEbgY+s1pq6RZNKuLfQFUDzpDtdnC7tjYRnMBo6C3c8iAgI0gnnYHY0zHPws+umUlS/kdiWBn6jvsNc6zz6bSyBY8xIuL4zm/Aa4wQJc5u1wLTQW00nXKJvYo7bvZsWhusATQlPm+VK+U0rdh6uAyaeatwc951KB3--N7qeSFBaRTq/dtNy--L8fWHRQMpTXu5+6E1HsNaQ== 0Upt112zhMfb3aADOgxSWUCTTUNgtTrpoivR9+KJFKcazTjqRauvQ9W+uicYrjJjv497gHMFhusWZysDl1/uwHHaoHvyp7auIjRHiOR1YKfRLgbMSYMgSOKlP4HbiZ66hjhT+4T50JjmwwLcPFtgPaZG3lasTAXejc9ejiSn+OsIGvJje5MXnPREId5pvC/SNW4uCYMe6OEsfhTlsj8hES7odHJzMsGQGGuVkcg1EimogOE9oWK6FS0bj45R+7HCiIYlbcmDkRNraGDMGJI+oaxx2mi+34ENoxqfbYEv4PhsWPYcOROK8FyrpXwvRG/a1J8LFxTLkVloKsBIInLojvd9u8zwpcTOtsaHOxsQV7gLzUt2GbUiT4EZUdzHpIDRboJEuVxm6ioBctcJ744xnkn5rxOoJH+JWRhxf+CVLYojcYMdkcyGEOHv0nXtpWtu/xsJT3fTqJBLuyGWNQUfTDsw3qQDUOrsgSNvXvhEu1iWptoByp4d0adaCDS0+TVt+BFg2xPzSnIU3IAXgSnhyLTVd87jxBMHtcngIj4HAj+nDIs65KT4dk4Y+ns3eWE345Z0CzUz1J6M8ikva0cQiBB6wxMl1yghysCcSfKX4z/KbuJv6StQJIqw4HkDZ9youXEbnmiXTxuEaC0Yg3SE0dFf5k9Rj5govLMdCf1Msj04RQHt0b08s3UdTgegriru+j7dC6yTaDbHkrNorREME3SENzdksI1D5k08D4Z+TYpO/+yyZE5qKELEse9TgJiFZ6g1H2sFs9zCxBDif67ovFSqrRaNgP7qBY8uEfFNVP6Y6eSnfccJlFBGlwflhwwA1osit+5rKlvhqQs37qsmFZRuj9BdrAJbdr/0ogEbLyeTEw3Zq+0m0/Vf4j5ueCv2eDpk/gSQdl869v+5anLTqMUWM4KV1wS1OrPkMC5XkZHLUo1/1+Dl6FKfZhWydRso1R9WL5B0Jk7UEWMPX0qoxxuixR1jwWzYmlehq0iNw7hQPdgwCbDtRxEMPr8MkUnG5Fd0YZUfnhHJ+EWVCZHKhUJclRSB9LnDKVPJr/oFuOHLmJg6Vll4WHCnIK9nCHdr7ed6O89vA5Z8DRlE/6yAXFlPKrCldWYbrL3BAgzQK8MxD5fzgzRkGiwVEtQwhbtbdDHUJ9rdAEmLJZj1UJXLIhX9jFspB9stHqyRxrcef/Y+h9dBvuFdvSIFEXA0TWHintx9YDgsJb591d6rjJn+JYEmZs9UONEEuiijPf9waqTb0oIrUQwnlUOX69bBipiU5ZQ2yQvepuRY3ooK3IGHvngxZPT0F8Mfh5Zcx9GGJd17LZb9DJOs7uOlrpXydToq/3Qm1q6TmgjbFYpC6iyrhDyE5XLL/XwVavh7m2QYqVbUXk2tGk2C0UR6CTE6tsV1+kDs1nylIEgAA5Nr43HQtRAXPmo0k8Txy5wMMIbLE1keqjl7XdGPnLsX9CJi6ue6KZxhigwcdakvW6Y=--H101ebDKrzdM39ll--a5R5klrhU6QgghGPjjWfAQ==

View File

@ -29,7 +29,8 @@ Rails.application.configure do
config.cache_store = :memory_store config.cache_store = :memory_store
# Store uploaded files on the local file system (see config/storage.yml for options). # Store uploaded files on the local file system (see config/storage.yml for options).
config.active_storage.service = :local # config.active_storage.service = :local
config.active_storage.service = :amazon_dev
# Don't care if the mailer can't send. # Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false config.action_mailer.raise_delivery_errors = false

View File

@ -22,7 +22,7 @@ Rails.application.configure do
# config.asset_host = "http://assets.example.com" # config.asset_host = "http://assets.example.com"
# Store uploaded files on the local file system (see config/storage.yml for options). # Store uploaded files on the local file system (see config/storage.yml for options).
config.active_storage.service = :local config.active_storage.service = :amazon
# Assume all access to the app is happening through a SSL-terminating reverse proxy. # Assume all access to the app is happening through a SSL-terminating reverse proxy.
config.assume_ssl = true config.assume_ssl = true

23
config/schedule.rb Normal file
View File

@ -0,0 +1,23 @@
# Use this file to easily define all of your cron jobs.
#
# It's helpful, but not entirely necessary to understand cron before proceeding.
# http://en.wikipedia.org/wiki/Cron
# Example:
#
# set :output, "/path/to/my/cron_log.log"
#
# every 2.hours do
# command "/usr/bin/some_great_command"
# runner "MyModel.some_method"
# rake "some:great:rake:task"
# end
#
# every 4.days do
# runner "AnotherModel.prune_old_records"
# end
every 1.hour do
# runner "BatchGenerateWeatherArtsJob.perform_later"
end
# Learn more: http://github.com/javan/whenever

View File

@ -13,6 +13,21 @@ local:
# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
# region: us-east-1 # region: us-east-1
# bucket: your_own_bucket-<%= Rails.env %> # bucket: your_own_bucket-<%= Rails.env %>
amazon_dev:
service: S3
access_key_id: <%= ENV.fetch("AWS_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :access_key_id)) %>
secret_access_key: <%= ENV.fetch("AWS_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :secret_access_key)) %>
region: <%= ENV.fetch("AWS_REGION", Rails.application.credentials.dig(:aws_dev, :region)) %>
bucket: <%= ENV.fetch("AWS_BUCKET", Rails.application.credentials.dig(:aws_dev, :bucket)) %>
endpoint: <%= ENV.fetch("AWS_ENDPOINT", Rails.application.credentials.dig(:aws_dev, :endpoint)) %>
amazon:
service: S3
access_key_id: <%= ENV.fetch("AWS_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws, :access_key_id)) %>
secret_access_key: <%= ENV.fetch("AWS_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws, :secret_access_key)) %>
region: <%= ENV.fetch("AWS_REGION", Rails.application.credentials.dig(:aws, :region)) %>
bucket: <%= ENV.fetch("AWS_BUCKET", Rails.application.credentials.dig(:aws, :bucket)) %>
endpoint: <%= ENV.fetch("AWS_ENDPOINT", Rails.application.credentials.dig(:aws, :endpoint)) %>
# Remember not to checkin your GCS keyfile to a repository # Remember not to checkin your GCS keyfile to a repository
# google: # google:

View File

@ -139,19 +139,7 @@ Country.create!([
Dir[Rails.root.join('db/seeds/cities/*.rb')].sort.each do |file| Dir[Rails.root.join('db/seeds/cities/*.rb')].sort.each do |file|
require file require file
end end
guangzhou = City.find_by name: 'Guangzhou'
china = Country.find_by(code: 'CN')
guangzhou = City.create!(
name: 'Guangzhou',
latitude: 23.1291,
longitude: 113.2644,
priority: 50,
country: china,
timezone: 'Asia/Shanghai',
active: true,
last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago
)
guangzhou_weather_art = WeatherArt.create!( guangzhou_weather_art = WeatherArt.create!(
city: guangzhou, city: guangzhou,

View File

@ -7,7 +7,7 @@ City.create!([
longitude: 151.2093, longitude: 151.2093,
country: australia, country: australia,
timezone: 'Australia/Sydney', timezone: 'Australia/Sydney',
active: true, active: false,
priority: 80, priority: 80,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -18,7 +18,7 @@ City.create!([
longitude: 144.9631, longitude: 144.9631,
country: australia, country: australia,
timezone: 'Australia/Melbourne', timezone: 'Australia/Melbourne',
active: true, active: false,
priority: 75, priority: 75,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 90.4125, longitude: 90.4125,
country: bangladesh, country: bangladesh,
timezone: 'Asia/Dhaka', timezone: 'Asia/Dhaka',
active: true, active: false,
priority: 85, priority: 85,
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

@ -7,7 +7,7 @@ City.create!([
longitude: -43.1729, longitude: -43.1729,
country: brazil, country: brazil,
timezone: 'America/Sao_Paulo', timezone: 'America/Sao_Paulo',
active: true, active: false,
priority: 80, priority: 80,
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

@ -6,7 +6,7 @@ City.create!(
priority: 50, priority: 50,
country: canada, country: canada,
timezone: 'America/Toronto', timezone: 'America/Toronto',
active: true, active: false,
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

@ -29,7 +29,7 @@ City.create!([
longitude: 114.0579, longitude: 114.0579,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -51,7 +51,7 @@ City.create!([
longitude: 104.0668, longitude: 104.0668,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -62,7 +62,7 @@ City.create!([
longitude: 117.3616, longitude: 117.3616,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -73,7 +73,7 @@ City.create!([
longitude: 114.3055, longitude: 114.3055,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -84,7 +84,7 @@ City.create!([
longitude: 113.7518, longitude: 113.7518,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -95,7 +95,7 @@ City.create!([
longitude: 106.9123, longitude: 106.9123,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -106,7 +106,7 @@ City.create!([
longitude: 108.9398, longitude: 108.9398,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -117,7 +117,7 @@ City.create!([
longitude: 120.1551, longitude: 120.1551,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -128,7 +128,7 @@ City.create!([
longitude: 113.1216, longitude: 113.1216,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -139,7 +139,7 @@ City.create!([
longitude: 118.7969, longitude: 118.7969,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -150,7 +150,7 @@ City.create!([
longitude: 114.1694, longitude: 114.1694,
country: china, country: china,
timezone: 'Asia/Hong_Kong', timezone: 'Asia/Hong_Kong',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -161,7 +161,7 @@ City.create!([
longitude: 123.4315, longitude: 123.4315,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -172,7 +172,7 @@ City.create!([
longitude: 113.6249, longitude: 113.6249,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -183,7 +183,7 @@ City.create!([
longitude: 120.3826, longitude: 120.3826,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -194,7 +194,7 @@ City.create!([
longitude: 120.5853, longitude: 120.5853,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -205,7 +205,7 @@ City.create!([
longitude: 112.9388, longitude: 112.9388,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -216,7 +216,7 @@ City.create!([
longitude: 117.1201, longitude: 117.1201,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -227,7 +227,7 @@ City.create!([
longitude: 102.7183, longitude: 102.7183,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -238,7 +238,7 @@ City.create!([
longitude: 126.5340, longitude: 126.5340,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -249,7 +249,7 @@ City.create!([
longitude: 114.5149, longitude: 114.5149,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -260,7 +260,7 @@ City.create!([
longitude: 117.2272, longitude: 117.2272,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -271,7 +271,7 @@ City.create!([
longitude: 121.6147, longitude: 121.6147,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -282,7 +282,7 @@ City.create!([
longitude: 118.0819, longitude: 118.0819,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -293,7 +293,7 @@ City.create!([
longitude: 108.3665, longitude: 108.3665,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -304,7 +304,7 @@ City.create!([
longitude: 125.3235, longitude: 125.3235,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -315,7 +315,7 @@ City.create!([
longitude: 112.5489, longitude: 112.5489,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -326,7 +326,7 @@ City.create!([
longitude: 121.4657, longitude: 121.4657,
country: china, country: china,
timezone: 'Asia/Taipei', timezone: 'Asia/Taipei',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -337,7 +337,7 @@ City.create!([
longitude: 106.6302, longitude: 106.6302,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -348,7 +348,7 @@ City.create!([
longitude: 120.3119, longitude: 120.3119,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -359,7 +359,7 @@ City.create!([
longitude: 116.6822, longitude: 116.6822,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -370,7 +370,7 @@ City.create!([
longitude: 87.6168, longitude: 87.6168,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -381,7 +381,7 @@ City.create!([
longitude: 113.3926, longitude: 113.3926,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -392,7 +392,7 @@ City.create!([
longitude: 121.5440, longitude: 121.5440,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -403,7 +403,7 @@ City.create!([
longitude: 119.2965, longitude: 119.2965,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -414,7 +414,7 @@ City.create!([
longitude: 115.8579, longitude: 115.8579,
country: china, country: china,
timezone: 'Asia/Shanghai', timezone: 'Asia/Shanghai',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 29.9187, longitude: 29.9187,
country: egypt, country: egypt,
timezone: 'Africa/Cairo', timezone: 'Africa/Cairo',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 2.3522, longitude: 2.3522,
country: france, country: france,
timezone: 'Europe/Paris', timezone: 'Europe/Paris',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 8.6821, longitude: 8.6821,
country: germany, country: germany,
timezone: 'Europe/Berlin', timezone: 'Europe/Berlin',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -18,7 +18,7 @@ City.create!([
longitude: 13.4050, longitude: 13.4050,
country: germany, country: germany,
timezone: 'Europe/Berlin', timezone: 'Europe/Berlin',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 72.8777, longitude: 72.8777,
country: india, country: india,
timezone: 'Asia/Kolkata', timezone: 'Asia/Kolkata',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -18,7 +18,7 @@ City.create!([
longitude: 77.5946, longitude: 77.5946,
country: india, country: india,
timezone: 'Asia/Kolkata', timezone: 'Asia/Kolkata',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 139.6503, longitude: 139.6503,
country: japan, country: japan,
timezone: 'Asia/Tokyo', timezone: 'Asia/Tokyo',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -18,7 +18,7 @@ City.create!([
longitude: 139.6380, longitude: 139.6380,
country: japan, country: japan,
timezone: 'Asia/Tokyo', timezone: 'Asia/Tokyo',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: -99.1332, longitude: -99.1332,
country: mexico, country: mexico,
timezone: 'America/Mexico_City', timezone: 'America/Mexico_City',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 3.3792, longitude: 3.3792,
country: nigeria, country: nigeria,
timezone: 'Africa/Lagos', timezone: 'Africa/Lagos',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 74.3587, longitude: 74.3587,
country: pakistan, country: pakistan,
timezone: 'Asia/Karachi', timezone: 'Asia/Karachi',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 37.6173, longitude: 37.6173,
country: russia, country: russia,
timezone: 'Europe/Moscow', timezone: 'Europe/Moscow',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -18,7 +18,7 @@ City.create!([
longitude: 30.3609, longitude: 30.3609,
country: russia, country: russia,
timezone: 'Europe/Moscow', timezone: 'Europe/Moscow',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 46.6753, longitude: 46.6753,
country: saudi_arabia, country: saudi_arabia,
timezone: 'Asia/Riyadh', timezone: 'Asia/Riyadh',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 103.8198, longitude: 103.8198,
country: singapore, country: singapore,
timezone: 'Asia/Singapore', timezone: 'Asia/Singapore',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 126.9780, longitude: 126.9780,
country: south_korea, country: south_korea,
timezone: 'Asia/Seoul', timezone: 'Asia/Seoul',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 100.5018, longitude: 100.5018,
country: thailand, country: thailand,
timezone: 'Asia/Bangkok', timezone: 'Asia/Bangkok',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 28.9784, longitude: 28.9784,
country: turkey, country: turkey,
timezone: 'Europe/Istanbul', timezone: 'Europe/Istanbul',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -18,7 +18,7 @@ City.create!([
longitude: 32.8597, longitude: 32.8597,
country: turkey, country: turkey,
timezone: 'Europe/Istanbul', timezone: 'Europe/Istanbul',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: -0.1278, longitude: -0.1278,
country: uk, country: uk,
timezone: 'Europe/London', timezone: 'Europe/London',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: -122.4194, longitude: -122.4194,
country: usa, country: usa,
timezone: 'America/Los_Angeles', timezone: 'America/Los_Angeles',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -18,7 +18,7 @@ City.create!([
longitude: -87.6298, longitude: -87.6298,
country: usa, country: usa,
timezone: 'America/Chicago', timezone: 'America/Chicago',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -29,7 +29,7 @@ City.create!([
longitude: -74.0060, longitude: -74.0060,
country: usa, country: usa,
timezone: 'America/New_York', timezone: 'America/New_York',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -40,7 +40,7 @@ City.create!([
longitude: -118.2437, longitude: -118.2437,
country: usa, country: usa,
timezone: 'America/Los_Angeles', timezone: 'America/Los_Angeles',
active: true, active: false,
priority: 100, priority: 100,
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

@ -7,7 +7,7 @@ City.create!([
longitude: 106.6297, longitude: 106.6297,
country: vietnam, country: vietnam,
timezone: 'Asia/Ho_Chi_Minh', timezone: 'Asia/Ho_Chi_Minh',
active: true, active: false,
priority: 100, priority: 100,
last_weather_fetch: 10.hours.ago, last_weather_fetch: 10.hours.ago,
last_image_generation: 10.hours.ago last_image_generation: 10.hours.ago
@ -18,7 +18,7 @@ City.create!([
longitude: 105.8542, longitude: 105.8542,
country: vietnam, country: vietnam,
timezone: 'Asia/Ho_Chi_Minh', timezone: 'Asia/Ho_Chi_Minh',
active: true, active: false,
priority: 100, priority: 100,
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,7 @@
require "test_helper"
class BatchGenerateWeatherArtsJobTest < ActiveJob::TestCase
# test "the truth" do
# assert true
# end
end

View File

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