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) -- Posted via http://www.ruby-forum.com/.
On Sep 16, 2009, at 6:39 AM, Bill Devaul 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 )> > 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) > -- > Posted via http://www.ruby-forum.com/. > > >
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 -- Posted via http://www.ruby-forum.com/.
> 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
Philip Hallstrom wrote:> Oh, could be... there''s probably another method that will give you > back key/value pairs for FasterCSV::Row. > > -philipIt looks like each_pair and each are identical methods. I can instance.each {|k,v| k = v } no problem. Any other ideas? -- Posted via http://www.ruby-forum.com/.
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 Jones On Sep 16, 3:31 pm, Bill Devaul <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> Philip Hallstrom 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? > -- > Posted viahttp://www.ruby-forum.com/.
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 Jones on ruby-forum.com 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 -- Posted via http://www.ruby-forum.com/.