Git Product home page Git Product logo

amoeba's People

Contributors

brentdodell avatar budu avatar ciddennis avatar gingermusketeer avatar hirurg103 avatar imdrasil avatar jrmhaig avatar mstate avatar palkan avatar robinroestenburg avatar rocksolidwebdesign avatar simonoff avatar srachner avatar swistaczek avatar tagliala avatar vieditcom avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

amoeba's Issues

doesn't deal with validations

Not sure of the details here - I only know that the dup subcollection was unable to save b/c of validation errors.

I was started to debug it, but then I simply flipped a bit on this library instead, rewrite my copy functions as

  alias :orig_dup :dup
  def dup
    copy = orig_dup
    model_runs.each {|model_run| copy.model_runs << model_run.dup}
    copy
  end

and moved on. Filed this ticket here in hopes it would trigger some better test case on your part.

Looks like it'll be a great library when it's finished. 

Dump to file (feature request)

I was wondering if it is possible to dump the copied model to a file so it can be loaded from another application with same model configuration. I search a way to replicate content between same apps but with complex models.

ownership transfer

Hi @simonoff I just tried transfering ownership to the amoeba-rb organization but github will not let me do that unless I have admin rights.

carrierwave files cloning

Vaughn, thanks for awesome gem.

I found it doesn't maintain carrierwave cloning. Do you plan to maintain it?

Not updating the value after amoeba_dup

Assume i am having a Model like as below :

Recipe is the model which is having a "name" attribute. So Recipe is having name as 'test1'

Now i am able to made a copy of recipe by amoeba_dup method and able to save that into database also like following :
r = Recipe.find(1).amoeba_dup
r.save;

But before storing i want to update the name of the recipe after made a copy.
r = Recipe.find(1).amoeba_dup
r.name = 'test2';
r.save;

