clowne-rb / clowne

A flexible gem for cloning models
https://clowne.evilmartians.io
MIT License
317 stars 18 forks source link

Active Storage & Action Text #34

Closed mcanto closed 5 years ago

mcanto commented 5 years ago

How can I handle has_one_attachment like for active storage. I'm also using Rails 6 with has_rich_text and it is not being cloned.

palkan commented 5 years ago

Hey @mcanto!

For Active Storage we use the following code:

class Post < ApplicationRecord
  has_one_attached :cover
end

class PostCloner < Clowne::Cloner
  finalize do |source, record, params|
    record.cover.attach(source.cover.blob) if source.cover.attached?
  end
end

For has_many_attached it should be smth like this:

finalize do |source, record, params|
  source.images.each do |image|
    record.images.attach(image.blob)
  end
end

Never tried with Action Text but seems it uses an association for RichText model, which has many embeds. So it should be something like:

class Post < ApplicationRecord
  has_rich_text :text
end

class RichTextCloner < Clowne::Cloner
  adapter :active_record

  finalize do |source, record, params|
    source.embeds.each do |embed|
      record.embeds.attach(embed.blob)
    end
  end
end

class PostCloner < Clowne::Cloner
  # the name of the association is `:rich_text_#{name}`
  # see https://github.com/rails/rails/blob/f0445213d8f23c982d1c080a750b33d4855d46e4/actiontext/lib/action_text/attribute.rb#L37
  include_association :rich_text_text, clone_with: RichTextCloner
end
mcanto commented 5 years ago

Great! Everything works like a charm!

Thank you a lot! You are doing a great job!

salismt commented 4 years ago

Hey @mcanto!

For Active Storage we use the following code:

class Post < ApplicationRecord
  has_one_attached :cover
end

class PostCloner < Clowne::Cloner
  finalize do |source, record, params|
    record.cover.attach(source.cover.blob) if source.cover.attached?
  end
end

For has_many_attached it should be smth like this:

finalize do |source, record, params|
  source.images.each do |image|
    record.images.attach(image.blob)
  end
end

Never tried with Action Text but seems it uses an association for RichText model, which has many embeds. So it should be something like:

class Post < ApplicationRecord
  has_rich_text :text
end

class RichTextCloner < Clowne::Cloner
  adapter :active_record

  finalize do |source, record, params|
    source.embeds.each do |embed|
      record.embeds.attach(embed.blob)
    end
  end
end

class PostCloner < Clowne::Cloner
  # the name of the association is `:rich_text_#{name}`
  # see https://github.com/rails/rails/blob/f0445213d8f23c982d1c080a750b33d4855d46e4/actiontext/lib/action_text/attribute.rb#L37
  include_association :rich_text_text, clone_with: RichTextCloner
end

Hei @palkan for this solution, I am stuck at infinite loop where the source.image keep getting added as record.image.attach grows

source.images.each do |image|
    record.images.attach(image.blob)
  end

these are the logs

Enqueued ActiveStorage::AnalyzeJob
Performing ActiveStorage::AnalyzeJob
Performed ActiveStorage::AnalyzeJob
Enqueued ActiveStorage::AnalyzeJob
Performing ActiveStorage::AnalyzeJob
Performed ActiveStorage::AnalyzeJob

what is the solution for this??

also for this to work, I need to remove default unique index on table active_storage_attachments, is this expected?

salismt commented 4 years ago

Hey @mcanto! For Active Storage we use the following code:

class Post < ApplicationRecord
  has_one_attached :cover
end

class PostCloner < Clowne::Cloner
  finalize do |source, record, params|
    record.cover.attach(source.cover.blob) if source.cover.attached?
  end
end

For has_many_attached it should be smth like this:

finalize do |source, record, params|
  source.images.each do |image|
    record.images.attach(image.blob)
  end
end

Never tried with Action Text but seems it uses an association for RichText model, which has many embeds. So it should be something like:

class Post < ApplicationRecord
  has_rich_text :text
end

class RichTextCloner < Clowne::Cloner
  adapter :active_record

  finalize do |source, record, params|
    source.embeds.each do |embed|
      record.embeds.attach(embed.blob)
    end
  end
end

class PostCloner < Clowne::Cloner
  # the name of the association is `:rich_text_#{name}`
  # see https://github.com/rails/rails/blob/f0445213d8f23c982d1c080a750b33d4855d46e4/actiontext/lib/action_text/attribute.rb#L37
  include_association :rich_text_text, clone_with: RichTextCloner
end

Hei @palkan for this solution, I am stuck at infinite loop where the source.image keep getting added as record.image.attach grows

source.images.each do |image|
    record.images.attach(image.blob)
  end

these are the logs

Enqueued ActiveStorage::AnalyzeJob
Performing ActiveStorage::AnalyzeJob
Performed ActiveStorage::AnalyzeJob
Enqueued ActiveStorage::AnalyzeJob
Performing ActiveStorage::AnalyzeJob
Performed ActiveStorage::AnalyzeJob

what is the solution for this??

also for this to work, I need to remove default unique index on table active_storage_attachments, is this expected?

I have found the solution for this. first my active_storage is attached to table that has UUID as its primary key, for that I need to support it by using this migration https://gist.github.com/salismt/950dd12b0f8c256a5324d5a32fd2ac84 (note that I need to drop active storage table or make the default as string empty, then delete the existing attachment)

Then instead of using above method, I simply find the clone in my active record, and do the attachment against the active record, instead of the clowne object. The reason I am doing this because there is uniqueness index in the active record. Doing the attachment against the active record instead will attach the record to the clownee record