How to make this secure?

Hi everyone,

I'm writing a piece of software where I receive the name of an active
record class from the outside (in the request_uri) and want to make a
lookup on whether this active record class exists. Then, I need to do a
.find(...) and whatever on that class.

The following lines do exactly what I want, however, they are
completely *NOT* secure :slight_smile:

def get_activerecord_named(name)
  activerecord = eval(name)
  if activerecord.superclass == ActiveRecord::Base
    return activerecord
  else
    return nil
  end
end

Anyone has a better idea?

A switch/case is not an option as I don't know the names of all
existing active record classes at design time. However, could one find
out the names of all available active record classes at run time?

Thank you, your help is very appreciated!

--jan

Populate a list of models at server startup?

how would you do that?

yeah wrote:

Hi everyone,

I'm writing a piece of software where I receive the name of an active
record class from the outside (in the request_uri) and want to make a
lookup on whether this active record class exists. Then, I need to do a
.find(...) and whatever on that class.

The following lines do exactly what I want, however, they are
completely *NOT* secure :slight_smile:

def get_activerecord_named(name)
  activerecord = eval(name)
  if activerecord.superclass == ActiveRecord::Base
    return activerecord
  else
    return nil
  end
end

Anyone has a better idea?

A switch/case is not an option as I don't know the names of all
existing active record classes at design time. However, could one find
out the names of all available active record classes at run time?

ActiveRecord::Base only finds out about its subclasses when they are loaded. I think it's easier to follow your approach, finding the named class (if there is one), and then finding out if its superclass is ActiveRecord::Base. (Note that if you start introducing inheritance among your model classes you will need to extend this to look beyond the direct superclass.)

Try this:

def get_activerecord_named(name)
   c = name.constantize rescue nil
   if c.class == Class && c.superclass == ActiveRecord::Base
     return c
   else
     return nil
   end
end

Rails adds the constantize method to String, to return the value of the constant named by the String. If there isn't one, it raises a NameError exception - the "rescue nil" clause catches this.

In the if statement, c could be nil, or some non-class constant value, or a class - so a check that it's a class is needed before trying to invoke its superclass method.

regards

   Justin Forder

Thank you, Justin. That looks great!

Justin Forder wrote:

Where are the ruby logs on Mac OS X Tiger?

I need to see the SQL commands the update_all method of ActiveRecord is
sending. Manually running the output of

    class MyTable < ActiveRecord: end
    puts "UPDATE my_table SET #{updates} WHERE #{conditions}
    MyTABLE.update_all(updates, conditions)

yeilds very different results from the result of the command. scope is not
set, so should not be a factor.

Seeing what ActiveRecord is saying to MySQL would really help.

Thanks,
Ric Turley

Look at your log/development.log. Also the query_trace plugin will be useful.

Vish

Thanks for the reply.

Actually, I am doing the "Use ActiveRecord Outside of Rails" trick as I
haven't figured out how to do the user interface yet. I am writing a method
to move a sub-tree in an acts_as_nested_set module.

Hence, I am trying to find the Ruby logs rather than the Rails logs.

Thanks again,
Ric Turley