4 Replies - 10767 Views - Last Post: 25 December 2011 - 04:43 PM Rate Topic: -----

#1 NotarySojac  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 53
  • View blog
  • Posts: 428
  • Joined: 30-September 10

Way to set activerecord variable by string?

Posted 23 December 2011 - 10:45 PM

So I'm having a blast writing a controller in a rails app that allows me to upload a CSV file to my server and then add it's data to the MySQL database on server side. It's been incredibly fun so far, but I have just run into a rather daunting section of code that I need to finish.


  def import_csv
    model_name = params[:table_name].split('.')[0].singularize.capitalize  # 1)  "Products.csv"
    
    @parsed_file=CSV.parse(params[:dump][:file].read)        # 2) 
    
    # get the model object
    model = get_model_object_by_string(model_name)           # 3)
    
    # get the headers                                          4)
    headers = get_headers(@parsed_file)
    @parsed_file.shift  # delete first row in array (which was comprized of column names, not data)
    
    
    gc_count=0
    @parsed_file.each  do |row|
      t=model.new  # t as in table of course
      
      i=0
      headers.each do |column_title|            # 5)
        eval "t.#{column_title} = #{row[i]}"    # if it's a string, it needs to be handled differently...
        i  += 1
      end

      .
      .
      .




See,
1) I take the table name, and convert it into a string which is in effect the model name
2) Then I parse the CSV data into rows of fields.
3) The the fun starts, and I return a reference to the object of the name model_name!
4) I do boring header stuff since the first row of that CSV is headers...

5) Now the fifth section is where I run into my problem...

I'm trying to set a variable on my ActiveRecord model instance... but all I have to go on is the name of the variable as a STRING =(

My solution was to use eval to have it do the work for me, but that method is discouraged on the web. It also means I'll need to code at least three different ways of setting the variable... If it's a string, I need to put quotes around the data in the eval call... If it's a plain old integer, I just leave it as is. And if it's a decimal, I need to look up how ruby does decimals and format the eval thing accordingly. And what about when I've got to do date times in other tables?

I've coded this type of thing before in C# and it feels just awful. Is this the right way to do things?

This post has been edited by NotarySojac: 23 December 2011 - 10:50 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Way to set activerecord variable by string?

#2 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2113
  • View blog
  • Posts: 3,235
  • Joined: 21-June 11

Re: Way to set activerecord variable by string?

Posted 24 December 2011 - 05:29 AM

Assuming column_title is the title of an actual column (as opposed to say an association) and you don't need to go through any custom setter methods, you can just do:

t.write_attribute(column_title, value)


Otherwise you can invoke the foo= using send:

t.send("#{column_title}=", value)


Either solution works no matter what type value is.

This post has been edited by sepp2k: 24 December 2011 - 10:44 AM

Was This Post Helpful? 1
  • +
  • -

#3 NotarySojac  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 53
  • View blog
  • Posts: 428
  • Joined: 30-September 10

Re: Way to set activerecord variable by string?

Posted 24 December 2011 - 10:09 AM

Thanks, the second one worked, but when I tried the first method it was telling me that they were private (since when is that a bother to ruby?). This shaved something like 20-30 lines from my controller and made it look happier =D
Was This Post Helpful? 0
  • +
  • -

#4 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2113
  • View blog
  • Posts: 3,235
  • Joined: 21-June 11

Re: Way to set activerecord variable by string?

Posted 24 December 2011 - 10:44 AM

You're right, it's private, sorry about that. Though now that you mention it, I didn't realize this code was in the controller before. Something like this should definitely go in the model (at which point there's no problem with calling private methods), there's no reason to put it in the controller.

Generally if there are 20-30 lines in the controller to be cut in the first place, that's a good sign, the controller contains too much application logic (where "too much" means "any").
Was This Post Helpful? 1
  • +
  • -

#5 noahgibbs  Icon User is offline

  • New D.I.C Head

Reputation: 8
  • View blog
  • Posts: 17
  • Joined: 18-December 11

Re: Way to set activerecord variable by string?

Posted 25 December 2011 - 04:43 PM

View PostNotarySojac, on 24 December 2011 - 09:09 AM, said:

Thanks, the second one worked, but when I tried the first method it was telling me that they were private (since when is that a bother to ruby?). This shaved something like 20-30 lines from my controller and made it look happier =D


Ruby doesn't worry about some kinds of private, for instance when using "send". But it cares about private methods with normal method calls, like write_attribute. You could use update_attributes() to do the same thing outside a model, but as the previous poster said, you're better off doing that stuff in the model where you're allowed to call it anyway.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1