kzen.dev
  • Вопросы
  • Метки
  • Пользователи
Оповещения
Вознаграждения
Регистрация
После регистрации, сможете получать уведомления об ответах и комментариях на Ваши вопросы.
Вход
Если у Вас уже есть аккаунт, войдите чтобы проверить новые уведомления.
Тут будут вознаграждения за добавленные вопросы, ответы и комментарий.
Дополнительно
Источник
Редактировать
 Mike
Mike
Вопрос

Миксины Ruby и вызов суперметодов

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

Пока все хорошо. Кажется, что все работает, но я столкнулся с проблемой, которую не знаю, как решить. Модуль (который я назвал sendable), будет просто кодом, который обрабатывает отправку факса, электронной почты или печать PDF документа. Так, например, у меня есть заказ на поставку, и есть внутренние заказы на продажу (образно сокращенно ISO).

Проблема, с которой я столкнулся, заключается в том, что я хочу, чтобы некоторые переменные инициализировались (инициализировались для тех, кто не знает правильного написания :P ) после загрузки объекта, поэтому я использовал after_initialize хук. Никаких проблем... пока я не начал добавлять новые миксины.

Проблема в том, что я могу иметь after_initialize в любом из моих миксинов, поэтому мне нужно включить вызов super в начале, чтобы убедиться, что вызовы других миксинов after_initialize будут вызваны. Это замечательно, пока я не вызову super и не получу ошибку, потому что нет никакого super для вызова.

Вот небольшой пример, если я не достаточно запутал вас:

class Iso < ActiveRecord::Base
  include Shared::TracksSerialNumberExtension
  include Shared::OrderLines
  extend  Shared::Filtered
  include Sendable::Model

  validates_presence_of   :customer
  validates_associated    :lines

  owned_by                :customer
  order_lines             :despatched # Mixin

  tracks_serial_numbers   :items  # Mixin

  sendable :customer                      # Mixin

  attr_accessor :address

  def initialize( params = nil )
    super
    self.created_at ||= Time.now.to_date
  end
end

Итак, если каждый из миксинов имеет вызов after_initialize с вызовом super, как я могу остановить этот последний вызов super от возникновения ошибки? Как я могу проверить, что суперметод существует до того, как я его вызову?

34 2008-08-14T08:30:27+00:00 5
Программирование
ruby
ruby-on-rails
Решение / Ответ
 valo
valo
5-го октября 2010 в 8:34
2010-10-05T20:34:17+00:00
Дополнительно
Источник
Редактировать
#8414686

Вы можете использовать это:

super if defined?(super)

Вот пример:

class A
end

class B < A
  def t
    super if defined?(super)
    puts "Hi from B"
  end
end

B.new.t
41
0
 newtonapple
newtonapple
14-го августа 2008 в 10:37
2008-08-14T22:37:56+00:00
Дополнительно
Источник
Редактировать
#8414683

Пробовали ли вы использовать alias_method_chain? По сути, вы можете объединить в цепочку все вызовы после_инициализации. Он действует как декоратор: каждый новый метод добавляет новый уровень функциональности и передает управление "переопределенному" методу, который делает все остальное.

Jeff Atwood
Jeff Atwood
Редактировал ответ 15-го августа 2008 в 12:56
3
0
James  A. Rosen
James A. Rosen
15-го августа 2008 в 1:28
2008-08-15T01:28:04+00:00
Дополнительно
Источник
Редактировать
#8414684

Включенный класс (то, что наследуется от ActiveRecord::Base, который в данном случае является Iso) может определить свой собственный after_initialize, поэтому любое решение, кроме alias_method_chain (или другого алиасинга, сохраняющего оригинал), рискует переписать код. Решение @Orion Edwards' - лучшее, что я смог придумать. Есть и другие, но они далее более хакерские.

Преимуществом alias_method_chain является также создание именованных версий метода after_initialize, что означает, что вы можете настроить порядок вызова в тех редких случаях, когда это имеет значение. В противном случае, вы находитесь во власти того порядка, в котором включающий класс включает миксины.

позже:

Я опубликовал вопрос в списке рассылки ruby-on-rails-core о создании пустых реализаций всех обратных вызовов по умолчанию. Процесс сохранения все равно проверяет их наличие, так что я не вижу причин, почему они не должны быть там. Единственный недостаток - создание дополнительных пустых стековых фреймов, но это довольно дешево для каждой известной реализации.

James  A. Rosen
James A. Rosen
Редактировал ответ 15-го августа 2008 в 1:42
3
0
Анонимный пользователь
25-го мая 2009 в 6:53
2009-05-25T06:53:52+00:00
Дополнительно
Источник
Редактировать
#8414685

Вы можете просто бросить быстрое условное предложение там:

super if respond_to?('super')

и Вы должны быть в порядке - никакие добавляющие бесполезные методы; хороший и чистый.

2
0
Orion Edwards
Orion Edwards
14-го августа 2008 в 9:30
2008-08-14T21:30:58+00:00
Дополнительно
Источник
Редактировать
#8414682

Вместо того чтобы проверять, существует ли суперметод, вы можете просто определить его

class ActiveRecord::Base
    def after_initialize
    end
end

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

0
0
Похожие сообщества 6
Чат по Руби
Чат по Руби
2 350 пользователей
Чат-болталка для учеников руби-школы и не только. Сайт школы: https://rubyschool.us Правила: https://telegra.ph/Pravila-chata-Rubi-shkoly-03-13 или тут https://graph.org/Pravila-chata-Rubi-shkoly-03-13
Открыть telegram
RubyRush.ru
RubyRush.ru
2 295 пользователей
Дружелюбный чат для начинающих программистов и учеников rubyrush.ru, обсуждаем программирование, ruby и т. п. Правила чата https://telegra.ph/22-09-05-3 Популярные вопросы (с ответами) https://telegra.ph/22-09-17-4 💎🦜
Открыть telegram
pro.rb (Ruby/Rails / RU)
pro.rb (Ruby/Rails / RU)
1 183 пользователей
Язык программирования Ruby: https://ru.wikipedia.org/wiki/Ruby Вакансии: @rubyjob
Открыть telegram
Ruby — вакансии и аналитика
Ruby — вакансии и аналитика
359 пользователей
Публикуем вакансии и запросы на поиск работы по направлению Ruby. Full-time, part-time, remote и разовые подработки. Обмен инсайдами и аналитикой на рынке труда. Тематическое общение: @ruby_ru См. также: @python_jobs, @nodejs_jobs, @devops_jobs
Открыть telegram
Ruby, Rails, Hanami | dry-rb
Ruby, Rails, Hanami | dry-rb
345 пользователей
Открыть telegram
Ruby Talks
Ruby Talks
255 пользователей
Национальная Флеймотека
Открыть telegram
Добавить вопрос
Категории
Все
Технологий
Культура / Отдых
Жизнь / Искусство
Наука
Профессии
Бизнес
Пользователи
Все
Новые
Популярные
1
Денис Васьков
Зарегистрирован 16 часов назад
2
Dima Patrushev
Зарегистрирован 2 дня назад
3
sirojidddin otaboyev
Зарегистрирован 1 неделю назад
4
Елена Гайдамамакинат
Зарегистрирован 1 неделю назад
5
Иван Степанюк
Зарегистрирован 1 неделю назад
ID
KO
RU
© kzen.dev 2023
Источник
stackoverflow.com
под лицензией cc by-sa 3.0 с атрибуцией