Псевдоним класса в Ruby - PullRequest
       16

Псевдоним класса в Ruby

41 голосов
/ 17 октября 2011

Я занимаюсь разработкой нового приложения Rails на основе аналогичного существующего.В моем старом приложении у меня есть класс Coupon, который очень похож на Ticket в моем новом приложении.Я хочу повторно использовать весь код в Coupon, но с новым именем класса.

Поскольку рефакторинг является громоздким в Rails, мне интересно, есть ли способ создать псевдоним для класса в Ruby (аналог псевдонима для атрибутови методы).

Ответы [ 5 ]

84 голосов
/ 17 октября 2011

Классы не имеют имен в Ruby. Это просто объекты, назначенные переменным, как и любой другой объект. Если вы хотите сослаться на класс через другую переменную, присвойте его другой переменной:

Foo = String
15 голосов
/ 20 февраля 2012

в файле coupon.rb:

class Coupon 
  #...
end

# add this line of code to make alias for class names
# option1. if you haven't defined a "Ticket" class: 
Ticket = Coupon   

# option2. if Ticket has been defined, you have to redefine it: 
Object.send :remove_const, "Ticket"
const_set "Ticket", Coupon

«Любая ссылка, которая начинается с заглавной буквы, включая имена классов и модулей, является константой» - << metaprogramming ruby ​​>>, стр. 38, секция констант

5 голосов
/ 16 марта 2015

Любой, кто приезжает сюда, ищет псевдоним класса модели рельсов, чтобы иметь новое имя:

Я мог просто сделать Foo = Bar, но мне пришлось поместить Foo в файл собственной модели, чтобы я не получил неинициализированную постоянную ошибку. например,

# models/foo.rb
Foo = Bar

Также вы можете обнаружить странность, пытаясь использовать псевдоним в ассоциациях, таких как has_many, has_one и т. Д. Я обнаружил, что вы обычно можете обойти их, используя корневое пространство имен (или соответствующее пространство имен в зависимости от того, как ваши модели структурированный), чтобы убедиться, что Rails пытается автоматически загрузить нужную константу:

has_many :foo, class_name: '::Foo'
2 голосов
/ 04 ноября 2013

Вы должны быть осторожны с этим, потому что, если ваш класс претерпевает какие-либо изменения состояния (добавленные функции, измененные константы, переменные класса и т. Д.), Состояние, в котором ваш класс находился в , когда псевдоним былэкземпляр не будет отражать обновленные изменения в вашем классе.

Чтобы избежать запястного канала без ущерба для читаемости , вы можете хранить лямбду в своем псевдониме, а не в фактическом классе.Конечно, лямбда содержит класс, но это гарантирует, что ваш псевдоним вызовет последнюю версию вашего класса.

Я поместил это в свой инициализатор supermanpatches.rb rails (внутри config/initializers/) ‡

LAP = lambda { LosAngelesParcel }

Теперь вы можете вызвать это, используя LAP[], и будет загружена только что выпущенная версия вашего класса.(Позволяет вам создавать экземпляры, например, с помощью l = LAP[].new)

запускается один раз при загрузке rails, а затем распространяется через ваше приложение, вызывается в любом месте, как глобальная переменная, но 'read-только ", так сказать .

2 голосов
/ 17 октября 2011

Я согласен с Warhog, более или менее - но я бы подкласс подкласса из вашего класса купонов - таким образом, если вам нужно сделать какие-либо данные, вы можете поместить код в свой класс билета

...