Когда использовать define_singleton_method v define_method - PullRequest
0 голосов
/ 12 мая 2019

В одном ответе на этот вопрос пользователь, мю слишком короткий, объясняет, что вы не хотели бы, чтобы поведение объекта изменялось слишком сильно при инициализации, что имеет смысл, вы должны иметь возможность рассуждать ообъект хорошо, прочитав его определение и будучи интроспективным, но я имел в виду этот случай:

french_colors.yml

blue: blue
red: rouge
...

translations.rb

class Translations
  def initialize(language: "french")
    data = YAML.load_file("./translations/#{language}.yml")
    data.each do |k, v|
      define_method k do
        v
      end
    end

    print_french_colors
  end

  def print_french_colors
    puts red
    puts blue
  end
end

При инициализации вышеупомянутые ошибки с #=> NoMethodError: undefined method `define_method' for #<C:0x2efae80>

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

Будет ли это более разумнымопределить и установить переводы как атрибуты объекта при инициализации вместо использования define_method при инициализации, как это вопросы OP, и я пытался сделать?Или это тот случай, когда метод define_singleton_method был написан специально для таких ситуаций?

Как использовать define_method внутри initialize ()

Ответы [ 2 ]

0 голосов
/ 12 мая 2019

Не ясно, какова ваша конечная цель.Например, я не уверен, почему у вас был бы метод print_french_colors, если бы язык отличался от французского.Похоже, что вы в основном хотите прочитать файл yaml и использовать его для установки значения некоторых предопределенных атрибутов.

Для этого, я думаю, было бы более целесообразно использовать instance_variable_set, а не define_method.Вот пример.

french.yml

blue: blue
red: rouge

require "yaml"
class Translations
  attr_reader :blue, :red 
  def initialize(language: "french")
    data = YAML.load_file("#{language}.yml")
    data.each do |k, v| 
        if respond_to?(k)
          instance_variable_set("@#{k}",v)    
        else 
          puts "#{k} is not defined"
        end
    end

    print_french_colors
  end

  def print_french_colors
    puts red
    puts blue
  end
end

t = Translations.new 
t.print_french_colors
0 голосов
/ 12 мая 2019

вернуться к вашему вопросу ... заменить следующий блок кода

define_method k do
  v
end

с

self.class.send(:define_method, k) do
  v
end
...