While doing this iam getting :
NoMethodError: undefined method `name=' for #Recipe:0x0000000ab971e8

First of all, is it possible to update the value after copy by amoeba_dup ?

Could you please clarify me...Thank you

Association between copied objects is missing

Hi, first amoeba is a great gem and i really enjoy using it :)

But now my following situation doesn't seem to work:

3 Models:

project.rb
has_many :risks
has_many :targets
amoeba do
enable
prepend :project_name => "Copy of: "
end

risk.rb
belongs_to :project
has_many :risk_target_allocations
has_many :targets, :through => :risk_target_allocations
amoeba do
enable
end

target.rb
belongs_to :project
has_many :risk_target_allocations
has_many :risks, :through => :risk_target_allocations

With the setup described above amoeba generates a copy of a project, the risks of that project and the targets of that project. But the association between the copied risks and the copied targets isn't showing up anymore.

I'm not sure if this is a real issue or that I've done something wrong.

Thanks for some feedback.

Switch databases before saving

Is there a way to use this gem and switch to a database that has the same structure and then save the duped data into that new database?

How do i duplicate a `belongs_to` relationship?

I have a model that looks like this:

class Foo < ActiveRecord::Base
  belongs_to :bar

  amoeba do
    enable
    include_field :bar
  end
end

But it doesn't work --- how should i go about duplicating the belongs_to association with amoeba?

Child association might be duplicated before the parent?

First off, in what order are the model and associations duplicated? I couldn't tell from the documentation.

Secondly, I'm trying to duplicate a Site record, which in turn is duplicating the association. This is fine. The issue is that I'm hitting a validation on the child Placement model before the duplicated Site is created.

Simplified code...

class Placement < ActiveRecord::Base
  belongs_to :site, inverse_of: :placements
  validate :site_must_have_stuff, if: proc { |record| record.some_condition? }

  def site_must_have_stuff
    if site.url.blank?
      errors.add(:url, "must be present")
      false
    else
      true
    end
  end
end

class Site < ActiveRecord::Base
  has_many :placements, inverse_of: :site
end

site = Site.new(attributes)
site.amoeba_dup  #=> (Placement invalid error)

Am I doing something wrong? Is the expected behavior to create the duplicated associations before the object you call amoeba_dup on? And if all of this is true, is there a way to coerce the duplication order?

New release coming soon?

Hello! What does the roadmap look like for the next gem release? We're using a few features from master and would love to be able to use a true released version before releasing.

before_validation called twice

before_validation seems to be called twice.

Callback:

before_validation :convert_tax_to_decimal, if: :tax_changed?

private
def convert_tax_to_decimal
  puts 'here'
  self.tax ||= 0
  self.tax = tax / 100
end

Controller:

job = current_business.jobs.find(params[:job_id])
copy_job = job.amoeba_dup
copy_job.save!
copy_job.build_client if copy_job.client.nil?
redirect_to edit_job_path(copy_job)

Output:

here
here

Self-referential has_many :through

How to copy the following association? Seems doesn't work right now. Thx.

class Field < ActiveRecord::Base
  has_many :field_trees
  has_many :subfields, through: :field_trees, dependent: :destroy
end

class FieldTree < ActiveRecord::Base
  belongs_to :field
  belongs_to :subfield, :class_name => "Field"
end

Rails 3.1 custom serialization and it does not clone correctly

This gem is amazing. This is some serious meta-fu. Is very impressive.

I am using a custom serialization class in one of my models and I am not getting a correct clone.

This is probably some bad programming but I have a class to store an array of numbers as a sorted comma separated string. I don't think it is cloning correctly.

  class ArrayPack
    def load(array_or_text)
      array_or_text = array_or_text.split(',').collect(&:to_i) if array_or_text.class == String
      return [] if array_or_text.blank?
      raise "Need to search a string or array, you passed #{array_or_text}" unless array_or_text.class == Array
      array_or_text.collect(&:to_i).sort
    end

    def dump(int_array)
      self.load(int_array).join(',')
    end
  end

  serialize :path, ArrayPack.new

When using amoeba_dub : undefined method for NilClass

I tried amoeba in a rails 2 console (with Ruby 2.1):

class Dict < ActiveRecord::Base
  belongs_to  :user
  has_many    :cards,  dependent: :destroy
  has_many :idioms, through: :cards
end
class Card < ActiveRecord::Base
  belongs_to :dict
  has_many  :idioms, dependent: :destroy
  amoeba do
    exclude_field :dict_id
  end
end
class Idiom < ActiveRecord::Base
  belongs_to :card
  amoeba do
    include_field :repres
    include_field :card_id
    include_field :kind
    include_field :note
  end
end

NOW IN THE CONSOLE:

c=Card.find_by_id(19) # yields a Card object
c.amoeba_dup

THIS RAISES THE EXCEPTION:

NoMethodError: undefined method `macro' for nil:NilClass
    from .../amoeba-2.0.0/lib/amoeba.rb:412:in `amo_process_association'
    from .../amoeba-2.0.0/lib/amoeba.rb:381:in `block in amoeba_dup'
    from .../amoeba-2.0.0/lib/amoeba.rb:379:in `each'
    from ..../amoeba-2.0.0/lib/amoeba.rb:379:in `amoeba_dup'
    from .../amoeba-2.0.0/lib/amoeba.rb:457:in `block in amo_process_association'

Where did I make a mistake?

Clone a has_many collection

In my use-case, I have an incoming email message, which has_many :attachments. I want to copy these attachments to another model. To use amoeba with this, my code now is as follows:

    def attachments_deep_copy
        self.attachments.map {|attachment| attachment.amoeba_dup }
    end

What seems nicer to me, is to add an amoeba_dup method to ActiveRecord::Associations::CollectionProxy, so it would simply be possible to use self.attachments.amoeba_dup.

How to prevent callbacks?

I tried out amoeba and running in a problem. My model has an after_create callback where some associated datas will be created. The user can change these predefined datas. On dup I will duplicate the changed associated datas. The original data I will not clone.

Can exclude_field and include_field be extended to attributes?

Howdy,

I understand that as things are, include_field and exclude_field are really only for associations (it might be more clear to new users to call them include_assoc and exclude_assoc, just a thought as the 'field' part tripped me up a bit at first). However, I can see some serious benefit to allowing them and the associated behavior to be used for normal, non-associative record attributes as well.

For example, I have a model with 30 fields in it and when a dup() is called, I want to exclude 25 of them. For those 25, I want them to get the default value for a new record. Of the 5 remaining, 3 are associations and 2 are regular fields. If I could use the inclusive model for everything, then my amoeba block would be nice and short (5 include_field or one with an array of the fields/attrs to copy and leave all the rest alone). Right now, I have a lengthy series of nullify lines (which don't exactly do the same thing as exclude_ would -- see the other issue I created about nullify).

Alternately, if refitting the include/exclude_field methods is a problem, would be to add include/exclude_attr that would work the same as include/exclude_field, but for non-assoc fields.

Fails when presence validation uses _id

Given I have a post and comments, if Comment has:

belongs_to :post
validates :post, presence: true

Then when I do post.amoeba_dup it clones the post and the comments.

However if my Comment model has:

belongs_to :post
validates :post_id, presence: true

amoeba won't set the post_id, so the comments are not saved, the error for comments contains:

@messages={:post_id=>["can't be blank"]}

Overwriting ActiveRecord::Base#dup

Hi,
I have trouble with using Amoeba together with PaperTrail ( ). The reason for that is overwrite of ActiveRecord::Base#dup by Amoeba. PaperTrail uses .dup method to clone object and serialize it. Is there any way to use .dup method by skiping Amoeba part for 'amobeoized' ( ๐Ÿ˜„ ) models?

Loading Amoeba causes nil and false to be frozen

The following code will cause nil and false to be frozen after loading amoeba. This is unexpected imho and causes problems in code that depends on object.frozen?.

class Config
  DEFAULTS = {
    enabled:        false,
    inherit:        false,
    do_preproc:     false,
    parenting:      false,
    raised:         false,
    dup_method:     :dup,
    remap_method:   nil,
    ...
  }

  ...
  DEFAULTS.freeze

  DEFAULTS.each do |key, value|
    value.freeze
    ...
  end

I don't think freezing every value inside the hash is needed here?

Dealing with translations not working

Hi,
we use Globalize3 (https://github.com/svenfuchs/globalize3) which is used to have translations for your objects. That is one can use things like below, which generates the needed translations in a table:

class Answer < ActiveRecord::Base
    attr_accessible :text
    belongs_to :question
    translate :text

    amoeba do
        enable
    end
end

Globalize3 creates a has_many :translations relation. If one creates a new answer, sets the text and saves everything works fine, and the text is also saved to the translations' table. If one dups an answer and saves it, it won't create a translation row. If one saves again it creates a nil raw. And if one then changes the text of the duplicated element, the translation of the first element is changed:

a = Answer.new
a.text = "Test"
a.save

-> Everything ok, entry in answers table and translations table with correct text

b = a.dup
b.save

-> Nothing happens in translations table

b.save (again)

-> Empty entry in translations table

b.text = "Test 2"
b.save

-> Changes in the row of object a

Summary: The has_many :translations has to be recognized and used correctly, which is not the case at the moment

Deep inheritance cloning

Hi,

We use amoeba to preview modifications on our data models, but we have an issue with deep inheritance as described below:

amoeba_inheritance

Basically a box has_many sub_products. In our example, box.sub_products returns SubSubProduct objects and we are unable to access to a parent class association, like in the graph above.
box.amoeba_dup.sub_products.first.another_product returns nil instead of AnotherProduct instance.

We have created a dummy app that reproduces the problem, you can find specs in the following repository: https://github.com/kdisneur/amoeba_inheritance

We've been really happy with amoeba so far and we're sorry we don't come with a fix (for now) but we wanted to share the issue with you.

Kevin

initialize_dup and ruby 2.0.0

I'm getting this error (amoeba 2.0.0) after upgrading to ruby 2.0.0

NoMethodError: private method `initialize_dup' called for #<Class:something>

