When to use define_singleton_method v define_method

Deadly 提交于 2019-12-25 01:33:29

问题


In one answer to this question user, mu is too short, explains that you wouldn't want an object's behavior to change too drastically on initialization, which makes sense, you should be able to reason about an object well by reading its definition and being introspective but I had this case in mind:

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

When initialized, the above Errors with #=> NoMethodError: undefined method `define_method' for #<C:0x2efae80>

Here you build all of the Translations behavior off of the file received from a translation company and want it as an instance and also want it to be dynamic based on the language file (this is all just an example)

Would it make more sense to define and set the translations as attributes of the object in initialization instead of using define_method in initialization like this questions OP and I were trying to do? Or is it the case that the method define_singleton_method was written to handle situations like this specifically?

How to use define_method inside initialize()


回答1:


Its not clear what your final goal is. For example I am not sure why you would have a print_french_colors method if the language were anything other than french. It seems like you basically want to read a yaml file and use that to set the value of some pre-defined attributes.

To accomplish that, I think it would make more sense to use instance_variable_set rather than define_method. Here is an example.

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



回答2:


back to your question... replace the following code block

define_method k do
  v
end

with

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


来源:https://stackoverflow.com/questions/56100281/when-to-use-define-singleton-method-v-define-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!