trying to seed data from seeds.rb within a class structure

Hey all,

I created this in seeds.rb because I want to avoid duplication as much as possible:

class DataGenerator   def initialize     @current_user = User.first   end

  def posts!     Title.each do |t|       Body.each do |b|         post! t, b, @current_user.id       end     end   end end

class StaticDataGenerator < DataGenerator   def initialize     super     @created_at = "2011-04-04".to_date     @updated_at = "2011-05-04".to_date     @published = false   end

  def post!(title, body, user_id, options = {})     defaults = {       :title => title,       :body => body,       :created => @created_at,       :updated => @updated_at,       :published => @published,       :user_id => user_id     }     blog_post = BlogPost.create!(defaults.merge(options))   end end

class RandomDataGenerator < DataGenerator   def initialize     super   end end

Title = ["ABC","DEF","GHI","JKL"] Body = ["MNO","PQR","STU","VWX"]

So basically what should happen is a new blog_posts record is written to the database populated with default values like in the following sql statement: INSERT INTO blog_posts (title,body,created_at,updated_at,published,user_id) VALUES("ABC","MNO",2011-04-04,2011-05-04,0,1)

However, when I run rake db:seed, nothing happens. I suspect that it's the class structure of my script that's not being triggered when I run db:seed. Any idea how to address this?

Thanks for response.

Have you tried adding:

StaticDataGenerator.new.posts!

to the end of your file?

Have you tried adding:

StaticDataGenerator.new.posts!

Yeah, that would make sense. I have run into that before where validation or something fails. BYW, does anyone know if there is a way to invoke the debugger during rake db:seed or for that matter any other rake task? I dont think I have ever been successful at this. Maybe have to include ruby-debug or the like?

You can add --trace to the end of your rake command. It’s not a debug per se but will show you what is going on with the rake command at the time. I also like to add a puts statement at the beginning of any call in my rake file. Something like “Begin seeding posts…” then on the next call “Begin seeding comments…”. It helps when you didn’t or forgot to add the --trace flag to see where you are in the process in case it hangs.

B.

Kendall Gifford wrote in post #991124:

Have you tried adding:

  StaticDataGenerator.new.posts!

to the end of your file?

Thanks for response. yes, that worked. That makes sense that you need to call a method in client code for it to do anything. I do have one unexpected result. This method right here:

  def posts!     Title.each do |t|       Body.each do |b|         post! t, b, @current_user.id       end     end   end

I was expecting it to generate a combination like this: "ABC" "MNO" "DEF" "PQR" "GHI" "STU" "JKL" "VWX"

See how it corresponds index 0 of the Title array with index 0 of the Body array and then index 1 of the Title array with index 1 of the Body array and so forth.

But what my posts! method does is this:

"ABC" "MNO" "ABC" "PQR" "ABC" "STU" "ABC" "VWX" "DEF" "MNO" "DEF" "PQR" "DEF" "STU" "DEF" "VWX"

and so forth. See how it generates index 0 of Title with all the indexes of Body and does it for the other indexes of Title as well.

I believe it's my misunderstanding of the nested block:

   Title.each do |t|       Body.each do |b|         post! t, b, @current_user.id       end     end

I thought this would iterate through the first index of Title as local variable t and then iterate through first index of Body as local variable b and then pass them into argument list of post! And then when the outer block ended, it would go to the next index and repeat same process

Anyone know what I am doing wrong and how to get it to match index to index not index to all the other indexes?

Thanks for response.

Kendall Gifford wrote in post #991124:

Have you tried adding:

StaticDataGenerator.new.posts!

to the end of your file? Thanks for response. yes, that worked.

Cool.

That makes sense that you need to call a method in client code for it to do anything. I do have one unexpected result. This method right here:

def posts! Title.each do |t| Body.each do |b| post! t, b, @current_user.id end end end

I was expecting it to generate a combination like this: “ABC” “MNO” “DEF” “PQR” “GHI” “STU” “JKL” “VWX”

See how it corresponds index 0 of the Title array with index 0 of the Body array and then index 1 of the Title array with index 1 of the Body array and so forth.

But what my posts! method does is this:

“ABC” “MNO” “ABC” “PQR” “ABC” “STU” “ABC” “VWX” “DEF” “MNO” “DEF” “PQR” “DEF” “STU” “DEF” “VWX”

and so forth. See how it generates index 0 of Title with all the indexes of Body and does it for the other indexes of Title as well.

I believe it’s my misunderstanding of the nested block:

Title.each do |t| Body.each do |b| post! t, b, @current_user.id end end

Yes, what you were expecting would have been “parallel iteration” (any experts know if there is a more correct term for this?). What you did was “nested iteration” (?). In nested iteration (what you did) your variables at your “innermost” scope will, over the course of the iterations, describe the “cartesian product” (Cartesian product - Wikipedia) of the sets that you’re iterating over. So, with two sets a and b, the total number of combinations (tuples) will be a.length * b.length.

I thought this would iterate through the first index of Title as local variable t and then iterate through first index of Body as local variable b and then pass them into argument list of post! And then when the outer block ended, it would go to the next index and repeat same process

Anyone know what I am doing wrong and how to get it to match index to index not index to all the other indexes?

One way to do what you want would be (assuming Title and Body will always contain the same number of elements):

def posts! Title.each_with_index do |t, i| post! t, Body[i], @current_user.id end end

I’m sure there are more clever, ruby-ish ways for parallel iteration that using #each_with_index.

P.S. - (nyone feel free to correct this or comment if I’m wrong here) here’s a style recommendation: constants such as Class instances (a.k.a class and module definitions or constants that “act” like them) are usually written with only the first letter capitalized. Constants of other types (like your arrays of strings) are usually ALL_CAPS.

P.P.S. - You may also be interested in the following Ruby syntactic sugar:

TITLE = %w{ ABC DEF GHI JKL } BODY = %w{ MNO PQR STU VWX }

This of course only works when all the strings in your array are simple and don’t contain any whitespace.

One way to do what you want would be (assuming Title and Body will always contain the same number of elements):

def posts! Title.each_with_index do |t, i| post! t, Body[i], @current_user.id end end

I’m sure there are more clever, ruby-ish ways for parallel iteration that using #each_with_index.

Okay, I couldn’t help myself. Here’s another alternative/example for this kind of “parallel iteration”

fruits = %w{ apples pineapples oranges } states = %w{ Washington Hawaii Florida }

states.zip(fruits) do |state, fruit| puts “#{state} grows #{fruit}” end

  def posts!     Title.each_with_index do |t, i|       post! t, Body[i], @current_user.id     end   end

each_for_index is very helpful. Thanks a lot for responses.

rdebug rake whatever

Colin