Robert Gabaree
2006-Sep-13 23:38 UTC
Need help on simplifying this code (and adding it via Migrations)
Hi guys,
I have a file that contains nutritional information for various foods
(around 7,000 in total). Its format looks like this (for example):
~04133~^~SALAD DRSNG,FRENCH,HOME
RECIPE~^24.20^631^0.10^70.20^1.80^3.40^0.0^^6^0.20^0^3^24^658^0.00^^^1.6
^0.6^0.010^0.020^0.130^0.000^0.000^0^0^0^0^0.00^514^26^0^8.00^^^^^^^12.6
00^20.700^33.700^0^14.00^~1 tablespoon~^220.00^~1 cup~^0
I''m trying to add these values (I''ve seperated them into
arrays) via
migrations and so need to create a column for each value and add the
value to the column. I tried something like this, which seems to work:
def self.up
create_table :foods do |t|
t.column :ndb_no, :string
t.column :shrt_desc, :string
t.column :water, :string
t.column :energ_kcal, :string
t.column :protein, :string
.. snip .. (50 t.column lines in total)
end
IO.foreach("lib/usda_db_files/abbr_version") do |line|
new_line =
line.strip.gsub(/~/,'''').split(''^'')
execute("INSERT INTO foods (ndb_no, shrt_desc, water,
energ_kcal, protein) VALUES
(''#{new_line[0]}'',''#{new_line[1]}'',''#
{new_line[2]}'',''#{new_line[3]}'',''#{new_line[4]}'')")
end
end
But, I have 50 t.column lines in total. I just showed you a small
sniplet. If I was to do this method, I would have to re-type all 50
values into the ( ) fields of the execute statement, and then
continue to add #{new_line[new_number]} after I do one. This can get
confusing, as there''s 50 values to do, and would take an aweful long
time to write out not to mention it looks messy.
Is there a way to simplify this process and do it quicker, or am I
out of luck?
Thanks,
Rob
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk
-~----------~----~----~----~------~----~------~--~---
Chris Hall
2006-Sep-14 00:01 UTC
Re: Need help on simplifying this code (and adding it via Migrations)
you should just be able to do
execute("INSERT INTO `foods` (`" +
Food.column_names.join("`,`") + "`)
VALUES (''" + new_line.join("'',''" +
"'')")
however, i am not sure on a couple of things...
1) if column_names returns the column names in the correct order
2) if this way is database agnostic
but it''s worth a shot
Chris
On 9/13/06, Robert Gabaree <lists-n9Q/XG8udXg@public.gmane.org>
wrote:>
> Hi guys,
>
> I have a file that contains nutritional information for various foods
> (around 7,000 in total). Its format looks like this (for example):
>
> ~04133~^~SALAD DRSNG,FRENCH,HOME
> RECIPE~^24.20^631^0.10^70.20^1.80^3.40^0.0^^6^0.20^0^3^24^658^0.00^^^1.6
> ^0.6^0.010^0.020^0.130^0.000^0.000^0^0^0^0^0.00^514^26^0^8.00^^^^^^^12.6
> 00^20.700^33.700^0^14.00^~1 tablespoon~^220.00^~1 cup~^0
>
> I''m trying to add these values (I''ve seperated them into
arrays) via
> migrations and so need to create a column for each value and add the
> value to the column. I tried something like this, which seems to work:
>
> def self.up
> create_table :foods do |t|
> t.column :ndb_no, :string
> t.column :shrt_desc, :string
> t.column :water, :string
> t.column :energ_kcal, :string
> t.column :protein, :string
> .. snip .. (50 t.column lines in total)
> end
>
> IO.foreach("lib/usda_db_files/abbr_version") do |line|
> new_line =
line.strip.gsub(/~/,'''').split(''^'')
> execute("INSERT INTO foods (ndb_no, shrt_desc, water,
> energ_kcal, protein) VALUES
(''#{new_line[0]}'',''#{new_line[1]}'',''#
>
{new_line[2]}'',''#{new_line[3]}'',''#{new_line[4]}'')")
> end
> end
>
> But, I have 50 t.column lines in total. I just showed you a small
> sniplet. If I was to do this method, I would have to re-type all 50
> values into the ( ) fields of the execute statement, and then
> continue to add #{new_line[new_number]} after I do one. This can get
> confusing, as there''s 50 values to do, and would take an aweful
long
> time to write out not to mention it looks messy.
>
> Is there a way to simplify this process and do it quicker, or am I
> out of luck?
>
> Thanks,
> Rob
>
>
>
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk
-~----------~----~----~----~------~----~------~--~---
johnson_d-j9pdmedNgrk@public.gmane.org
2006-Sep-14 02:19 UTC
Re: Need help on simplifying this code (and adding it via Migrations)
Data model change: Separate the food from the food attributes and turn the table that is giving you headaches 90 degrees. You have three manageable tables instead of one unwieldy table, and migrations are a breeze because new attributes are just data (not table changes). There is a small performance hit, exacerbated by rails insistence on building and preparing the SQL every time you run the query, but for small systems on decent hardware the database hit shouldn''t be too bad. You only have 7,000 rows, so you are looking at IO hit of 7 I/O''s per select on a generational database, or 4 I/O per hit on a locking RDBMS with a good optimizer and support for index only scans. This entire schema will most likely end up in the buffer pool, so you should rarely hit the actual physical store on selects. create table foods ( id integer not null primary key, name varchar (128) not null, recipe memo (8192) ) create table attributes ( id integer not null primary key, name varchar (128) not null, type varchar(20) ) create table attributes_foods ( attribute_id integer not null references attributes(id), food_id integer not null references foods(id), nvalue numeric(10,4), cvalue varchar(50), primary key (attribute_id, food_id) } I hope this helps. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---