Ruby: Overloading Indexed Assignment to Instance Attributes

For instances of the class I'm writing (ActiveRecord model), I would like to be able to overload assignments as follows:

m.rank['foo'] = 1
m.rank['bar'] = 2

In other words, I do not want the numbers to be written into the actual hash @rank, but I would like the setter method with 'foo'and to be called as its parameters 1.

A naive way to get this functionality is to define set_rank(key, rank)and get_rank(key), but the syntax is not very cloying. For better syntax, you can define a helper class that defines []both []=and the method rankreturns an instance of this class.

Is there an established template to write this in concise form? Or is it a bad idea in the first place, and I should just use set_rankand get_rank?

+3
source share
2 answers

You can achieve this by initializing your rank attribute as follows:

@rank = {}

def @rank.[] key
    puts "Retrieving key #{key}" #put code to execute when key is retrieved here
    begin
        self.fetch key
    rescue
        puts "Key not found" #put code to execute when key is not found here
        nil
    end
end

def @rank.[]= key, val
    puts "Setting key #{key} to #{val}" #put code to execute when key is set here
    self.store key, val
end

You will need to do this in your method initializeand use attr_reader :rank(recommended) or attr_accessor :rank.

Explanation

This uses a Ruby function called singleton methods. Singleton methods are where you define methods for specific objects, and not for all instances of the class. You can define singleton methods for any object. The syntax is as above def identifier.method ... end.

+4
source

, . :

class Test
    attr_accessor :rank

    def initialize
        @rank = Rank.new
    end

    def meth(key, rank)
        print key, " ", rank
    end 

    class Rank
        def []=(key, rank)
            @test = Test.new
            @test.meth(key, rank)
        end
    end

end

m = Test.new
m.rank["key"] = "rank" # => key rank
+1

Source: https://habr.com/ru/post/1796361/


All Articles