# Removing eval from seed.rb code

**URL:** <https://www.ruby-forum.com/t/removing-eval-from-seed-rb-code/175614>\
**Category:** Rails\
**Created:** [September 16, 2009, 3:39pm UTC](https://www.ruby-forum.com/t/removing-eval-from-seed-rb-code/175614 "2009-09-16T15:39:18Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![devaulw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8e7dd6/32.png) [@devaulw](https://www.ruby-forum.com/u/devaulw)\
**Post date:** [September 16, 2009, 3:39pm UTC](https://www.ruby-forum.com/t/removing-eval-from-seed-rb-code/175614/1 "2009-09-16T15:39:18Z")

</div>

I have written the below code in my seed.rb file. It takes my old data  
in tab delimited format and brings it into the Rails database.

I want to remove the eval statement as I understand there are problems  
with eval.

Any suggestions are appreciated.

## seed.rb

#TODO move require and plant class to helper  
#TODO do not use eval if possible  
require ‘FasterCSV’

class Plant

def self.grow (model, filename, datamap, headers = true)

```
Kernel.const_get(model).delete_all

table = FasterCSV.table(filename, {
   :headers => headers,
   :header_converters => :symbol,
   :col_sep => "\t" # need the double quotes
   })

table.each do |row|
  record = eval datamap
end

```

end

end

Plant.grow(  
“Business”,  
File.join(File.dirname( **FILE** ), ‘vendor.db’),  
“Business.create(  
:address =\> row[:vendoraddress],  
:city =\> row[:vendorcity],  
:email\_general =\> row[:vendoremail],  
:fax =\> row[:faxnumber],  
:name =\> row[:vendorname],  
:old\_vendorid =\> row[:vendorid],  
:phone =\> row[:vendorphone],  
:sales\_tax\_rate =\> row[:vendorsalestax],  
:zip\_code =\> row[:vendorzipcode]  
)”,  
true)

---

<div class="post-metadata">

**Author:** ![devaulw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8e7dd6/32.png) [@devaulw](https://www.ruby-forum.com/u/devaulw)\
**Post date:** [September 16, 2009, 5:38pm UTC](https://www.ruby-forum.com/t/removing-eval-from-seed-rb-code/175614/2 "2009-09-16T17:38:23Z")

</div>

On Sep 16, 2009, at 6:39 AM, Bill D. wrote:

> I have written the below code in my seed.rb file. It takes my old  
> data  
> in tab delimited format and brings it into the Rails database.
> 
> I want to remove the eval statement as I understand there are problems  
> with eval.
> 
> Any suggestions are appreciated.

I’m sure there’s a more efficient way of re-mapping the fields, but  
the below should work.

class Plant

def self.grow (model\_name, filename, field\_mappings, headers = true)

```
 the_model = Kernel.const_get(model_name)
 the_model.delete_all

 table = FasterCSV.table(filename, {
   :headers => headers,
   :header_converters => :symbol,
   :col_sep => "\t" # need the double quotes
 })

 table.each do |row|
   mapped_fields = {}
   row.each_pair{|k,v| mapped_fields[field_mappings[k.to_sym]] = v}
   record = the_model.create(mapped_fields)
 end

```

end

end

Plant.grow(  
“Business”,  
File.join(File.dirname( **FILE** ), ‘vendor.db’),  
{:address =\> :vendoraddress,  
:city =\> :vendorcity,  
:email\_general =\> :vendoremail,  
:fax =\> :faxnumber,  
:name =\> :vendorname,  
:old\_vendorid =\> :vendorid,  
:phone =\> :vendorphone,  
:sales\_tax\_rate =\> :vendorsalestax,  
:zip\_code =\> :vendorzipcode},  
true  
)

---

<div class="post-metadata">

**Author:** ![devaulw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8e7dd6/32.png) [@devaulw](https://www.ruby-forum.com/u/devaulw)\
**Post date:** [September 16, 2009, 5:58pm UTC](https://www.ruby-forum.com/t/removing-eval-from-seed-rb-code/175614/3 "2009-09-16T17:58:52Z")

</div>

> Thanks for the reply. That definitely gets rid of the eval.
> 
> When I run that code I’m seeing:
> 
> rake aborted!  
> undefined method `each\_pair’ for #FasterCSV::Row:0x2638dbc
> 
> I guess that method is not defined for the FasterCSV::Row class.
> 
> I will take another look this afternoon.

Oh, could be… there’s probably another method that will give you  
back key/value pairs for FasterCSV::Row.

-philip

---

<div class="post-metadata">

**Author:** ![devaulw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8e7dd6/32.png) [@devaulw](https://www.ruby-forum.com/u/devaulw)\
**Post date:** [September 16, 2009, 9:31pm UTC](https://www.ruby-forum.com/t/removing-eval-from-seed-rb-code/175614/4 "2009-09-16T21:31:07Z")

</div>

Philip H. wrote:

> Oh, could be… there’s probably another method that will give you  
> back key/value pairs for FasterCSV::Row.
> 
> -philip

It looks like each\_pair and each are identical methods. I can  
instance.each {|k,v| k = v } no problem.

Any other ideas?

---

<div class="post-metadata">

**Author:** ![devaulw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8e7dd6/32.png) [@devaulw](https://www.ruby-forum.com/u/devaulw)\
**Post date:** [September 16, 2009, 5:53pm UTC](https://www.ruby-forum.com/t/removing-eval-from-seed-rb-code/175614/5 "2009-09-16T17:53:34Z")

</div>

Thanks for the reply. That definitely gets rid of the eval.

When I run that code I’m seeing:

rake aborted!  
undefined method `each\_pair’ for #FasterCSV::Row:0x2638dbc

I guess that method is not defined for the FasterCSV::Row class.

I will take another look this afternoon.

Bill

---

<div class="post-metadata">

**Author:** ![devaulw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8e7dd6/32.png) [@devaulw](https://www.ruby-forum.com/u/devaulw)\
**Post date:** [September 17, 2009, 6:10pm UTC](https://www.ruby-forum.com/t/removing-eval-from-seed-rb-code/175614/6 "2009-09-17T18:10:38Z")

</div>

The standard idiom here is to have grow take a block, thus:

def self.grow (model\_name, filename, headers = true)  
Kernel.const\_get(model).delete\_all  
table = FasterCSV.table(filename, {  
:headers =\> headers,  
:header\_converters =\> :symbol,  
:col\_sep =\> “\t” # need the double quotes  
})  
table.each do |row|  
yield(row)  
end  
end

and then call with:

Plant.grow(…params here…) do |row|  
Business.create(  
:address =\> row[:vendoraddress],  
:city =\> row[:vendorcity],  
:email\_general =\> row[:vendoremail],  
:fax =\> row[:faxnumber],  
:name =\> row[:vendorname],  
:old\_vendorid =\> row[:vendorid],  
:phone =\> row[:vendorphone],  
:sales\_tax\_rate =\> row[:vendorsalestax],  
:zip\_code =\> row[:vendorzipcode]  
)  
end

–Matt J.

On Sep 16, 3:31 pm, Bill D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![devaulw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8e7dd6/32.png) [@devaulw](https://www.ruby-forum.com/u/devaulw)\
**Post date:** [September 17, 2009, 10:31pm UTC](https://www.ruby-forum.com/t/removing-eval-from-seed-rb-code/175614/7 "2009-09-17T22:31:01Z")

</div>

That worked great! Thanks for clearing up the idiomatic usage. I have  
not quite wrapped my head around it yet, but look forward to learning  
more.

For the record, here’s the working code:

#TODO move require and plant class to helper  
#DONE do not use eval if possible – Possible thanks to Matt J. on

> **[Ruby-Forum](https://www.ruby-forum.com/)**
>
> Online Community that helps beginners learn Ruby, and coders solve Ruby coding problems since 2005

require ‘FasterCSV’

class Plant

def self.grow (model, filename, headers = true)  
Kernel.const\_get(model).delete\_all  
table = FasterCSV.table(filename, {  
:headers =\> headers,  
:header\_converters =\> :symbol,  
:col\_sep =\> “\t” # need the double quotes  
})  
table.each do |row|  
yield(row)  
end  
end

end

Plant.grow(“Business”, File.join(File.dirname( **FILE** ), ‘vendor.db’))  
do |row|  
Business.create(  
:address =\> row[:vendoraddress],  
:city =\> row[:vendorcity],  
:domain\_name =\> row[:vendordomainname].to\_s.gsub(/^(www.)+([^  
]_)._/, ‘\2’),  
:email\_general =\> row[:vendoremail],  
:fax =\> row[:faxnumber],  
:iadm\_member =\> row[:iadm],  
:name =\> row[:vendorname],  
:old\_vendorid =\> row[:vendorid],  
:phone =\> row[:vendorphone],  
:sales\_tax\_rate =\> row[:vendorsalestax],  
:zip\_code =\> row[:vendorzipcode]  
)  
end
