2

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()

Jbur43
  • 1,284
  • 17
  • 38

2 Answers2

0

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
nPn
  • 16,254
  • 9
  • 35
  • 58
  • This forces you to manually set `attr_readers` for reach instance variable you need which defeats the purpose of programmatically defining a method/instance variable. – hkly Apr 28 '20 at 17:12
-1

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
Mr.
  • 9,429
  • 13
  • 58
  • 82
  • That's not how the word "singleton" is used in a Ruby context. In Ruby, a singleton method is a method applied to the Eigen class (in Ruby called the Singleton class) of an object. These methods are effectively attached to the particular instance and not the class of objects. This is reflected in the 2 methods mentioned in the title. define_singleton_method is a public method that creates a singleton method on an abject and define_method is a private method that creates a method on a class. – Peter Camilleri May 12 '19 at 15:41
  • The *Singleton Design Pattern* is only tangentially related to *singleton methods* in Ruby. In particular, the only relationship between the two is that both use the word "singleton" in its standard English (Latin) sense. – Jörg W Mittag May 12 '19 at 15:43