clowne-rb / clowne Goto Github PK
View Code? Open in Web Editor NEWA flexible gem for cloning models
Home Page: https://clowne.evilmartians.io
License: MIT License
A flexible gem for cloning models
Home Page: https://clowne.evilmartians.io
License: MIT License
Hello,
Thanks for the gem are there any plans to support belongs to or has_many through associations?
class StageCloner < Clowne::Cloner
# Symbol support (method is called on the source)
include_association :comments, if: :published?
# Block support
include_association :votes, if: ->(source, record, params) { params[:need_votes] }
end
I know about nullify, but I would like to ignore an attribute all together. This is needed when cloning an object that contains a full text search field (TS_VECTOR) like we have when using Postgresql full text search.
Hello.
In my app I have a models scheme similar to the next:
class Table
has_many :rows
has_many :columns
end
class Row
belongs_to :table
has_many :cells
end
class Column
belongs_to :table
has_many :cells
end
class Cell
belongs_to :row
belongs_to :column
end
and cloners:
class TableCloner < Clowne::Cloner
adapter :active_record
include_association :rows
include_association :columns
finalize do |source, record, **params|
record.title = "Copy of #{source.title}"
end
end
class RowCloner < Clowne::Cloner
adapter :active_record
include_association :cells
end
class ColumnCloner < Clowne::Cloner
adapter :active_record
include_association :cells
end
class CellCloner < Clowne::Cloner
adapter :active_record
end
Unfortunately, when I try to clone the Table
operation = TableCloner.call(original_table)
operation.persist!
I get correct table, rows and columns, but cells are cloned twice and it seems that both are wrong:
one cells set has wrong row_id
from the original_table
rows
and correct column_id
from the cloned_table
columns
and the second cells set has correct row_id
from the cloned_table
rows
but wrong column_id
from the original_table
columns
It seems that it doesn't understand how to sync all these record cloners (two dimensional table) and does clone rows
and columns
associations independent from each other.
Could you help me to understand how to clone such a scheme properly?
Thank you
It looks like Clowne is not compatible with Ruby 3.0. I get a lot of errors like these when running the tests suite:
ArgumentError: wrong number of arguments (given 2, expected 1)
This appears to be related to this breaking change in Ruby 3.0.
I have a very simple two model scenario with a has_many association in the model that I want to clone. So I declared
class PostsCloner < Clowne::Cloner
adapter :active_record
include_association :comments
end
The clone attempt results in an exception: Clowne::Adapters::ActiveRecord::Resolvers::UnknownAssociation: Association comments couldn't be found for User
It appears that this code is attempting to resolve the relation using a string index into ...reflections, but the reflections hash uses symbols.
clowne/lib/clowne/adapters/active_record/resolvers/association.rb
Lines 12 to 18 in 3d8f23f
Maybe this is a compatibility issue with Rails 4.1.8, Ruby 2.3
Hello guys,
I see that you copied a lot of our logic from https://github.com/amoeba-rb/amoeba but not mentioned it.
I see one of mainteiners was a contributor in amoeba.
Can you add a mention on original library?
class Member
has_many :jobs
has_many :addresses
end
class Job
....
validate :validate_member_address
def validate_member_address
VALID_STREET_ADDRESSES.include?(member.current_address.street_name)
end
end
When cloning a member, the cloner will clone jobs and addresses but the cloned job objects will fail to validate because at the time you clone member.jobs
, member.current_address
(class Address) has not been cloned yet.
So, is there any way to making sure we will clone member.address
first before member.jobs
?
class MemberCloner < Clowne::Cloner
include_association :jobs
include_association :addresses
end
Hello,
Thank you for your had work! This gem is awesome.
I'm having a hard time debugging an issue after upgrading from 0.2.0 to 1.1.0. I am using the ActiveRecord adaptor with my Rails application and Ruby version 2.6.2.
After updating to the newest version, I am able to successfully clone new objects in my database without any issues. However, records that existed in 0.2.0 land throw an ActiveRecord::RecordInvalid
error when trying to clone them.
I've noticed that the older records do not create Operation
records after being cloned which I think may be the reason why they get an error. Newly created records do not have this problem and work as described in the documentation. Just to be clear, the same cloner is being used in both instances. One record was created before we upgraded to version 1.1.0 and the other after.
Any ideas about what could be causing this issue? It seems weird to me that the records would be aware of what version of Clowne was being used when they were created. Let me know if you need any more information.
Hi! I am planning a new feature for my app that will need cloning a structure with nested models. There are plan has_many/belongs_to and has_many :trhough associations.
My question: does clowne automatically set the correct/new parent IDs for child models?
Say I have an instance of A1, that has_many B1s. These B1s of course have A1's ID as the id for the belongs_to association. If I clone A1 to A2, A2 will have many B2s. Will these B2s have A2's ID as the parent ID, or A1's ID? And what if I have multiple nesting levels? And what about parent IDs in has_many :through associations?
I hope the question is clear. I am still thinking about how to implement this feature so I am trying to put the pieces together.
Thanks in advance!
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.
For example, if I have a friends table, and I want to represent a bi-directional relationship between them.
Friendship
id | user_id | friend_id
----------------------
It would be awesome if a new release could be cut that includes PR #60 in it. I've been using a fork with this branch merged in and it really fits our needs very well. Thank you!!
Hi guys!
First of all congrats for your awesome gem. I'm opening an issue because I didn't find anywhere documentation for polymorphic tables, and I think the current behaviour is not as intended.
Example to reproduce. The table tag mapping has a polymorphic field owner (owner_id and owner_type)
# app/models/a.rb
class A < ApplicationRecord
has_many :tag_mappings
has_many :tags, through: tag_mappings
end
# app/models/b.rb
class B < ApplicationRecord
has_many :tag_mappings
has_many :tags, through: tag_mappings
end
# app/models/tag_mapping.rb
class TagMapping < ApplicationRecord
belongs_to :tag
belongs_to :owner, polymorphic: true
end
# app/models/tag.rb
class Tag < ApplicationRecord
has_many :tag_mappings, dependent: :destroy
has_many :as, through: :tag_mappings, source: :owner
has_many :bs, through: :tag_mappings, source: :owner
end
Cloner
class ACloner < Common::BaseCloner
include_association :tag_mappings
end
rails console
a = FactoryBot.create(:a, :with_tags)
a.tag_mappings # => <TagMapping owner_id: 1, owner_type: A, tag_id: 1>
a.tags # => <Tag id: 1>
cloned_a = ACloner.call(a).to_record
cloned_a.tags # => []
cloned_a.tag_mappings # => <TagMapping owner_id: nil, owner_type: A, tag_id: 1>
My workaround is:
class ACloner < Common::BaseCloner
finalize do |original_a, cloned_a, _params| do
cloned_a.tags = original_a.tags
end
end
Thank you :-)
Associations that contain dependent: :destroy
option will be destroyed on source object after the cloning process. It's easy to reproduce in your tests - just add
dependent: :destroy
to has_one :image, class_name: 'AR::Image'
and tests will fail.
When doing a deep cloning of an ActiveRecord object, I would like a child to access it's cloned parent in the finalize
block. Instead when I access the parent association, it is linked to the source parent.
Is this there a way for the child of deep cloned object to retrieve it's parent association which is also a cloned object?
First off, very nice looking gem, I actually just started work on something very similar, except my use case involves cloning records from a separate, but (mostly) identical database. I'm currently using a separate ApplicationRecord
base class, for handling the alternate models to clone from, that looks like this.
module GuestHouse
class ApplicationRecord < ::ActiveRecord::Base
self.abstract_class = true
establish_connection "guest_house_#{Rails.env}".to_sym
end
end
So, if I have:
class Widget < ApplicationRecord
end
class GuestHouse::Widget < GuestHouse::ApplicationRecord
end
Then Widget
s can be cloned from GuestHouse::Widget
s
Could this gem handle that use case out of the box, or would it need some additional development, and if so, could you point me to a starting place?
Hey there,
I've got a requirement that requires me to keep a point-in-time snapshot of some data whose associations and attributes change over time.
In order to go back to old records and understand the makeup of it at that point in time, we need to make sure that once that record is at a certain stage, it has a snapshot taken of it, and all its associations, and values of all their attributes.
I really don't want to have to do this manually, and would love to use something like Clowne. In order for me to do that though, I'll need to clone my records to their equivalent *Snapshot
models instead of the standard models. Here's a non-real-world example in case I'm not making too much sense:
As we either release new modules for a course, or remove old modules, or update existing modules, I don't want a certificate's scores to be affected.
My goal is that once each module is completed, all the data is snapshot from its CourseModule
to a CourseModuleSnapshot
record. I'd like to probably do a little bit of postprocessing too, but my main goal is to clone the model to a different but similar model.
Is this at all possible?
BTW - thank you evil martians for all the amazing open source you put out ❤️
Hello there! 👋
Is there a way to use traits in trait like in factory_bot?
Here is an example :
class ListCloner < Clowne::Cloner
trait :with_items do
include_association :items
end
trait :special_list do
with_items
finalize do |_source, record, **_params|
# Do some stuff...
end
end
end
Thanks for your work! ❤️
Currently, we had an effect of params shadowing: nested cloner could rely on the same params as the top-level ones, but they must not know about each other (more precisely, children cloners must not know about parent cloners).
We need a way to control how params
are passed to associations cloners, e.g.:
# just pass params as is (current behaviour)
include_association :users, params: true
# use custom block to prepare params
include_association :users, params: ->(params) { params[:data] }
# or use a key
include_association :profile, params: :profile
# usage
UserCloner.call(user, profile: { reset: true })
I also propose to not proxy params by default to the underlying cloners.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.