问题
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