diff --git a/.idea/today_ai_weather.iml b/.idea/today_ai_weather.iml
index 970ce87..706094c 100644
--- a/.idea/today_ai_weather.iml
+++ b/.idea/today_ai_weather.iml
@@ -69,6 +69,7 @@
+
diff --git a/Gemfile b/Gemfile
index 7f2f5ae..2de0783 100644
--- a/Gemfile
+++ b/Gemfile
@@ -43,6 +43,7 @@ gem "thruster", require: false
# gem "image_processing", "~> 1.2"
gem 'devise', '~> 4.9'
gem 'activeadmin', '~> 3.2'
+gem 'friendly_id', '~> 5.5'
group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
diff --git a/Gemfile.lock b/Gemfile.lock
index f5cdd53..317fb06 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -135,6 +135,8 @@ GEM
formtastic (5.0.0)
actionpack (>= 6.0.0)
formtastic_i18n (0.7.0)
+ friendly_id (5.5.1)
+ activerecord (>= 4.0.0)
fugit (1.11.1)
et-orbi (~> 1, >= 1.2.11)
raabro (~> 1.4)
@@ -428,6 +430,7 @@ DEPENDENCIES
cssbundling-rails
debug
devise (~> 4.9)
+ friendly_id (~> 5.5)
jbuilder
jsbundling-rails
kamal
diff --git a/app/admin/cities.rb b/app/admin/cities.rb
new file mode 100644
index 0000000..cb616ea
--- /dev/null
+++ b/app/admin/cities.rb
@@ -0,0 +1,54 @@
+ActiveAdmin.register City do
+ controller do
+ def find_resource
+ scoped_collection.friendly.find(params[:id])
+ end
+ end
+
+ # 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, :country, :latitude, :longitude, :active, :priority, :timezone, :region, :last_weather_fetch, :last_image_generation, :slug
+ #
+ # or
+ #
+ # permit_params do
+ # permitted = [:name, :country, :latitude, :longitude, :active, :priority, :timezone, :region, :last_weather_fetch, :last_image_generation, :slug]
+ # permitted << :other if params[:action] == 'create' && current_user.admin?
+ # permitted
+ # end
+
+ index do
+ selectable_column
+ id_column
+ column :name
+ column :slug
+ column :latitude
+ column :longitude
+ column :active
+ column :created_at
+ actions
+ end
+
+ filter :name
+ filter :active
+
+ form do |f|
+ f.inputs do
+ f.input :active
+ f.input :name
+ f.input :country, as: :String
+ f.input :latitude
+ f.input :longitude
+ f.input :priority
+ f.input :timezone
+ f.input :region
+ f.input :last_weather_fetch
+ f.input :last_image_generation
+ end
+ f.actions
+ end
+
+end
diff --git a/app/admin/weather_arts.rb b/app/admin/weather_arts.rb
new file mode 100644
index 0000000..311c1f9
--- /dev/null
+++ b/app/admin/weather_arts.rb
@@ -0,0 +1,78 @@
+ActiveAdmin.register WeatherArt 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 :city_id, :weather_date, :description, :temperature, :feeling_temp, :humidity, :wind_scale, :wind_speed, :precipitation, :pressure, :visibility, :cloud, :prompt
+ #
+ # or
+ #
+ # permit_params do
+ # permitted = [:city_id, :weather_date, :description, :temperature, :feeling_temp, :humidity, :wind_scale, :wind_speed, :precipitation, :pressure, :visibility, :cloud, :prompt]
+ # permitted << :other if params[:action] == 'create' && current_user.admin?
+ # permitted
+ # end
+ permit_params :city_id, :weather_date, :description, :temperature,
+ :feeling_temp, :humidity, :wind_scale, :wind_speed,
+ :precipitation, :pressure, :visibility, :cloud,
+ :prompt, :image
+
+ remove_filter :image_attachment, :image_blob
+
+ index do
+ selectable_column
+ id_column
+ column :city
+ column :weather_date
+ column :description
+ column :temperature
+ column :image do |weather_art|
+ image_tag(weather_art.image, size: '100x100') if weather_art.image.attached?
+ end
+ actions
+ end
+
+ show do
+ attributes_table do
+ row :city
+ row :weather_date
+ row :description
+ row :temperature
+ row :feeling_temp
+ row :humidity
+ row :wind_scale
+ row :wind_speed
+ row :precipitation
+ row :pressure
+ row :visibility
+ row :cloud
+ row :prompt
+ row :image do |weather_art|
+ image_tag(weather_art.image) if weather_art.image.attached?
+ end
+ end
+ end
+
+ form do |f|
+ f.inputs do
+ f.input :city
+ f.input :weather_date
+ f.input :description
+ f.input :temperature
+ f.input :feeling_temp
+ f.input :humidity
+ f.input :wind_scale
+ f.input :wind_speed
+ f.input :precipitation
+ f.input :pressure
+ f.input :visibility
+ f.input :cloud
+ f.input :prompt
+ f.input :image, as: :file
+ end
+ f.actions
+ end
+
+end
diff --git a/app/controllers/cities_controller.rb b/app/controllers/cities_controller.rb
new file mode 100644
index 0000000..1bcf857
--- /dev/null
+++ b/app/controllers/cities_controller.rb
@@ -0,0 +1,8 @@
+class CitiesController < ApplicationController
+ def index
+ @cities = City.friendly.find(params[:id])
+ end
+
+ def show
+ end
+end
diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb
new file mode 100644
index 0000000..95f2992
--- /dev/null
+++ b/app/controllers/home_controller.rb
@@ -0,0 +1,4 @@
+class HomeController < ApplicationController
+ def index
+ end
+end
diff --git a/app/controllers/weather_arts_controller.rb b/app/controllers/weather_arts_controller.rb
new file mode 100644
index 0000000..0c1e6f4
--- /dev/null
+++ b/app/controllers/weather_arts_controller.rb
@@ -0,0 +1,4 @@
+class WeatherArtsController < ApplicationController
+ def show
+ end
+end
diff --git a/app/helpers/cities_helper.rb b/app/helpers/cities_helper.rb
new file mode 100644
index 0000000..dce779d
--- /dev/null
+++ b/app/helpers/cities_helper.rb
@@ -0,0 +1,2 @@
+module CitiesHelper
+end
diff --git a/app/helpers/home_helper.rb b/app/helpers/home_helper.rb
new file mode 100644
index 0000000..23de56a
--- /dev/null
+++ b/app/helpers/home_helper.rb
@@ -0,0 +1,2 @@
+module HomeHelper
+end
diff --git a/app/helpers/weather_arts_helper.rb b/app/helpers/weather_arts_helper.rb
new file mode 100644
index 0000000..6643a83
--- /dev/null
+++ b/app/helpers/weather_arts_helper.rb
@@ -0,0 +1,2 @@
+module WeatherArtsHelper
+end
diff --git a/app/models/admin_user.rb b/app/models/admin_user.rb
index 3c851a1..a853398 100644
--- a/app/models/admin_user.rb
+++ b/app/models/admin_user.rb
@@ -3,4 +3,9 @@ class AdminUser < ApplicationRecord
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable,
:recoverable, :rememberable, :validatable
+
+ def self.ransackable_attributes(auth_object = nil)
+ # 列出你想要允许搜索的属性
+ %w[created_at email id updated_at]
+ end
end
diff --git a/app/models/city.rb b/app/models/city.rb
new file mode 100644
index 0000000..891a90d
--- /dev/null
+++ b/app/models/city.rb
@@ -0,0 +1,23 @@
+class City < ApplicationRecord
+ extend FriendlyId
+ friendly_id :name, use: :slugged
+
+ has_many :weather_arts, dependent: :destroy
+
+ validates :name, presence: true
+ validates :latitude, presence: true
+ validates :longitude, presence: true
+
+ def should_generate_new_friendly_id?
+ name_changed? || super
+ end
+
+ def self.ransackable_associations(auth_object = nil)
+ [ "weather_arts" ]
+ end
+
+ def self.ransackable_attributes(auth_object = nil)
+ ["active", "country", "created_at", "id", "id_value", "last_image_generation", "last_weather_fetch", "latitude", "longitude", "name", "priority", "region", "slug", "timezone", "updated_at"]
+ end
+
+end
diff --git a/app/models/weather_art.rb b/app/models/weather_art.rb
new file mode 100644
index 0000000..fc4c9d9
--- /dev/null
+++ b/app/models/weather_art.rb
@@ -0,0 +1,16 @@
+class WeatherArt < ApplicationRecord
+ belongs_to :city
+
+ has_one_attached :image
+
+ validates :weather_date, presence: true
+ validates :city_id, presence: true
+
+ def self.ransackable_associations(auth_object = nil)
+ ["city", "image_attachment", "image_blob"]
+ end
+
+ def self.ransackable_attributes(auth_object = nil)
+ [ "city_id", "cloud", "created_at", "description", "feeling_temp", "humidity", "id", "id_value", "precipitation", "pressure", "prompt", "temperature", "updated_at", "visibility", "weather_date", "wind_scale", "wind_speed" ]
+ end
+end
diff --git a/app/views/cities/index.html.erb b/app/views/cities/index.html.erb
new file mode 100644
index 0000000..ecfe641
--- /dev/null
+++ b/app/views/cities/index.html.erb
@@ -0,0 +1,2 @@
+
Cities#index
+Find me in app/views/cities/index.html.erb
diff --git a/app/views/cities/show.html.erb b/app/views/cities/show.html.erb
new file mode 100644
index 0000000..8654a9c
--- /dev/null
+++ b/app/views/cities/show.html.erb
@@ -0,0 +1,2 @@
+Cities#show
+Find me in app/views/cities/show.html.erb
diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb
new file mode 100644
index 0000000..2085730
--- /dev/null
+++ b/app/views/home/index.html.erb
@@ -0,0 +1,2 @@
+Home#index
+Find me in app/views/home/index.html.erb
diff --git a/app/views/weather_arts/show.html.erb b/app/views/weather_arts/show.html.erb
new file mode 100644
index 0000000..faedb50
--- /dev/null
+++ b/app/views/weather_arts/show.html.erb
@@ -0,0 +1,2 @@
+WeatherArts#show
+Find me in app/views/weather_arts/show.html.erb
diff --git a/config/initializers/active_admin.rb b/config/initializers/active_admin.rb
index 4ea37c7..724a84e 100644
--- a/config/initializers/active_admin.rb
+++ b/config/initializers/active_admin.rb
@@ -4,12 +4,12 @@ ActiveAdmin.setup do |config|
# Set the title that is displayed on the main layout
# for each of the active admin pages.
#
- config.site_title = "Today Ai Weather"
+ config.site_title = "Today Ai Weather Admin"
# Set the link url for the title. For example, to take
# users to your main site. Defaults to no link.
#
- # config.site_title_link = "/"
+ config.site_title_link = "/"
# Set an optional image to be displayed for the header
# instead of a string (overrides :site_title)
diff --git a/config/initializers/friendly_id.rb b/config/initializers/friendly_id.rb
new file mode 100644
index 0000000..5852b58
--- /dev/null
+++ b/config/initializers/friendly_id.rb
@@ -0,0 +1,107 @@
+# FriendlyId Global Configuration
+#
+# Use this to set up shared configuration options for your entire application.
+# Any of the configuration options shown here can also be applied to single
+# models by passing arguments to the `friendly_id` class method or defining
+# methods in your model.
+#
+# To learn more, check out the guide:
+#
+# http://norman.github.io/friendly_id/file.Guide.html
+
+FriendlyId.defaults do |config|
+ # ## Reserved Words
+ #
+ # Some words could conflict with Rails's routes when used as slugs, or are
+ # undesirable to allow as slugs. Edit this list as needed for your app.
+ config.use :reserved
+
+ config.reserved_words = %w[new edit index session login logout users admin
+ stylesheets assets javascripts images]
+
+ # This adds an option to treat reserved words as conflicts rather than exceptions.
+ # When there is no good candidate, a UUID will be appended, matching the existing
+ # conflict behavior.
+
+ # config.treat_reserved_as_conflict = true
+
+ # ## Friendly Finders
+ #
+ # Uncomment this to use friendly finders in all models. By default, if
+ # you wish to find a record by its friendly id, you must do:
+ #
+ # MyModel.friendly.find('foo')
+ #
+ # If you uncomment this, you can do:
+ #
+ # MyModel.find('foo')
+ #
+ # This is significantly more convenient but may not be appropriate for
+ # all applications, so you must explicitly opt-in to this behavior. You can
+ # always also configure it on a per-model basis if you prefer.
+ #
+ # Something else to consider is that using the :finders addon boosts
+ # performance because it will avoid Rails-internal code that makes runtime
+ # calls to `Module.extend`.
+ #
+ # config.use :finders
+ #
+ # ## Slugs
+ #
+ # Most applications will use the :slugged module everywhere. If you wish
+ # to do so, uncomment the following line.
+ #
+ # config.use :slugged
+ #
+ # By default, FriendlyId's :slugged addon expects the slug column to be named
+ # 'slug', but you can change it if you wish.
+ #
+ # config.slug_column = 'slug'
+ #
+ # By default, slug has no size limit, but you can change it if you wish.
+ #
+ # config.slug_limit = 255
+ #
+ # When FriendlyId can not generate a unique ID from your base method, it appends
+ # a UUID, separated by a single dash. You can configure the character used as the
+ # separator. If you're upgrading from FriendlyId 4, you may wish to replace this
+ # with two dashes.
+ #
+ # config.sequence_separator = '-'
+ #
+ # Note that you must use the :slugged addon **prior** to the line which
+ # configures the sequence separator, or else FriendlyId will raise an undefined
+ # method error.
+ #
+ # ## Tips and Tricks
+ #
+ # ### Controlling when slugs are generated
+ #
+ # As of FriendlyId 5.0, new slugs are generated only when the slug field is
+ # nil, but if you're using a column as your base method can change this
+ # behavior by overriding the `should_generate_new_friendly_id?` method that
+ # FriendlyId adds to your model. The change below makes FriendlyId 5.0 behave
+ # more like 4.0.
+ # Note: Use(include) Slugged module in the config if using the anonymous module.
+ # If you have `friendly_id :name, use: slugged` in the model, Slugged module
+ # is included after the anonymous module defined in the initializer, so it
+ # overrides the `should_generate_new_friendly_id?` method from the anonymous module.
+ #
+ # config.use :slugged
+ # config.use Module.new {
+ # def should_generate_new_friendly_id?
+ # slug.blank? || _changed?
+ # end
+ # }
+ #
+ # FriendlyId uses Rails's `parameterize` method to generate slugs, but for
+ # languages that don't use the Roman alphabet, that's not usually sufficient.
+ # Here we use the Babosa library to transliterate Russian Cyrillic slugs to
+ # ASCII. If you use this, don't forget to add "babosa" to your Gemfile.
+ #
+ # config.use Module.new {
+ # def normalize_friendly_id(text)
+ # text.to_slug.normalize! :transliterations => [:russian, :latin]
+ # end
+ # }
+end
diff --git a/config/routes.rb b/config/routes.rb
index a281fe2..026b4a6 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,20 @@
Rails.application.routes.draw do
+ root "home#index"
+
+ resources :cities, only: [ :index, :show ] do
+ resources :weather_arts, only: [ :show ]
+ end
+
+ # namespace :admin do
+ # resources :cities
+ # resources :weather_arts
+ # root to: "cities#index"
+ # end
+
+ get "weather_arts/show"
+ get "cities/index"
+ get "cities/show"
+ get "home/index"
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
diff --git a/db/migrate/20250119022826_create_cities.rb b/db/migrate/20250119022826_create_cities.rb
new file mode 100644
index 0000000..9187f1a
--- /dev/null
+++ b/db/migrate/20250119022826_create_cities.rb
@@ -0,0 +1,18 @@
+class CreateCities < ActiveRecord::Migration[8.0]
+ def change
+ create_table :cities do |t|
+ t.string :name
+ t.string :country
+ t.float :latitude
+ t.float :longitude
+ t.boolean :active
+ t.integer :priority
+ t.string :timezone
+ t.string :region
+ t.datetime :last_weather_fetch
+ t.datetime :last_image_generation
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20250119032146_add_slug_to_cities.rb b/db/migrate/20250119032146_add_slug_to_cities.rb
new file mode 100644
index 0000000..cb547ed
--- /dev/null
+++ b/db/migrate/20250119032146_add_slug_to_cities.rb
@@ -0,0 +1,6 @@
+class AddSlugToCities < ActiveRecord::Migration[8.0]
+ def change
+ add_column :cities, :slug, :string
+ add_index :cities, :slug, unique: true
+ end
+end
diff --git a/db/migrate/20250119032158_create_friendly_id_slugs.rb b/db/migrate/20250119032158_create_friendly_id_slugs.rb
new file mode 100644
index 0000000..a09491d
--- /dev/null
+++ b/db/migrate/20250119032158_create_friendly_id_slugs.rb
@@ -0,0 +1,21 @@
+MIGRATION_CLASS =
+ if ActiveRecord::VERSION::MAJOR >= 5
+ ActiveRecord::Migration["#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"]
+ else
+ ActiveRecord::Migration
+ end
+
+class CreateFriendlyIdSlugs < MIGRATION_CLASS
+ def change
+ create_table :friendly_id_slugs do |t|
+ t.string :slug, null: false
+ t.integer :sluggable_id, null: false
+ t.string :sluggable_type, limit: 50
+ t.string :scope
+ t.datetime :created_at
+ end
+ add_index :friendly_id_slugs, [:sluggable_type, :sluggable_id]
+ add_index :friendly_id_slugs, [:slug, :sluggable_type], length: {slug: 140, sluggable_type: 50}
+ add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], length: {slug: 70, sluggable_type: 50, scope: 70}, unique: true
+ end
+end
diff --git a/db/migrate/20250119032316_create_weather_arts.rb b/db/migrate/20250119032316_create_weather_arts.rb
new file mode 100644
index 0000000..022627c
--- /dev/null
+++ b/db/migrate/20250119032316_create_weather_arts.rb
@@ -0,0 +1,21 @@
+class CreateWeatherArts < ActiveRecord::Migration[8.0]
+ def change
+ create_table :weather_arts do |t|
+ t.references :city, null: false, foreign_key: true
+ t.date :weather_date
+ t.string :description
+ t.decimal :temperature
+ t.decimal :feeling_temp
+ t.decimal :humidity
+ t.string :wind_scale
+ t.decimal :wind_speed
+ t.decimal :precipitation
+ t.decimal :pressure
+ t.decimal :visibility
+ t.decimal :cloud
+ t.text :prompt
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20250119032348_create_active_storage_tables.active_storage.rb b/db/migrate/20250119032348_create_active_storage_tables.active_storage.rb
new file mode 100644
index 0000000..6bd8bd0
--- /dev/null
+++ b/db/migrate/20250119032348_create_active_storage_tables.active_storage.rb
@@ -0,0 +1,57 @@
+# This migration comes from active_storage (originally 20170806125915)
+class CreateActiveStorageTables < ActiveRecord::Migration[7.0]
+ def change
+ # Use Active Record's configured type for primary and foreign keys
+ primary_key_type, foreign_key_type = primary_and_foreign_key_types
+
+ create_table :active_storage_blobs, id: primary_key_type do |t|
+ t.string :key, null: false
+ t.string :filename, null: false
+ t.string :content_type
+ t.text :metadata
+ t.string :service_name, null: false
+ t.bigint :byte_size, null: false
+ t.string :checksum
+
+ if connection.supports_datetime_with_precision?
+ t.datetime :created_at, precision: 6, null: false
+ else
+ t.datetime :created_at, null: false
+ end
+
+ t.index [ :key ], unique: true
+ end
+
+ create_table :active_storage_attachments, id: primary_key_type do |t|
+ t.string :name, null: false
+ t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type
+ t.references :blob, null: false, type: foreign_key_type
+
+ if connection.supports_datetime_with_precision?
+ t.datetime :created_at, precision: 6, null: false
+ else
+ t.datetime :created_at, null: false
+ end
+
+ t.index [ :record_type, :record_id, :name, :blob_id ], name: :index_active_storage_attachments_uniqueness, unique: true
+ t.foreign_key :active_storage_blobs, column: :blob_id
+ end
+
+ create_table :active_storage_variant_records, id: primary_key_type do |t|
+ t.belongs_to :blob, null: false, index: false, type: foreign_key_type
+ t.string :variation_digest, null: false
+
+ t.index [ :blob_id, :variation_digest ], name: :index_active_storage_variant_records_uniqueness, unique: true
+ t.foreign_key :active_storage_blobs, column: :blob_id
+ end
+ end
+
+ private
+ def primary_and_foreign_key_types
+ config = Rails.configuration.generators
+ setting = config.options[config.orm][:primary_key_type]
+ primary_key_type = setting || :primary_key
+ foreign_key_type = setting || :bigint
+ [ primary_key_type, foreign_key_type ]
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index b433d02..de46ad8 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[8.0].define(version: 2025_01_18_163460) do
+ActiveRecord::Schema[8.0].define(version: 2025_01_19_032348) do
create_table "active_admin_comments", force: :cascade do |t|
t.string "namespace"
t.text "body"
@@ -25,6 +25,34 @@ ActiveRecord::Schema[8.0].define(version: 2025_01_18_163460) do
t.index ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource"
end
+ create_table "active_storage_attachments", force: :cascade do |t|
+ t.string "name", null: false
+ t.string "record_type", null: false
+ t.bigint "record_id", null: false
+ t.bigint "blob_id", null: false
+ t.datetime "created_at", null: false
+ t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
+ t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
+ end
+
+ create_table "active_storage_blobs", force: :cascade do |t|
+ t.string "key", null: false
+ t.string "filename", null: false
+ t.string "content_type"
+ t.text "metadata"
+ t.string "service_name", null: false
+ t.bigint "byte_size", null: false
+ t.string "checksum"
+ t.datetime "created_at", null: false
+ t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
+ end
+
+ create_table "active_storage_variant_records", force: :cascade do |t|
+ t.bigint "blob_id", null: false
+ t.string "variation_digest", null: false
+ t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
+ end
+
create_table "admin_users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
@@ -36,4 +64,55 @@ ActiveRecord::Schema[8.0].define(version: 2025_01_18_163460) do
t.index ["email"], name: "index_admin_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true
end
+
+ create_table "cities", force: :cascade do |t|
+ t.string "name"
+ t.string "country"
+ t.float "latitude"
+ t.float "longitude"
+ t.boolean "active"
+ t.integer "priority"
+ t.string "timezone"
+ t.string "region"
+ t.datetime "last_weather_fetch"
+ t.datetime "last_image_generation"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.string "slug"
+ t.index ["slug"], name: "index_cities_on_slug", unique: true
+ end
+
+ create_table "friendly_id_slugs", force: :cascade do |t|
+ t.string "slug", null: false
+ t.integer "sluggable_id", null: false
+ t.string "sluggable_type", limit: 50
+ t.string "scope"
+ t.datetime "created_at"
+ t.index ["slug", "sluggable_type", "scope"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type_and_scope", unique: true
+ t.index ["slug", "sluggable_type"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type"
+ t.index ["sluggable_type", "sluggable_id"], name: "index_friendly_id_slugs_on_sluggable_type_and_sluggable_id"
+ end
+
+ create_table "weather_arts", force: :cascade do |t|
+ t.integer "city_id", null: false
+ t.date "weather_date"
+ t.string "description"
+ t.decimal "temperature"
+ t.decimal "feeling_temp"
+ t.decimal "humidity"
+ t.string "wind_scale"
+ t.decimal "wind_speed"
+ t.decimal "precipitation"
+ t.decimal "pressure"
+ t.decimal "visibility"
+ t.decimal "cloud"
+ t.text "prompt"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["city_id"], name: "index_weather_arts_on_city_id"
+ end
+
+ 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 "weather_arts", "cities"
end
diff --git a/db/seeds.rb b/db/seeds.rb
index 0874563..07b096c 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -7,4 +7,39 @@
# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name|
# MovieGenre.find_or_create_by!(name: genre_name)
# end
-AdminUser.create!(email: 'admin@example.com', password: 'password', password_confirmation: 'password') if Rails.env.development?
\ No newline at end of file
+AdminUser.create!(email: 'admin@example.com', password: 'password', password_confirmation: 'password') if Rails.env.development?
+
+guangzhou = City.create!(
+ name: 'Guangzhou',
+ country: 'China',
+ latitude: 23.1291,
+ longitude: 113.2644,
+ active: true,
+ priority: 50,
+ timezone: 'Asia/Shanghai',
+ region: 'Asia',
+ last_weather_fetch: 10.hours.ago,
+ last_image_generation: 10.hours.ago
+)
+
+guangzhou_weather_art = WeatherArt.create!(
+ city: guangzhou,
+ weather_date: Date.today,
+ description: 'Sunny with some clouds',
+ temperature: 28.5,
+ feeling_temp: 30.2,
+ humidity: 65,
+ wind_scale: "3级",
+ wind_speed: 15,
+ precipitation: 0,
+ pressure: 1013,
+ visibility: 10,
+ cloud: 30,
+ prompt: "A sunny day in Guangzhou with modern buildings under blue sky and white clouds, digital art style"
+)
+
+guangzhou_weather_art.image.attach(
+ io: File.open("db/seeds/images/sample-guangzhou-weather-art.png"),
+ filename: "sample-guangzhou-weather-art.png",
+ content_type: "image/png"
+)
\ No newline at end of file
diff --git a/db/seeds/images/sample-guangzhou-weather-art.png b/db/seeds/images/sample-guangzhou-weather-art.png
new file mode 100644
index 0000000..fb04d62
Binary files /dev/null and b/db/seeds/images/sample-guangzhou-weather-art.png differ
diff --git a/test/controllers/cities_controller_test.rb b/test/controllers/cities_controller_test.rb
new file mode 100644
index 0000000..f232f79
--- /dev/null
+++ b/test/controllers/cities_controller_test.rb
@@ -0,0 +1,13 @@
+require "test_helper"
+
+class CitiesControllerTest < ActionDispatch::IntegrationTest
+ test "should get index" do
+ get cities_index_url
+ assert_response :success
+ end
+
+ test "should get show" do
+ get cities_show_url
+ assert_response :success
+ end
+end
diff --git a/test/controllers/home_controller_test.rb b/test/controllers/home_controller_test.rb
new file mode 100644
index 0000000..f6f3785
--- /dev/null
+++ b/test/controllers/home_controller_test.rb
@@ -0,0 +1,8 @@
+require "test_helper"
+
+class HomeControllerTest < ActionDispatch::IntegrationTest
+ test "should get index" do
+ get home_index_url
+ assert_response :success
+ end
+end
diff --git a/test/controllers/weather_arts_controller_test.rb b/test/controllers/weather_arts_controller_test.rb
new file mode 100644
index 0000000..f768179
--- /dev/null
+++ b/test/controllers/weather_arts_controller_test.rb
@@ -0,0 +1,8 @@
+require "test_helper"
+
+class WeatherArtsControllerTest < ActionDispatch::IntegrationTest
+ test "should get show" do
+ get weather_arts_show_url
+ assert_response :success
+ end
+end
diff --git a/test/fixtures/cities.yml b/test/fixtures/cities.yml
new file mode 100644
index 0000000..b1abf5f
--- /dev/null
+++ b/test/fixtures/cities.yml
@@ -0,0 +1,29 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+#one:
+# name: MyString
+# country: MyString
+# slug: MyString
+# latitude: 1.5
+# longitude: 1.5
+# active: false
+# priority: 1
+# timezone: MyString
+# population: 1
+# region: MyString
+# last_weather_fetch: 2025-01-19 10:28:26
+# last_image_generation: 2025-01-19 10:28:26
+#
+#two:
+# name: MyString
+# country: MyString
+# slug: MyString
+# latitude: 1.5
+# longitude: 1.5
+# active: false
+# priority: 1
+# timezone: MyString
+# population: 1
+# region: MyString
+# last_weather_fetch: 2025-01-19 10:28:26
+# last_image_generation: 2025-01-19 10:28:26
diff --git a/test/fixtures/weather_arts.yml b/test/fixtures/weather_arts.yml
new file mode 100644
index 0000000..1ebf909
--- /dev/null
+++ b/test/fixtures/weather_arts.yml
@@ -0,0 +1,31 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ city: one
+ weather_date: 2025-01-19
+ description: MyString
+ temperature: 9.99
+ feeling_temp: 9.99
+ humidity: 9.99
+ wind_scale: MyString
+ wind_speed: 9.99
+ precipitation: 9.99
+ pressure: 9.99
+ visibility: 9.99
+ cloud: 9.99
+ prompt: MyText
+
+two:
+ city: two
+ weather_date: 2025-01-19
+ description: MyString
+ temperature: 9.99
+ feeling_temp: 9.99
+ humidity: 9.99
+ wind_scale: MyString
+ wind_speed: 9.99
+ precipitation: 9.99
+ pressure: 9.99
+ visibility: 9.99
+ cloud: 9.99
+ prompt: MyText
diff --git a/test/models/city_test.rb b/test/models/city_test.rb
new file mode 100644
index 0000000..a294ebc
--- /dev/null
+++ b/test/models/city_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class CityTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/weather_art_test.rb b/test/models/weather_art_test.rb
new file mode 100644
index 0000000..f00458e
--- /dev/null
+++ b/test/models/weather_art_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class WeatherArtTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end