Issue with cloning has_many :through

I'm on Rails 4.1.9 and when trying to clone a through association I'm getting the following error.

Cannot modify association 'Client#cost_timespans' because the source reflection class 'CostTimespan' is associated to 'Cost' via :has_many.

Heres my simplified code

class CostTimespan < ActiveRecord::Base

  belongs_to :cost

end

class Cost < ActiveRecord::Base

  has_many :cost_timespans, -> { order(end_date: :desc) }

end

class Client < ActiveRecord::Base
  has_many :costs
  has_many :cost_timespans, through: :costs

  amoeba do
    include_association :available_services
    include_association :sign_cancellation_charges
    include_association :costs
    include_association :cost_timespans

    clone [:cost_timespans]

    customize ->(original_client, new_client) {
      new_client.service_ids = original_client.service_ids
      new_client.assign_attributes new_client.attributes.select { |k, v| k.ends_with?('_count') }.inject({}) { |h, (k, v)| h[k] = 0; h }
    }
  end
end

Here's the stack trace

activerecord (4.1.9) lib/active_record/associations/through_association.rb:86:in `ensure_mutable'
activerecord (4.1.9) lib/active_record/associations/has_many_through_association.rb:84:in `build_through_record'
activerecord (4.1.9) lib/active_record/associations/has_many_through_association.rb:46:in `block in concat_records'
activerecord (4.1.9) lib/active_record/associations/has_many_through_association.rb:45:in `concat_records'
activerecord (4.1.9) lib/active_record/associations/collection_association.rb:157:in `concat'
activerecord (4.1.9) lib/active_record/associations/has_many_through_association.rb:36:in `concat'
activerecord (4.1.9) lib/active_record/associations/collection_proxy.rb:972:in `<<'
amoeba (3.0.0) lib/amoeba/macros/has_many.rb:19:in `block in follow_with_clone'
activerecord (4.1.9) lib/active_record/relation/delegation.rb:46:in `each'
amoeba (3.0.0) lib/amoeba/macros/has_many.rb:16:in `follow_with_clone'
amoeba (3.0.0) lib/amoeba/macros/has_many.rb:6:in `follow'
amoeba (3.0.0) lib/amoeba/cloner.rb:108:in `follow_association'
amoeba (3.0.0) lib/amoeba/cloner.rb:80:in `block in follow_all_except_excludes'
amoeba (3.0.0) lib/amoeba/cloner.rb:78:in `follow_all_except_excludes'
amoeba (3.0.0) lib/amoeba/cloner.rb:94:in `apply_associations'
amoeba (3.0.0) lib/amoeba/cloner.rb:102:in `apply'
amoeba (3.0.0) lib/amoeba/cloner.rb:23:in `run'
amoeba (3.0.0) lib/amoeba/instance_methods.rb:34:in `amoeba_dup'
app/controllers/account/clients_controller.rb:39:in `duplicate'
actionpack (4.1.9) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
actionpack (4.1.9) lib/abstract_controller/base.rb:189:in `process_action'
actionpack (4.1.9) lib/action_controller/metal/rendering.rb:10:in `process_action'
actionpack (4.1.9) lib/abstract_controller/callbacks.rb:20:in `block in process_action'
activesupport (4.1.9) lib/active_support/callbacks.rb:113:in `call'
activesupport (4.1.9) lib/active_support/callbacks.rb:149:in `block in halting_and_conditional'
activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
activesupport (4.1.9) lib/active_support/callbacks.rb:229:in `block in halting'
activesupport (4.1.9) lib/active_support/callbacks.rb:229:in `block in halting'
activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
activesupport (4.1.9) lib/active_support/callbacks.rb:86:in `run_callbacks'
actionpack (4.1.9) lib/abstract_controller/callbacks.rb:19:in `process_action'
actionpack (4.1.9) lib/action_controller/metal/rescue.rb:29:in `process_action'
actionpack (4.1.9) lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
activesupport (4.1.9) lib/active_support/notifications.rb:159:in `block in instrument'
activesupport (4.1.9) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
activesupport (4.1.9) lib/active_support/notifications.rb:159:in `instrument'
actionpack (4.1.9) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
actionpack (4.1.9) lib/action_controller/metal/params_wrapper.rb:250:in `process_action'
activerecord (4.1.9) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
actionpack (4.1.9) lib/abstract_controller/base.rb:136:in `process'
actionview (4.1.9) lib/action_view/rendering.rb:30:in `process'
actionpack (4.1.9) lib/action_controller/metal.rb:196:in `dispatch'
actionpack (4.1.9) lib/action_controller/metal/rack_delegation.rb:13:in `dispatch'
actionpack (4.1.9) lib/action_controller/metal.rb:232:in `block in action'
actionpack (4.1.9) lib/action_dispatch/routing/route_set.rb:82:in `dispatch'
actionpack (4.1.9) lib/action_dispatch/routing/route_set.rb:50:in `call'
actionpack (4.1.9) lib/action_dispatch/journey/router.rb:73:in `block in call'
actionpack (4.1.9) lib/action_dispatch/journey/router.rb:59:in `call'
actionpack (4.1.9) lib/action_dispatch/routing/route_set.rb:685:in `call'
meta_request (0.3.4) lib/meta_request/middlewares/app_request_handler.rb:13:in `call'
meta_request (0.3.4) lib/meta_request/middlewares/meta_request_handler.rb:13:in `call'
rack-ssl-enforcer (0.2.6) lib/rack/ssl-enforcer.rb:56:in `call'
warden (1.2.3) lib/warden/manager.rb:35:in `block in call'
warden (1.2.3) lib/warden/manager.rb:34:in `call'
rack (1.5.2) lib/rack/etag.rb:23:in `call'
rack (1.5.2) lib/rack/conditionalget.rb:25:in `call'
rack (1.5.2) lib/rack/head.rb:11:in `call'
actionpack (4.1.9) lib/action_dispatch/middleware/params_parser.rb:27:in `call'
actionpack (4.1.9) lib/action_dispatch/middleware/flash.rb:254:in `call'
rack (1.5.2) lib/rack/session/abstract/id.rb:225:in `context'
rack (1.5.2) lib/rack/session/abstract/id.rb:220:in `call'
actionpack (4.1.9) lib/action_dispatch/middleware/cookies.rb:562:in `call'
activerecord (4.1.9) lib/active_record/query_cache.rb:36:in `call'
activerecord (4.1.9) lib/active_record/connection_adapters/abstract/connection_pool.rb:621:in `call'
activerecord (4.1.9) lib/active_record/migration.rb:380:in `call'
actionpack (4.1.9) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
activesupport (4.1.9) lib/active_support/callbacks.rb:82:in `run_callbacks'
actionpack (4.1.9) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
actionpack (4.1.9) lib/action_dispatch/middleware/reloader.rb:73:in `call'
actionpack (4.1.9) lib/action_dispatch/middleware/remote_ip.rb:76:in `call'
rollbar (1.4.2) lib/rollbar/middleware/rails/rollbar.rb:24:in `block in call'
rollbar (1.4.2) lib/rollbar.rb:754:in `scoped'
rollbar (1.4.2) lib/rollbar/middleware/rails/rollbar.rb:22:in `call'
better_errors (2.0.0) lib/better_errors/middleware.rb:84:in `protected_app_call'
better_errors (2.0.0) lib/better_errors/middleware.rb:79:in `better_errors_call'
better_errors (2.0.0) lib/better_errors/middleware.rb:57:in `call'
rack-contrib (1.1.0) lib/rack/contrib/response_headers.rb:17:in `call'
meta_request (0.3.4) lib/meta_request/middlewares/headers.rb:16:in `call'
actionpack (4.1.9) lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'
rollbar (1.4.2) lib/rollbar/middleware/rails/show_exceptions.rb:22:in `call_with_rollbar'
actionpack (4.1.9) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
railties (4.1.9) lib/rails/rack/logger.rb:38:in `call_app'
railties (4.1.9) lib/rails/rack/logger.rb:20:in `block in call'
activesupport (4.1.9) lib/active_support/tagged_logging.rb:68:in `block in tagged'
activesupport (4.1.9) lib/active_support/tagged_logging.rb:26:in `tagged'
activesupport (4.1.9) lib/active_support/tagged_logging.rb:68:in `tagged'
railties (4.1.9) lib/rails/rack/logger.rb:20:in `call'
quiet_assets (1.0.2) lib/quiet_assets.rb:18:in `call_with_quiet_assets'
actionpack (4.1.9) lib/action_dispatch/middleware/request_id.rb:21:in `call'
rack (1.5.2) lib/rack/methodoverride.rb:21:in `call'
rack (1.5.2) lib/rack/runtime.rb:17:in `call'
activesupport (4.1.9) lib/active_support/cache/strategy/local_cache_middleware.rb:26:in `call'
rack (1.5.2) lib/rack/lock.rb:17:in `call'
actionpack (4.1.9) lib/action_dispatch/middleware/static.rb:84:in `call'
rack (1.5.2) lib/rack/sendfile.rb:112:in `call'
railties (4.1.9) lib/rails/engine.rb:514:in `call'
railties (4.1.9) lib/rails/application.rb:144:in `call'
rack (1.5.2) lib/rack/content_length.rb:14:in `call'
thin (1.6.2) lib/thin/connection.rb:86:in `block in pre_process'
thin (1.6.2) lib/thin/connection.rb:84:in `pre_process'
thin (1.6.2) lib/thin/connection.rb:53:in `process'
thin (1.6.2) lib/thin/connection.rb:39:in `receive_data'
eventmachine (1.0.3) lib/eventmachine.rb:187:in `run'
thin (1.6.2) lib/thin/backends/base.rb:73:in `start'
thin (1.6.2) lib/thin/server.rb:162:in `start'
rack (1.5.2) lib/rack/handler/thin.rb:16:in `run'
rack (1.5.2) lib/rack/server.rb:264:in `start'
railties (4.1.9) lib/rails/commands/server.rb:69:in `start'
railties (4.1.9) lib/rails/commands/commands_tasks.rb:81:in `block in server'
railties (4.1.9) lib/rails/commands/commands_tasks.rb:76:in `server'
railties (4.1.9) lib/rails/commands/commands_tasks.rb:40:in `run_command!'
railties (4.1.9) lib/rails/commands.rb:17:in `<top (required)>'
spring (1.0.0) lib/spring/client/rails.rb:29:in `call'
spring (1.0.0) lib/spring/client/command.rb:7:in `call'
spring (1.0.0) lib/spring/client.rb:23:in `run'
spring (1.0.0) bin/spring:31:in `<top (required)>'
bin/rails:9:in `<main>'

