У меня есть идентичный код получения / установки, используемый для нескольких виртуальных атрибутов - могу ли я выполнить рефакторинг с помощью eval? - PullRequest
1 голос
/ 16 мая 2011

Я написал настраиваемые методы получения и установки для виртуальных атрибутов, чтобы преобразовывать десятичные числа в целые числа для хранения в базе данных.Это один из трех виртуальных атрибутов (year_fee_dollars), которые получают / устанавливают из реальных атрибутов (year_fee) в базе данных:

def annual_fee_dollars
  @annual_fee_dollars || int_to_dec(annual_fee)
end

def annual_fee_dollars=(string)
  @annual_fee_dollars = string
  self.annual_fee = dec_to_int(string)
end

Вместо того, чтобы повторять весь этот код три раза, имеет ли смыслэто безопасно для / это 'Rails Way' для рефакторинга кода следующим образом:

def self.decimal_get_and_set(variable, suffix)
  eval (
    "def #{variable + suffix}
      @#{variable + suffix} || int_to_dec(self.#{variable})
    end
    def #{variable+suffix}=(string)
      @#{variable+suffix} = string
      self.#{variable} = dec_to_int(string)
    end")
end
self.decimal_get_and_set "annual_fee", "_dollars"
self.decimal_get_and_set "interest_purchase", "_percent"
self.decimal_get_and_set "interest_cash", "_percent"

Или есть ли более чистый способ создания такого типа функциональности?

Извинения, если этоэто «субъективный вопрос».Частично, все вопросы рефакторинга имеют некоторую субъективность к ним, но я думаю, что этот вопрос все еще имеет место в SO.Рад поправиться на это.

Ура!

1 Ответ

3 голосов
/ 16 мая 2011

Я думаю, что ваш подход хорош, но я бы не советовал использовать eval, в основном потому, что для этого уже есть более подходящий способ метапрограммирования ruby.Ознакомьтесь с документацией для define_method и методами объекта instance_variable_get и instance_variable_set.

Похоже, что вы хотите, и вам не нужно использовать eval самостоятельно.Я бы, вероятно, предложил что-то вроде следующего, но вы правы - все вопросы рефакторинга несколько субъективны по своей природе.Удачи!

{'annual_fee' => '_dollars', 'interest_purchase' => '_percent', 'interest_cash' => '_percent'}.each_pair do |variable, suffix|
  # Define getters
  define_method "#{variable+suffix}" do
    instance_variable_get("@#{variable+suffix}") || int_to_dec(send("#{variable}")
  end

  # Define setters
  define_method "#{variable+suffix}=" do
    ...
  end
end
...