0

I have the following model for my Pages in my rails app:

class Page < ActiveRecord::Base

  has_many :blocks
  has_many :contents, :through => :blocks

  validates :title, presence: true
  validates :content, presence: true
  validates :page_template_id, presence: true

  amoeba do
    enable
    include_association :blocks
    include_association :contents
  end

  def create_branch
    branch = self.amoeba_dup #should dup content and blocks too
    branch.branched_from = self.id #so we know what record it was copied from
    branch.status = 0 #set this new copy to draft
    branch.save #save the branch
    branch #return the branch
  end

end

So a Page has Blocks, and Blocks have Contents.

The models for them are as follows:

class Block < ActiveRecord::Base
  belongs_to :page
  belongs_to :block_template
  has_many :contents
  validates :title, presence: true
  validates :block_template_id, presence: true
  validates :page_id, presence: true
end

class Content < ActiveRecord::Base
  belongs_to :block
  validates :name, presence: true
  validates :content, presence: true
  validates :block_id, presence: true
end

What I want to do is when I'm calling this in my controller:

  def branch
    @page = Page.find(params[:id])
    @branch = @page.create_branch
    redirect_to edit_page_path(@branch), :notice => 'Draft created!'
  end

It should be duplicating the Page and its Blocks and Contents. As in actually creating new versions of these records in the DB but with all the associations in tact! I'm using the Amoeba gem to duplicate the associations to the Page. You can also see I reference PageTemplate and BlockTemplate. The templates themselves should not be duplicated, but the references via foreign key should be, hence why I'm only specifying Block and Content for include_association.

However if I put a break point on @branch, it looks to have all the data but doesn't have an ID, so the redirect fails. It doesn't have an ID because it hasn't be properly duplicated... any ideas why?

It should be creating copies of the Page, Blocks, and Content.

I tried the clone method like clone: [:blocks, :contents] but that gave me an error that clone takes 0 parameters...


I can achieve what I want manually using:

def create_branch
  new_page = self.dup
  new_page.branched_from = self.id
  new_page.status = 0
  new_page.save
  # duplicate the blocks and contents
  self.blocks.each do |block|
    new_block = block.dup
    new_block.page_id = new_page.id
    new_block.save
    block.contents.each do |content|
      new_content = content.dup
      new_content.block_id = new_block.id
      new_content.save
    end
  end
  # finally return the new page
  new_page
end
Cameron
  • 27,963
  • 100
  • 281
  • 483
  • `@branch` should have some errors, could you add this `puts @branch.errors.full_mesasges` after `branch.save` line to see what errors it has. – Thanh Dec 05 '16 at 10:14
  • Okay so using the evaluate expression. I get the error 'Blocks is invalid'. So I'd presume it was failing its validation when duplicating them. See updated post with what validation I have in the models, but still means that the copying isn't working correctly. – Cameron Dec 05 '16 at 10:41

1 Answers1

0

You can include all the options you need inside the block, and for Contents relation you can create it from Block class as following:

class Page < ActiveRecord::Base
  ...
  amoeba do
    include_association :blocks
    set :status => 0
    customize(lambda { |original_page, new_page|
      new_page.branched_from = original_page.id
    })
  end
  .....
  def create_branch 
    branch = self.amoeba_dup
    branch.save
    branch
  end
end

and when cloning Block we will have the code to clone the contents:

class Block < ActiveRecord::Base
  .......
  amoeba do
    include_association :contents
    set :status => 0
    customize(lambda { |original_block, new_block|
      new_block.page_id = original_page.id
    })
  end
  ....... 
end

 class Content < ActiveRecord::Base
  ....... 
  amoeba do
    enable
  end
  ....... 
 end
mohamed-ibrahim
  • 10,837
  • 4
  • 39
  • 51