Applying customize to children

Love the gem.

So in my application, I'm saving duplicated objects in the same table as the original object. I associate the two (with self-referential associations), so I'm able to find the "draft" version of an object. It works great for the most part.

Assume all objects have an :approved_version_id, with this amoeba configuration:

    amoeba do
      include_association :ratings
      exclude_association [:approved, :draft]
      customize(lambda {|live_obj, draft_obj|
        draft_obj.approved_version_id = live_obj.id
      })
    end

(see the entire sample of 3 models at https://gist.github.com/stevehodges/e85a1e367d546d527984)

By default, propagation uses submissive parenting, meaning the config settings on the parent will be applied, but any child settings, if present, will either add to or overwrite the parent settings depending on how you call the DSL methods.

I've found that the customize directive doesn't get passed to the model's children. The easy way around this is to define another amoeba block in the child, which is convenient when the child model is also duplicating its children (the grandchildren).

However, I can't figure out a way to set that customize directive on the grandchild.

The result: the original object has an approved_version_id, as does its child. The grandchild does not.

Gist of Rails models
Gist of Rails Console output

  1. Am I doing something wrong, or is there any way for customize to be applied to children (including children which don't have an amoeba block)?
  2. Are there any workarounds if this isn't supported?

amoeba method doesn't deal with class hierarchies correctly

If you have have:

class Post
  has_many :comments
  amoeba do enabled end
end

class EnhancedPost < Post
end

and then following code fails:

a=EnhancedPost.find(... a enhanced post with comments)
b = a.dup
b.comments.size.should == b.comments.size ## FAILS

The reason is that the Amoeba::Config in the EnhancedPost class has enabled=false (the default) b/c it is not the same instance as the Amoeba::Config in the Post base class.

I'm thinking that the amoeba block in EnhancedPost should perhaps be written this way:

class EnhancedPost < Post
  amoeba do 
      super.amoeba ## get the defaults from the base class
      ## then do anything special for EnhancedPost class
  end
end

and I'm wishing that you could include a note about the behaviour of Amoeba and inherited classes in your wonderful documentation, it took two of us quite a few hours to figure out what was happening.

Thanks!
Rob.

Enable for all models by default

We have lots of models that should be copied recursively. This means that each involved model needs to have amoeba enabled. This is error-prone since a developer can forget to include new models. Because of this, we simply enable by convention all models by hand. That means adding an enable-amoeba block which is cumbersome.

Is it possible to just enable amoeba for all models?

Nullify and set don't work on an STI model

Is this intended? We have the following

class Activity < ActiveRecord::Base
  amoeba do
    nullify :uuid
  end
end

module Activities
  class Video < ::Activity
  end
end

activity = Activities::Video.last
cloned_activity = activity.amoeba_dup
cloned_activity.uuid == activity.uuid # true when I would have expected false

It does work when I move the amoeba block into the the child class.

passing in parameter to dup method?

When creating a deep-copy of a model, I'd like to pass in a parameter to be used in the preprocessing of fields. Is it possible to send parameters in to model.dup? Or is it necessary to instead do this logic separately after running the dup (but before actually saving the deep-copy to the database).

Thanks for your help--not to mention writing a helpful gem!

docs question.

Reading through Known Limitations... section in the docs, there is a part that talks about case sensitive substitutions using gsub.
I may have not understood correctly what you meant gsub is case sensitive. gsub doesn't care about case sensitivity unless you pass a string, otherwise when passing a regexp it depends on the /i flag determining case insensitivity...

custom serialization

Sorry to open the ticket so fast again, but the serialization only had one problem and then it works with the 'old_post'

    def load(str)
      str.split(',').collect(&:to_i)
    end

I was missing the to_i so it was trying to match ['1'] to [1]. This all seems rather silly but I use it in my app to store a path so I can search for [6,7] in the database as '6,7'. It is working fine, i just thought i would simplify the cloning.

I wish there was more documentation for the custom serialization to actually prove it's a Rails feature ;-) The only thing I can find in the code is here:
activerecord/lib/active_record/attribute_methods/serialization.rb:

          coder = if [:load, :dump].all? { |x| class_name.respond_to?(x) }
                    class_name
                  else
                    Coders::YAMLColumn.new(class_name)
                  end

After fixing the custom serializer the old_post works fine, but when cloning it throws an exception

NoMethodError: undefined method `to_i' for [1, 2]:Array
    from /Users/a/RubyMineProjects/amoeba/spec/support/models.rb:79:in `collect'
    from /Users/a/RubyMineProjects/amoeba/spec/support/models.rb:79:in `load'
    from /Users/a/.rvm/gems/ruby-1.9.3-p125-falcon@amoeba/gems/activerecord-3.2.3/lib/active_record/attribute_methods/serialization.rb:24:in `unserialize'
    from /Users/a/.rvm/gems/ruby-1.9.3-p125-falcon@amoeba/gems/activerecord-3.2.3/lib/active_record/attribute_methods/serialization.rb:15:in `unserialized_value'

So what is interesting is that if you take the first custom_thing and you dup & save it, it works fine. But when you dup and save the post object, it throws the exception. So there is something happening through the recursion. I looked at the code but don't see anything that would explain it to me.

Polymorphic workaround?

I can't seem to find a 'great' way to hook up polymorphic has many. Any preferred workarounds?

Nullify action not matching documentation regarding nullified field value

Howdy,

Reading over the docs for nullify, while it does say that it puts nil into specified fields, it also says those fields should take on their default values. At least for us using PostgreSQL, that is not the case. The nil values installed via 'nullify' as nil/null and then are stored that way (or blow up in the save for fields that have default values, but do not allow null values).

I suspect this is a DB thing and may be different between DBs.

What we are really looking for is a way to exclude copying a simple field/attribute so that the 'new' record (the copy) has the initial/default value as if you had just executed a .new on the model. Perhaps a "default" command that, like "nullify", would not copy the value but would leave it in an unmolested state (i.e. DB default, like .new). Or, alternately, from my other post, extend the concept of "exclude/include_field" to record attributes and/or add a exclude/include_attr that would leave un-specified record attribute fields alone.

Set user_id in association

Hi there,

I have a Tasklist & a Task Model.

I'm using amoeba to duplicate one task list with its associated tasks.
Both Tasklist & Task have a user_id field.

The user_id is set to NULL by default.

When I duplicate, I want the user_id to be set to the current_user.id (from Devise).

I'm able to copy the task list with the proper user_id using:

   @tasklist = Tasklist.find(topic_params[:tasklist])
   @tasklist.user_id = current_user.id
   @tasklist.tasks.user_id = current_user.id
   @tasklist.amoeba_dup.save

Tasks are also properly copied but the user_id is not updated in the copied tasks (only task list).
I can't use the current_user.id in the Model with :set.

So I'm wondering how I can achieve this?

Thanks!
Vincent

Bug with clone method?

Hi!
I doing the same thing like in docs:

class Post < ActiveRecord::Base
  has_many :post_widgets
  has_many :widgets, :through => :post_widgets

  amoeba do
    enable
    clone [:widgets]
  end
end

Then when I cloned post instance, amoeba adds extra records into widgets table, but not into post_widgets where they should really be.

Is this a bug?

(Rails 4.2.1, amoeba 3.0.0)

undefined method `include_association'

I'm trying to load index action
My model

class Responder < ActiveRecord::Base
    has_many :responder_actions
    validates :name, presence: true, uniqueness: true
    accepts_nested_attributes_for :responder_actions

    def self.search(search)
      if search
        where('name LIKE ?', "%#{search}%").order(id: :desc)
      else
        all.order(id: :desc)
      end
    end

    amoeba do
        enable
        prepend :title => "Copy of "
        include_association :responder_actions
    end
end

I'm getting an error

NoMethodError at /dashboard/messages/responders
undefined method `include_association' for #<Amoeba::Dsl::Config:0x007ff83c37cd78>

Where is my mistake?
amoeba 2.1.0
rails 4.1.7

Is the usage of On The Fly configurations thread-safe?

Let's say one thread calls the amoeba method (as in, some_object.class.amoeba do ...) to set custom configurations. But then before it has a chance to complete its some_object.amoeba_dup call, another thread calls amoeba on the same type of object (but a different instance) and sets configurations differently. Is the process happening in amoeba_dup on that first thread/object affected by that second call to amoeba?

If so, is there a supported way to ensure thread safety and concurrency while using On The Fly configurations?

include/exclude_association with conditions

I'd like to use include/exclude_association with conditions, similar to the :if option of the validation methods in rails. For example

amoeba do
  include_association :tags, if: my_condition_method?
end

def my_condition_method?
   # ... do some stuff that returns bool
end

Any chance that you build that in?

include/exclude_association is undefined, yet other amoeba configurations work.

Amoeba config block:

  amoeba do
    enable

    include_association :redacted_associatons_1
    include_association :redacted_associatons_2
    include_association :redacted_associatons_3

    nullify :created_at
    nullify :updated_at
    nullify :published_at

    set published: false
    prepend title: 'Copy of '
  end

Here's the error:

/Users/austinsaylor/.rvm/gems/ruby-1.9.3-p484/gems/hobo_support-2.0.1/lib/hobo_support/string.rb:23:in `class_eval': undefined method `include_association' for #<Amoeba::Dsl::Config:0x007fbea38eca60> (NoMethodError)

Could it be a conflict with Hobo? (http://www.hobocentral.net/manual/about)

The amoeba_dup works with the nullify, set, and prepend config when include_association isn't present.

Support for counter_cache

I recently added a counter_cache to a model only to be surprised when duplication via amoeba brought it out of sync. I should have anticipated this, but it would be nice for amoeba to "just work" in this situation.

Here's the scenario. I dup a deep model hierarchy. One of the collections (A) on the root object has another collection (B). Collection B is not to be duplicated. Easy enough; I simply did not include amoeba do in the class for A. But then I added a counter_cache for collection B.

On the clone collection B empty, but the counter_cache says that it has items. The fix is simple:

  amoeba do
    set signups_count: 0
    propagate #this is in a base class
  end

But it would be nice if the counter cache stayed in sync without doing anything special. I'm not sure how it would be implemented but probably involves this: http://apidock.com/rails/ActiveRecord/CounterCache/reset_counters

self has_one creates another record in 2.0.0

Hi,
We experiment some troubles lately, as took us time to find the root of the problem, here it is with the solution, to keep a record for next ones :

In 2.0.0 version of amoeba, an object which has a self references through a belongs_to and a has_one make a second record on cloning.

class Post < ActiveRecord::Base

belongs_to :next_post, class_name: 'Post', inverse_of: :father_post
has_one :father_post, class_name: 'Post', dependent: :nullify, inverse_of: :next_post, foreign_key: :next_post_id

amoeba do
  enable
  clone :comments
end

To resolve that we had to add a '''exclude_field :father_post''' inside the amoeaba block.

NB: it is exclude_fieldand NOT exclude_associationin 2.0.0

Dunno how and why it would create another record in addition to the clone but that how we stopped it from doing it !

Cheers.

Applying different amoeba configurations for different use cases

Hi guys,

I have a small challenge. I'd like to apply different configs for amoeba, when I have different cases of cloning my objects.

Let assume that I have class Job with fields: name, description. The thing is that in one case I'd like to clone name & description and in the other case, I'd like to skip cloning description.

The other example can be, that I have a structure: MilestoneTemplate, TaskTemplate. Milestone template has many task templates. For one case I cast objects into the other classes: Milestone & Task and in the other case, I'd like to keep the original classes.

I'm not sure how to handle these cases - conditionally applying logic for cloning across multiple classes. Most likely I'll write custom thing for that. I'd really like to use / extend amoeba for this case. Maybe it could be solved by e.g. using refinements and overriding method for cloning?

Models Saved and Committed on amoeba_dup (Rails 4)

When I call amoeba_dup, everything works correctly, except that all cloned models and associations are committed to the database without calling save. Here is my config block:

35 amoeba do
36 include_field [:campaign_providers, :data_fields, :delivery_methods]
37 append :name => ' (copy)'
38 end

in the console i type: ModelName.last.amoeba_dup and all models and associations are saved/commited. This should only happen when i save the model after calling amoeba_dup.

Relations and related items does not copied/cloned

So i have Tour model wich defines amoeba like this:

  amoeba do
    enable
    append :name => " COPY"
    include_field [:tags, :managers]
    clone [:days, :departures, :assets, :prices, :locations]
  end

All related and relation models has this:

  amoeba do
    enable
  end

From 'rails c' i do

Tour.first.amoeba_dup.save!

And model itself is duplicated.. But relations to tags and managers does not respected aswell as other relations does not get cloned...
All i see is INSERT SQL query to Tours table..

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.