Rails 6. Перенос вложенного файла из экземпляра одной модели в экземпляр другой модели - PullRequest
0 голосов
/ 11 января 2020

У меня есть модель User и модель Spkr.

Пользователь:

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  has_many :tlks, dependent: :destroy
  has_many :spkrs, dependent: :destroy
  has_many :msgs, dependent: :destroy

  has_one_attached :image

  extend FriendlyId
  friendly_id :slug_candidates, use: :slugged

  def slug_candidates
    [
      :username,
      [:username, DateTime.now.to_date]
    ]
  end
end

Spkr

class Spkr < ApplicationRecord
  belongs_to :tlk
  belongs_to :user
  has_many :msgs, dependent: :destroy

  has_one_attached :image
end

Когда к моей модели пользователя прикреплено изображение, когда spkr сделан, я хочу, чтобы к нему было прикреплено то же изображение, что и для пользователя, генерирующего spkr.

У меня есть модуль SpkrMaker:

module SpkrMaker
  def make_spkr
    spkr = Spkr.create!(
      user: current_user,
      tlk: @tlk,
      name: current_user.username,
      bio: current_user.bio,
    )
    if current_user.image.present?
      ActiveStorage::Attachment.create(
        name: 'image',
        record_type: 'Spkr',
        record_id: spkr.id,
        blob_id: current_user.image.id
      )
    end
  end
end

Это вызывается во время потока, когда он называется состояние журнала моего сервера:

    Started POST "/tlks" for ::1 at 2020-01-11 10:39:41 +0000
Processing by TlksController#create as JS
  Parameters: {"authenticity_token"=>"1NJc0ZSwo8hL1JHw5karkWNxoWRzHPNx/xecaAQHdN+EdsG/o+yZwdxZXLZLPVbkgiPiZZX6PpaF38VX5etTAw==", "tlk"=>{"title"=>"goooolan"}, "commit"=>"Create Tlk"}
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 23], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  ↳ app/controllers/tlks_controller.rb:34:in `create'
  Tlk Exists? (0.3ms)  SELECT 1 AS one FROM "tlks" WHERE "tlks"."id" IS NOT NULL AND "tlks"."slug" = ? LIMIT ?  [["slug", "goooolan"], ["LIMIT", 1]]
  ↳ app/controllers/tlks_controller.rb:34:in `create'
  Tlk Create (0.4ms)  INSERT INTO "tlks" ("user_id", "title", "created_at", "updated_at", "slug", "invite_code") VALUES (?, ?, ?, ?, ?, ?)  [["user_id", 23], ["title", "goooolan"], ["created_at", "2020-01-11 10:39:41.866979"], ["updated_at", "2020-01-11 10:39:41.866979"], ["slug", "goooolan"], ["invite_code", 469667]]
  ↳ app/controllers/tlks_controller.rb:34:in `create'
   (0.9ms)  commit transaction
  ↳ app/controllers/tlks_controller.rb:34:in `create'
   (0.1ms)  begin transaction
  ↳ lib/spkr_maker.rb:3:in `make_spkr'
  Spkr Create (0.5ms)  INSERT INTO "spkrs" ("tlk_id", "user_id", "name", "bio", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?)  [["tlk_id", 135], ["user_id", 23], ["name", "test"], ["bio", "info about me"], ["created_at", "2020-01-11 10:39:41.871219"], ["updated_at", "2020-01-11 10:39:41.871219"]]
  ↳ lib/spkr_maker.rb:3:in `make_spkr'
   (0.8ms)  commit transaction
  ↳ lib/spkr_maker.rb:3:in `make_spkr'
  ActiveStorage::Attachment Load (0.1ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 23], ["record_type", "User"], ["name", "image"], ["LIMIT", 1]]
  ↳ lib/spkr_maker.rb:9:in `make_spkr'
   (0.0ms)  begin transaction
  ↳ lib/spkr_maker.rb:10:in `make_spkr'
  Spkr Load (0.2ms)  SELECT "spkrs".* FROM "spkrs" WHERE "spkrs"."id" = ? LIMIT ?  [["id", 104], ["LIMIT", 1]]
  ↳ lib/spkr_maker.rb:10:in `make_spkr'
  ActiveStorage::Blob Load (0.0ms)  SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = ? LIMIT ?  [["id", 51], ["LIMIT", 1]]
  ↳ lib/spkr_maker.rb:10:in `make_spkr'
   (0.0ms)  rollback transaction
  ↳ lib/spkr_maker.rb:10:in `make_spkr'
Completed 422 Unprocessable Entity in 25ms (ActiveRecord: 3.7ms | Allocations: 14233)



ActiveRecord::RecordInvalid (Validation failed: Blob must exist):

lib/spkr_maker.rb:10:in `make_spkr'
app/controllers/tlks_controller.rb:36:in `create

Когда я запускаю User.last.image в консоли rails, я получаю следующее:

irb(main):002:0> User.last.image
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ?  [["LIMIT", 1]]
=> #<ActiveStorage::Attached::One:0x00007f88a21cda90 @name="image", @record=#<User id: 23, email: "j@test.com", username: "test", bio: "info about me", name: nil, created_at: "2020-01-11 01:56:22", updated_at: "2020-01-11 01:56:48", slug: "test">>
irb(main):003:0>

Я не знаю, что проблема в том, что я недостаточно хорош в понимании логов сервера, чтобы понять, что происходит не так.

Во время процесса создается Spkr, поэтому все, что находится выше строки 10, работает в модуле SpkrMaker (ActiveStorage :: Attachment.create (= строка 10).

OK. Дополнительная информация по этому вопросу утро ... (11/01/2020)

irb(main):010:0> User.last.image.id
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ?  [["LIMIT", 1]]
  ActiveStorage::Attachment Load (0.2ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 23], ["record_type", "User"], ["name", "image"], ["LIMIT", 1]]
=> 51

Но

    irb(main):011:0> ActiveStorage::Blob.last.id
  ActiveStorage::Blob Load (0.2ms)  SELECT "active_storage_blobs".* FROM "active_storage_blobs" ORDER BY "active_storage_blobs"."id" DESC LIMIT ?  [["LIMIT", 1]]
=> 49

Я не знаю, почему есть такая разница.

1 Ответ

1 голос
/ 14 января 2020

При прикреплении изображения к Spkr вы помечаете идентификатор активного хранилища для current_user вместо blob_id вместо идентификатора blob. Я обновляю код.

module SpkrMaker
  def make_spkr
    spkr = Spkr.create!(
      user: current_user,
      tlk: @tlk,
      name: current_user.username,
      bio: current_user.bio,
    )
    if current_user.image.present?
      ActiveStorage::Attachment.create(
        name: 'image',
        record_type: 'Spkr',
        record_id: spkr.id,
        blob_id: current_user.image.blob_id
      )
    end
  end
end

Теперь он должен работать.

...