Forum: Ruby on Rails Anyone know how to copy rows?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Jeff S. (Guest)
on 2006-04-22 04:38
Hey all,

I'm trying to write something that allows one to copy several rows from
a table and create new rows based on those rows.  This will be used to
intentionally duplicate rows.  Did I mention that I was having little
luck?  I'm from a PHP world, but I've been getting really into Rails
lately.

Here's what I've got(assume an event has_many wastes):

  def wastePrepopulate
  @wastes = Waste.find_all
  @wastes.each do |waste|
     Event.find(params[:id]).wastes.create(params[:waste])
  end
     flash[:notice] = 'The records have been prepopulated.'
     redirect_to :action => "showwastes", :id =>params[:id]
  end

If I feed parameters to it using a form, it will create new records with
those parameters, but I can't get it to use the data from
@wastes=Waste.find_all.

I'm ultimately trying to set up a way to create records based on
existing data.  Any help would be GREATLY appreciated.

Cheers,
Monkey
Alex W. (Guest)
on 2006-04-22 05:03
jeff stevens wrote:
> Hey all,
>
> I'm trying to write something that allows one to copy several rows from
> a table and create new rows based on those rows.  This will be used to
> intentionally duplicate rows.  Did I mention that I was having little
> luck?  I'm from a PHP world, but I've been getting really into Rails
> lately.
>
> Here's what I've got(assume an event has_many wastes):
>
>   def wastePrepopulate
>   @wastes = Waste.find_all
>   @wastes.each do |waste|
>      Event.find(params[:id]).wastes.create(params[:waste])
>   end
>      flash[:notice] = 'The records have been prepopulated.'
>      redirect_to :action => "showwastes", :id =>params[:id]
>   end
>
> If I feed parameters to it using a form, it will create new records with
> those parameters, but I can't get it to use the data from
> @wastes=Waste.find_all.
>
> I'm ultimately trying to set up a way to create records based on
> existing data.  Any help would be GREATLY appreciated.
>
> Cheers,
> Monkey


Something like this should work

@event = Event.find(params[:id])
@wastes = Waste.find_all
@wastes.each do |waste|
  data = waste.attributes.reject do |key, value|
    key == :id       ||
    key == :event_id
  end
  @event.wastes.create(data)
end

First, you don't to do "Event.find(params[:id])" in a loop since the
result will be the same every time, so sense adding that DB strain.

Second, active record objects have an "attributes" method that dumps
their data to a hash.  We take that hash and reject the keys we don't
want duplicated, in this case the id, since the new rows should have new
ids, and event_id, since we want the new wastes to be associated with
the event we are calling create on.
Jeff S. (Guest)
on 2006-04-23 05:52
Alex W. wrote:
> jeff stevens wrote:
>> Hey all,
>>
>> I'm trying to write something that allows one to copy several rows from
>> a table and create new rows based on those rows.  This will be used to
>> intentionally duplicate rows.  Did I mention that I was having little
>> luck?  I'm from a PHP world, but I've been getting really into Rails
>> lately.
>>
>> Here's what I've got(assume an event has_many wastes):
>>
>>   def wastePrepopulate
>>   @wastes = Waste.find_all
>>   @wastes.each do |waste|
>>      Event.find(params[:id]).wastes.create(params[:waste])
>>   end
>>      flash[:notice] = 'The records have been prepopulated.'
>>      redirect_to :action => "showwastes", :id =>params[:id]
>>   end
>>
>> If I feed parameters to it using a form, it will create new records with
>> those parameters, but I can't get it to use the data from
>> @wastes=Waste.find_all.
>>
>> I'm ultimately trying to set up a way to create records based on
>> existing data.  Any help would be GREATLY appreciated.
>>
>> Cheers,
>> Monkey
>
>
> Something like this should work
>
> @event = Event.find(params[:id])
> @wastes = Waste.find_all
> @wastes.each do |waste|
>   data = waste.attributes.reject do |key, value|
>     key == :id       ||
>     key == :event_id
>   end
>   @event.wastes.create(data)
> end
>
> First, you don't to do "Event.find(params[:id])" in a loop since the
> result will be the same every time, so sense adding that DB strain.
>
> Second, active record objects have an "attributes" method that dumps
> their data to a hash.  We take that hash and reject the keys we don't
> want duplicated, in this case the id, since the new rows should have new
> ids, and event_id, since we want the new wastes to be associated with
> the event we are calling create on.


He shoots...he scores!
You are a gentleman and a scholar!  It worked perfectly.

As for "Event.find(params[:id])" being part of the loop; that was just
an embarrassing oversight.  Your point is clear and well taken.

As for your approach; I wasn't sure if rails would overwrite the ids
automatically or not.  Rejecting attributes makes perfect sense.

Where can I find some good reference.  I've gone through some tutorials
and bought the Agile Rails book, but that isn't cutting it.  Any ideas?
Is there an up to date Active directory reference?  For instance:

data = waste.attributes.reject do |key, value|
    key == :id       ||
    key == :event_id
  end

It's simple, clean and straight forward, but I can't find any place to
find that kind of usage. I would not have come up with "reject", but I
should be able to. What did you read to get to where you are?  I'm
usually a spounge, but I need some water to soak up. ;)

Thanks a bunch for your previous reply, it was just what the doctor
ordered!

Cheers,
Monkey
Bryan D. (Guest)
on 2006-04-23 06:05
Is there something here I'm missing? Why not use ActiveRecord's .clone
method? From api.rubyonrails.org:

"Returns a clone of the record that hasnâ??t been assigned an id yet and
is treated as a new record. Note that this is a "shallow" clone: it
copies the objectâ??s attributes only, not its associations. The extent of
a "deep" clone is application-specific and is therefore left to the
application to implement according to its need."

So, if you wanted to copy every row of a table, you could call clone on
every row and save those returned copies.
Alex W. (Guest)
on 2006-04-23 22:10
Bryan D. wrote:
> Is there something here I'm missing? Why not use ActiveRecord's .clone
> method? From api.rubyonrails.org:
>
> "Returns a clone of the record that hasnâ??t been assigned an id yet and
> is treated as a new record. Note that this is a "shallow" clone: it
> copies the objectâ??s attributes only, not its associations. The extent of
> a "deep" clone is application-specific and is therefore left to the
> application to implement according to its need."
>
> So, if you wanted to copy every row of a table, you could call clone on
> every row and save those returned copies.

Heh, didn't AR had that.

so you can probably rewrire my code as:

@event = Event.find(params[:id])
@wastes = Waste.find_all
@wastes.each do |waste|
  new_waste = waste.clone
  new_waste.event = @event
  new_waste.save
end

As for learning, everything I know is from http://api.rubyonrails.com/
http://www.rubycentral.com/ref/ and the Agile Web D. book.
This topic is locked and can not be replied to.