views:

72

answers:

1

in the extract of my script code (see the first piece of code below) I use the array @post_csv_order to specify the order and key => value relationship of elements for the hash @post[post_id]. I run the assignment line @post[forum_id] = Hash[*@post_csv_order.flatten] in a loop when I collected all values (like forum_id, post_title etc). Why I want to have this array? I want to have all the key names (=csv headers) and key => value definition at one place only. So when I change the order or I add new detail I want to store, I do not have to make any more changes anywhere else in the code. I want to have that one array approach even if using object instead of hash.

To create the array @post_csv_order the second item of the array must be defined otherwise I get undefined local variable or method.

Little bit more about the whole script: it flows like that- I parse a forum page and that gives me an array of posts.I process that and get all details I want per post and store it.I want to use the array @post_csv_order at this point, to create new hash of these details. I also want to use the array @post_csv_order to save all data I got into csv and also to read that csv next time when I run the script so I can update any fields (like last post author,last post date,number of views).

require 'pp'

@post = {}

forum_id = 123
post_title = "Test post"

@post_csv_order = [
  ["ForumID" , forum_id],
  ["Post title", post_title]  
 ]

@post[forum_id] = Hash[*@post_csv_order.flatten]                       

pp @post

so I thought I can fix it by defining all variables used in the array and assigning empty string to them forum_id , post_title = "" but I am not sure if it's the right way how to do this in ruby.

require 'pp'

@post = {}

forum_id , post_title = ""

@post_csv_order = [
  ["ForumID" , forum_id],
  ["Post title", post_title]  
 ]

forum_id = 123
post_title = "Test post"

@post[forum_id] = Hash[*@post_csv_order.flatten]                       


pp @post

PS. Could somebody suggest or edit the title? I don't know how to name it...

+1  A: 

I'm not entirely clear on what you're trying to do, but I think you might get around a lot of your challenges by using a Post object, which has a forum id, post title, etc. Your import method would create a number of these objects, which could then be manipulated, set to defaults, etc without using a hash.

EDIT

I think the "ruby-ist" way of doing what you describe would be:

@post_csv_order = [
  ["ForumID" , Method_To_Get_Forum_Id_Or_Nil || ""],
  ["Post title", Method_To_Get_Post_Title_Or_Nil || ""]  
 ]

But I'm still not clear on what you're doing - is this method in the iteration of the CSVs rows?

EDIT 2 The problem with Hashes are that they are not guaranteed to maintain ordering, so you'd need to confirm the order once it's out. In pseudo code, it sounds like you want to do the following:

  • Parse Page -> results in many forum entries
  • Take forum entries and save them with proper ordering and unique key for future retrieval
  • Reload the objects at a later date, compare them to the a new pass at the parsed forum, and update (and save) if different

I'm afraid I'm going to have to point you back at using ActiveRecord and objects. Using a Hash here is possible, but this is exactly what Ruby and Rails are designed to do for you.

For example, to do what you're doing above, all you would have to do is (mostly real code):

p = Post.new
p.unique_key = create_unique_key(forum_id)
p.forum_id = forum_id
p.post_title = post_title
p.save

and to get them back later (mostly real code):

all_posts = Posts.find(:all)
all_posts.each do | post |
   update_if_changed(post, parsed_post[post.unique_key])
end
aronchick
@aronchick: yes, you're right. It seems to me easier to do it that wasy.I was thinking about that too. I might rewrite the code to use object. Still I would like to know the answer. If there is any :-) Thank you for your suggestion...
Radek
@aronchick: I edited the question and added **Little bit more about the whole script** paragraph
Radek
@aronchick: the code you provided is from ActiveRecord?
Radek
@aronchick: I was thinking yesterday of rewriting my code using objects but I do not know how to "solve" the same when I use hashes. I want to have an array that keeps **definition of the "header => value" relationships** for the data the script scrapes from the net and the **order of the data scraped**. And I want to use this array in different parts of my script. I do not know how to **declare the array without knowing the values** from the net. This is the 'trouble' if I use either hashes or object.... to be continued
Radek
... I need this array when I create new hash/instance of the object, when I save the all hashes/objects into csv file. This array is used also when saving headers for csv file. Which I guess would be outside the object.
Radek
You don't need to declare an array without knowing the values. Just download all the content, and then instantiate a new object for each object downloaded. In the object, keep a value in the object that has the order of the scraping.
aronchick
@aronchick: I am not so confident with objects... I was thinking the way you say but then I did not know how to save headers of csv file. Which would be the first column from my array.
Radek
If you're using activerecord, you wouldn't need to save the headers. The object's properties would be the field you assigned them to.
aronchick