С точки зрения Ruby, "#{x}"
просто эквивалентно x.to_s
, что для значений String точно такое же, как и сама строка. В других языках, таких как PHP, вы можете отменить ссылку на строку и рассматривать ее как класс, но здесь это не так. Что вы, вероятно, имеете в виду, это:
fruit_class = fruit_type.titleize.singularize.constantize
fruit_class.create(...)
Метод constantize
преобразует строку в эквивалентный класс, но он чувствителен к регистру.
Имейте в виду, что вы подвергаете себя риску того, что кто-то может создать что-то с fruit_type
, установленным на "users"
, а затем продолжить и создать учетную запись администратора. Возможно, более ответственным является дополнительная проверка того, что то, что вы делаете, действительно относится к нужному классу.
fruit_class = fruit_type.titleize.singularize.constantize
if (fruit_class.superclass == Fruit)
fruit_class.create(...)
else
render(:text => "What you're doing is fruitless.")
end
При загрузке классов таким способом следует обратить внимание на то, что constantize
не будет автоматически загружать классы, как это делается в вашем приложении. В режиме разработки вы не сможете создавать подклассы, на которые нет явной ссылки. Вы можете избежать этого, используя таблицу сопоставления, которая решает потенциальную проблему безопасности и предварительно загружая все сразу:
fruit_class = Fruit::SUBCLASS_FOR[fruit_type]
Вы можете определить эту константу следующим образом:
class Fruit < ActiveRecord::Base
SUBCLASS_FOR = {
'apples' => Apple,
'bananas' => Banana,
# ...
'zuchini' => Zuchini
}
end
Использование константы литерального класса в вашей модели приведет к их немедленной загрузке.