Как оптимизировать хэш сопоставления, содержащий похожие ключи и значения?

#ruby-on-rails #ruby #ruby-hash

#ruby-on-rails #ruby #ruby-hash

Вопрос:

У меня есть некоторые константы, определенные следующим образом

 CONSUMER_TYPE = 'consumer'
CONSUMER_1_TYPE = "#{CONSUMER_TYPE}1"
CONSUMER_2_TYPE = "#{CONSUMER_TYPE}2"
CONSUMER_3_TYPE = "#{CONSUMER_TYPE}3"

INDUSTRIAL_TYPE = 'industrial'
INDUSTRIAL_1_TYPE = "#{INDUSTRIAL_TYPE}1"
INDUSTRIAL_2_TYPE = "#{INDUSTRIAL_TYPE}2"
INDUSTRIAL_3_TYPE = "#{INDUSTRIAL_TYPE}3"

SERVICES_TYPE = 'services'
SERVICES_1_TYPE = "#{SERVICES_TYPE}1"
SERVICES_2_TYPE = "#{SERVICES_TYPE}2"
SERVICES_3_TYPE = "#{SERVICES_TYPE}3"
 

Поле записи может иметь такие значения, как services2 или industrial1 . В моей модели я создал метод сопоставления, который должен возвращать хэш с разным набором атрибутов в зависимости от значения поля записи, например

 def classification_attributes
  product_type_mapping[product_type]
end

def product_type_mapping
  {
     CONSUMER_1_TYPE => { abc: abc, vpn: vpn, lbc: lbc },
     CONSUMER_2_TYPE => { abc: abc, vpn: vpn, lbc: lbc },
     CONSUMER_3_TYPE => { abc: abc, vpn: vpn, lbc: lbc },
     INDUSTRIAL_1_TYPE => { vpn: vpn, htt: htt, bnn: bnn },
     INDUSTRIAL_2_TYPE => { vpn: vpn, htt: htt, bnn: bnn },
     INDUSTRIAL_3_TYPE => { vpn: vpn, htt: htt, bnn: bnn },
     SERVICES_1_TYPE => { dhy: dhy, rtt: rtt, abc: abc },
     SERVICES_2_TYPE => { dhy: dhy, rtt: rtt, abc: abc },
     SERVICES_3_TYPE => { dhy: dhy, rtt: rtt, abc: abc }
  }
end
 

Например, если запись содержит значение consumer3 , метод сопоставления должен вернуть { abc: abc, vpn: vpn, lbc: lbc } . Как вы можете видеть, существует много дублирования кода. Мне было интересно, может ли быть более оптимальный и краткий способ решения этой задачи.

Комментарии:

1. Вы выбрали ключи? Почему не classification_attributes принимает аргумент?

2. Затем я объединяю classification_attributes хэш с основным base_attributes . base_attributes.merge(classification_attributes)

Ответ №1:

  1. Используйте символы вместо констант.
  2. Не раскрывайте сопоставление.

Константы в Ruby в основном предназначены для сокрытия информации. Например, если ключ изменяется с consumer1 на до consumer_1 тех пор, пока все обращается к хэшу, с CONSUMER_1_TYPE вами все в порядке. Зачем рисковать?

Вместо этого полностью скройте хэш. Теперь, когда он скрыт, константы не нужны. Используйте символы.

Если все значения будут одинаковыми, поместите их в свои собственные методы.

 def classification_attributes(product_type)
  product_type_mapping[product_type]
end

private def consumer_config
  { abc: abc, vpn: vpn, lbc: lbc }
end

private def industrial_config
  { vpn: vpn, htt: htt, bnn: bnn }
end

private def services_config
  { dhy: dhy, rtt: rtt, abc: abc }
end

private def product_type_mapping
  {
     conumser1: consumer_config,
     consumer2: consumer_config,
     consumer3: consumer_config,
     industrial1: industrial_config,
     industrial2: industrial_config,
     industrial3: industrial_config,
     services1: services_config,
     services2: services_config,
     services3: services_config
  }
end
 

Это все, что я могу сказать без дополнительного контекста. При такой избыточности вы можете разделить product_type на тип и подтип.


Рассмотрите возможность перехода product_type_mapping в config/application.rb, а также любые другие связанные конфигурации. Это сохраняет конфигурацию приложения в одном месте, а не разбросано по разным классам.

 module YourApp
  class Application < Rails::Application
    config.x.consumer_config = { abc: abc, vpn: vpn, lbc: lbc }.freeze
    config.x.industrial_config = { vpn: vpn, htt: htt, bnn: bnn }.freeze
    config.x.services_config = { dhy: dhy, rtt: rtt, abc: abc }.freeze

    config.x.product_type_mapping = {
      conumser1: config.x.consumer_config,
      consumer2: config.x.consumer_config,
      consumer3: config.x.consumer_config,
      industrial1: config.x.industrial_config,
      industrial2: config.x.industrial_config,
      industrial3: config.x.industrial_config,
      services1: config.x.services_config,
      services2: config.x.services_config,
      services3: config.x.services_config
    }.freeze
  end
end

# in your class...

def classification_attributes(product_type)
  Rails.configuration.x.product_type_mapping[product_type]
end
 

Комментарии:

1. Спасибо. Я выбираю ключи, поэтому consumer1 consumer_1 преобразование невозможно.