views:

48

answers:

1

Background

Currently, I am working on a Rails application. I have different products that can be processed through different vendors. All vendors require a text file in a particular format in order to process the orders.

I decided to use a Factory class to generate instances of the Formatter classes that will render the order information in the proper format.

In the factory class I was considering using the following code:

class ExportFactory
  def self.exporter_class_for_vendor(vendor_name)
    class_name = "ProductExporter#{vendor_name}".gsub(' ','').camelize
    class_name.constantize
  end
end

Question

Would it be save to use ActiveSupport::CoreExtensions::String::Inflections.constantize on data submitted by a user? Or, should I just hard-code the class names.

Note: In this particular application, the only users that would be able to change the given data would be admin users that have full control throughout the system.

+3  A: 

It should be safe, but it depends on what you are doing with it after.

If, for example, you are later calling #delete on the class, the input of File would be dangerous.

My preferred approach is to keep all user accessible classes of this nature in a module, then validate user input against that module's #constants. This ensures you are opening up just a small sub section of the ruby namespace to the user, and also allows you to create drop downs so users can select the module, rather than just guessing the names.

Another way of providing this same level of security is to prefix the name of this module full of available classes on the start of the user input.

module AvailableClasses
  Foo = ::Foo
  Bar = ::Bar
end

validates_inclusion_of :user_input, :in => AvailableClasses.constants

AvailableClasses.const_get(user_input)

"AvailableClasses::#{user_input}".constantize
cwninja
I really like this solution. Thank you.
Matt Haley
Yeah, I really like it too. Always wondered how that would be limited.
Ryan Bigg