From 687ccf860feebf1bd2997cb79355bd5ebbcf6895 Mon Sep 17 00:00:00 2001 From: OmarMWarraich Date: Tue, 2 Jul 2024 02:43:13 +0500 Subject: [PATCH 1/5] feat: Install ActiveStorage --- db/schema.rb | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/db/schema.rb b/db/schema.rb index 476e0a5..51e8931 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,10 +10,38 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_07_01_172911) do +ActiveRecord::Schema[7.1].define(version: 2024_07_01_214248) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + 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 "progress_holders", force: :cascade do |t| t.string "task_ref" t.integer "live_preview_id" @@ -31,5 +59,7 @@ t.datetime "updated_at", null: false 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 "progress_holders", "users" end From b4cdb5a212f3b65181a3fe70d7566a1612c97d85 Mon Sep 17 00:00:00 2001 From: OmarMWarraich Date: Tue, 2 Jul 2024 03:14:26 +0500 Subject: [PATCH 2/5] feat: Active Storage --- config/environments/development.rb | 2 + ...te_active_storage_tables.active_storage.rb | 57 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 db/migrate/20240701214248_create_active_storage_tables.active_storage.rb diff --git a/config/environments/development.rb b/config/environments/development.rb index 4a6f537..532181f 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -88,3 +88,5 @@ config.action_mailer.perform_deliveries = true config.action_mailer.raise_delivery_errors = true end + +Rails.application.default_url_options = { host: "localhost", port: 3000 } diff --git a/db/migrate/20240701214248_create_active_storage_tables.active_storage.rb b/db/migrate/20240701214248_create_active_storage_tables.active_storage.rb new file mode 100644 index 0000000..e4706aa --- /dev/null +++ b/db/migrate/20240701214248_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 From c1ee279892d2814f0f9c8170d6bbe9c5f9cc4abc Mon Sep 17 00:00:00 2001 From: OmarMWarraich Date: Tue, 2 Jul 2024 03:18:33 +0500 Subject: [PATCH 3/5] feat: Model GeneratedImage --- app/models/generated_image.rb | 4 ++++ .../20240701221718_create_generated_images.rb | 14 ++++++++++++++ db/schema.rb | 15 ++++++++++++++- test/fixtures/generated_images.yml | 17 +++++++++++++++++ test/models/generated_image_test.rb | 7 +++++++ 5 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 app/models/generated_image.rb create mode 100644 db/migrate/20240701221718_create_generated_images.rb create mode 100644 test/fixtures/generated_images.yml create mode 100644 test/models/generated_image_test.rb diff --git a/app/models/generated_image.rb b/app/models/generated_image.rb new file mode 100644 index 0000000..2e6efab --- /dev/null +++ b/app/models/generated_image.rb @@ -0,0 +1,4 @@ +class GeneratedImage < ApplicationRecord + belongs_to :user + has_one_attached :sketch +end diff --git a/db/migrate/20240701221718_create_generated_images.rb b/db/migrate/20240701221718_create_generated_images.rb new file mode 100644 index 0000000..25ad21b --- /dev/null +++ b/db/migrate/20240701221718_create_generated_images.rb @@ -0,0 +1,14 @@ +class CreateGeneratedImages < ActiveRecord::Migration[7.1] + def change + create_table :generated_images do |t| + t.string :prompt + t.string :negative_prompt + t.string :style_template + t.references :user, null: false, foreign_key: true + t.json :info + t.json :parameters + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 51e8931..1edf723 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[7.1].define(version: 2024_07_01_214248) do +ActiveRecord::Schema[7.1].define(version: 2024_07_01_221718) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -42,6 +42,18 @@ t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true end + create_table "generated_images", force: :cascade do |t| + t.string "prompt" + t.string "negative_prompt" + t.string "style_template" + t.bigint "user_id", null: false + t.json "info" + t.json "parameters" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["user_id"], name: "index_generated_images_on_user_id" + end + create_table "progress_holders", force: :cascade do |t| t.string "task_ref" t.integer "live_preview_id" @@ -61,5 +73,6 @@ 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 "generated_images", "users" add_foreign_key "progress_holders", "users" end diff --git a/test/fixtures/generated_images.yml b/test/fixtures/generated_images.yml new file mode 100644 index 0000000..039e427 --- /dev/null +++ b/test/fixtures/generated_images.yml @@ -0,0 +1,17 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + prompt: MyString + negative_prompt: MyString + style_template: MyString + user: one + info: + parameters: + +two: + prompt: MyString + negative_prompt: MyString + style_template: MyString + user: two + info: + parameters: diff --git a/test/models/generated_image_test.rb b/test/models/generated_image_test.rb new file mode 100644 index 0000000..9c5800c --- /dev/null +++ b/test/models/generated_image_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class GeneratedImageTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end From e7397c5acccbcb46f169637ee93ef3e7678aaec3 Mon Sep 17 00:00:00 2001 From: OmarMWarraich Date: Tue, 2 Jul 2024 03:25:45 +0500 Subject: [PATCH 4/5] feat: Annotate Models --- app/models/generated_image.rb | 22 +++++++++++ app/models/progress_holder.rb | 13 ++++++- lib/tasks/auto_annotate_models.rake | 59 +++++++++++++++++++++++++++++ test/fixtures/generated_images.yml | 23 ++++++++++- test/fixtures/progress_holders.yml | 21 +++++++++- test/fixtures/users.yml | 11 +++++- test/models/generated_image_test.rb | 22 +++++++++++ test/models/progress_holder_test.rb | 13 ++++++- 8 files changed, 177 insertions(+), 7 deletions(-) create mode 100644 lib/tasks/auto_annotate_models.rake diff --git a/app/models/generated_image.rb b/app/models/generated_image.rb index 2e6efab..212cbf6 100644 --- a/app/models/generated_image.rb +++ b/app/models/generated_image.rb @@ -1,3 +1,25 @@ +# == Schema Information +# +# Table name: generated_images +# +# id :bigint not null, primary key +# info :json +# negative_prompt :string +# parameters :json +# prompt :string +# style_template :string +# created_at :datetime not null +# updated_at :datetime not null +# user_id :bigint not null +# +# Indexes +# +# index_generated_images_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (user_id => users.id) +# class GeneratedImage < ApplicationRecord belongs_to :user has_one_attached :sketch diff --git a/app/models/progress_holder.rb b/app/models/progress_holder.rb index 910348f..7969bce 100644 --- a/app/models/progress_holder.rb +++ b/app/models/progress_holder.rb @@ -4,10 +4,19 @@ # # id :bigint not null, primary key # task_ref :string -# live_preview_id :integer -# user_id :bigint not null # created_at :datetime not null # updated_at :datetime not null +# live_preview_id :integer +# user_id :bigint not null +# +# Indexes +# +# index_progress_holders_on_task_ref (task_ref) UNIQUE +# index_progress_holders_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (user_id => users.id) # class ProgressHolder < ApplicationRecord include ActionView::RecordIdentifier diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake new file mode 100644 index 0000000..e96283e --- /dev/null +++ b/lib/tasks/auto_annotate_models.rake @@ -0,0 +1,59 @@ +# NOTE: only doing this in development as some production environments (Heroku) +# NOTE: are sensitive to local FS writes, and besides -- it's just not proper +# NOTE: to have a dev-mode tool do its thing in production. +if Rails.env.development? + require 'annotate' + task :set_annotation_options do + # You can override any of these by setting an environment variable of the + # same name. + Annotate.set_defaults( + 'active_admin' => 'false', + 'additional_file_patterns' => [], + 'routes' => 'false', + 'models' => 'true', + 'position_in_routes' => 'before', + 'position_in_class' => 'before', + 'position_in_test' => 'before', + 'position_in_fixture' => 'before', + 'position_in_factory' => 'before', + 'position_in_serializer' => 'before', + 'show_foreign_keys' => 'true', + 'show_complete_foreign_keys' => 'false', + 'show_indexes' => 'true', + 'simple_indexes' => 'false', + 'model_dir' => 'app/models', + 'root_dir' => '', + 'include_version' => 'false', + 'require' => '', + 'exclude_tests' => 'false', + 'exclude_fixtures' => 'false', + 'exclude_factories' => 'false', + 'exclude_serializers' => 'false', + 'exclude_scaffolds' => 'true', + 'exclude_controllers' => 'true', + 'exclude_helpers' => 'true', + 'exclude_sti_subclasses' => 'false', + 'ignore_model_sub_dir' => 'false', + 'ignore_columns' => nil, + 'ignore_routes' => nil, + 'ignore_unknown_models' => 'false', + 'hide_limit_column_types' => 'integer,bigint,boolean', + 'hide_default_column_types' => 'json,jsonb,hstore', + 'skip_on_db_migrate' => 'false', + 'format_bare' => 'true', + 'format_rdoc' => 'false', + 'format_yard' => 'false', + 'format_markdown' => 'false', + 'sort' => 'false', + 'force' => 'false', + 'frozen' => 'false', + 'classified_sort' => 'true', + 'trace' => 'false', + 'wrapper_open' => nil, + 'wrapper_close' => nil, + 'with_comment' => 'true' + ) + end + + Annotate.load_tasks +end diff --git a/test/fixtures/generated_images.yml b/test/fixtures/generated_images.yml index 039e427..bb60cbc 100644 --- a/test/fixtures/generated_images.yml +++ b/test/fixtures/generated_images.yml @@ -1,4 +1,25 @@ -# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html +# == Schema Information +# +# Table name: generated_images +# +# id :bigint not null, primary key +# info :json +# negative_prompt :string +# parameters :json +# prompt :string +# style_template :string +# created_at :datetime not null +# updated_at :datetime not null +# user_id :bigint not null +# +# Indexes +# +# index_generated_images_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (user_id => users.id) +# one: prompt: MyString diff --git a/test/fixtures/progress_holders.yml b/test/fixtures/progress_holders.yml index 1b246da..d861eb4 100644 --- a/test/fixtures/progress_holders.yml +++ b/test/fixtures/progress_holders.yml @@ -1,4 +1,23 @@ -# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html +# == Schema Information +# +# Table name: progress_holders +# +# id :bigint not null, primary key +# task_ref :string +# created_at :datetime not null +# updated_at :datetime not null +# live_preview_id :integer +# user_id :bigint not null +# +# Indexes +# +# index_progress_holders_on_task_ref (task_ref) UNIQUE +# index_progress_holders_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (user_id => users.id) +# one: task_ref: MyString diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index 0f1914f..10a70b4 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -1,4 +1,13 @@ -# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html +# == Schema Information +# +# Table name: users +# +# id :bigint not null, primary key +# email :string +# password_digest :string +# created_at :datetime not null +# updated_at :datetime not null +# one: email: MyString diff --git a/test/models/generated_image_test.rb b/test/models/generated_image_test.rb index 9c5800c..523d092 100644 --- a/test/models/generated_image_test.rb +++ b/test/models/generated_image_test.rb @@ -1,3 +1,25 @@ +# == Schema Information +# +# Table name: generated_images +# +# id :bigint not null, primary key +# info :json +# negative_prompt :string +# parameters :json +# prompt :string +# style_template :string +# created_at :datetime not null +# updated_at :datetime not null +# user_id :bigint not null +# +# Indexes +# +# index_generated_images_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (user_id => users.id) +# require "test_helper" class GeneratedImageTest < ActiveSupport::TestCase diff --git a/test/models/progress_holder_test.rb b/test/models/progress_holder_test.rb index 6c71f8a..e1d76db 100644 --- a/test/models/progress_holder_test.rb +++ b/test/models/progress_holder_test.rb @@ -4,10 +4,19 @@ # # id :bigint not null, primary key # task_ref :string -# live_preview_id :integer -# user_id :bigint not null # created_at :datetime not null # updated_at :datetime not null +# live_preview_id :integer +# user_id :bigint not null +# +# Indexes +# +# index_progress_holders_on_task_ref (task_ref) UNIQUE +# index_progress_holders_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (user_id => users.id) # require "test_helper" From 765cdbdba65236a29b3835bbffdf430caab68aef Mon Sep 17 00:00:00 2001 From: OmarMWarraich Date: Tue, 23 Jul 2024 15:30:53 +0500 Subject: [PATCH 5/5] feat: Store Images --- Gemfile | 2 ++ Gemfile.lock | 4 +++ app/controllers/txt2_imgs_controller.rb | 8 +---- app/jobs/sd_render_job.rb | 9 ++--- app/models/generated_image.rb | 34 +++++++++++++++++++ app/models/user.rb | 2 ++ .../_display_main_image.html.erb | 1 + config/environments/development.rb | 2 +- 8 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 app/views/generated_images/_display_main_image.html.erb diff --git a/Gemfile b/Gemfile index bb8d2ef..42e2751 100644 --- a/Gemfile +++ b/Gemfile @@ -77,3 +77,5 @@ gem 'font-awesome-sass', '~> 5.15.1' gem 'ruby-stableDiffusion', path: '/home/owa/Docs/ror/ruby-stablediffusion/' gem "sidekiq" + +gem "ruby-vips", "~> 2.2" diff --git a/Gemfile.lock b/Gemfile.lock index ee64089..ac42444 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -248,6 +248,9 @@ GEM io-console (~> 0.5) rexml (3.3.0) strscan + ruby-vips (2.2.2) + ffi (~> 1.12) + logger rubyzip (2.3.2) sassc (2.4.0) ffi (~> 1.9) @@ -329,6 +332,7 @@ DEPENDENCIES rails (~> 7.1.3, >= 7.1.3.4) redis (>= 4.0.1) ruby-stableDiffusion! + ruby-vips (~> 2.2) sassc-rails (~> 2.1) selenium-webdriver sidekiq diff --git a/app/controllers/txt2_imgs_controller.rb b/app/controllers/txt2_imgs_controller.rb index 7510911..965ac7d 100644 --- a/app/controllers/txt2_imgs_controller.rb +++ b/app/controllers/txt2_imgs_controller.rb @@ -37,6 +37,7 @@ def create sd_settings = { original_prompt: image_create_params[:prompt], + style_template: image_create_params[:style_template], prompt: merged_prompt, negative_prompt: merged_negative_prompt, sampler_name: 'DPM++ 2M Karras', @@ -55,13 +56,6 @@ def create render turbo_stream: turbo_stream.replace( 'process_starting', partial: '/txt2_imgs/process_starting' - ) + - turbo_stream.replace( - 'image_maker', - partial: '/txt2_imgs/image_maker', - locals: { - render_result: render_result, - } ) end end diff --git a/app/jobs/sd_render_job.rb b/app/jobs/sd_render_job.rb index f3c4dec..d6ed1ca 100644 --- a/app/jobs/sd_render_job.rb +++ b/app/jobs/sd_render_job.rb @@ -2,8 +2,6 @@ class SdRenderJob < ApplicationJob queue_as :default def perform(render_settings, user_id) - original_prompt = render_settings.delete(:original_prompt) - style_template = render_settings.delete(:style_template) config = RStableDiffusionAI::Configuration.new config.host = ENV['SD_API_HOST'] @@ -19,9 +17,12 @@ def perform(render_settings, user_id) render_settings[:task_id] = our_task_id render_settings[:id_task] = our_task_id - ImgProgressJob.perform_later(our_task_id, user_id, original_prompt, style_template) + ImgProgressJob.perform_later(our_task_id, user_id, render_settings[:original_prompt], render_settings[:style_template]) - result = api_instance.text2imgapi_sdapi_v1_txt2img_post(render_settings) + result = api_instance.text2imgapi_sdapi_v1_txt2img_post(render_settings.except(:original_prompt, :style_template)) + GeneratedImage.create_from_sd_render_job(render_settings, user_id, result) + + result end end diff --git a/app/models/generated_image.rb b/app/models/generated_image.rb index 212cbf6..b7aa451 100644 --- a/app/models/generated_image.rb +++ b/app/models/generated_image.rb @@ -21,6 +21,40 @@ # fk_rails_... (user_id => users.id) # class GeneratedImage < ApplicationRecord + include ActionView::RecordIdentifier + belongs_to :user has_one_attached :sketch + + after_create_commit { broadcast_created } + + def broadcast_created + broadcast_update_to( + "#{dom_id(user)}_main_image", + partial: "generated_images/display_main_image", + locals: { + scroll_to: true, + generated_image: self + }, + target: "image_maker" + ) + end + + def self.create_from_sd_render_job(render_settings, user_id, result) + user = User.find(user_id) + result.images.each do |src_image| + generated_image = user.generated_images.create( + prompt: render_settings[:original_prompt], + negative_prompt: render_settings[:negative_prompt], + style_template: render_settings[:style_template], + parameters: result.parameters, + info: result.info, + sketch: { + io: StringIO.new(Base64.decode64(src_image)), + content_type: 'image/png', + filename: "#{render_settings[:original_prompt]}-#{SecureRandom.uuid}.png".last(256) + } + ) + end + end end diff --git a/app/models/user.rb b/app/models/user.rb index 55512d6..890c795 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -14,6 +14,8 @@ class User < ApplicationRecord normalizes :email, with: ->(email) { email.strip.downcase } + has_many :generated_images, dependent: :destroy + generates_token_for :password_reset, expires_in: 10.minutes do password_salt&.last(10) end diff --git a/app/views/generated_images/_display_main_image.html.erb b/app/views/generated_images/_display_main_image.html.erb new file mode 100644 index 0000000..267ca44 --- /dev/null +++ b/app/views/generated_images/_display_main_image.html.erb @@ -0,0 +1 @@ +<%= image_tag generated_image.sketch, alt: "#{generated_image.info}", class: "img-fluid" %> \ No newline at end of file diff --git a/config/environments/development.rb b/config/environments/development.rb index 532181f..481b75e 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -89,4 +89,4 @@ config.action_mailer.raise_delivery_errors = true end -Rails.application.default_url_options = { host: "localhost", port: 3000 } +Rails.application.routes.default_url_options = { host: "localhost", port: 3000 }