Class method vs constant in Ruby/Rails

前端 未结 4 812
野性不改
野性不改 2020-12-13 12:51

I was implementing a form that includes a hard-coded dropdown for a collection and I was wondering what would be the best solution, I know both ways exposed below work, stil

4条回答
  •  无人及你
    2020-12-13 13:36

    TL;DR: It depends. Are the values meant to be used outside the class? Could they ever become dynamic? Could they change for subclasses?

    As @sawa wrote, the downside of the method (written this way) is that a new array and strings are created each time.

    A better way to write it would be:

    class Example
      def self.options
        @options ||= ['Yes', 'No', 'Not sure']
      end
    end
    

    The array is stored in the instance variable @options, to avoid creating a new array each time.

    Written this way, the method is very similar to the constant.

    One key difference is if Example is subclassed, it will be more natural to refine the options method than the constant OPTIONS:

    class Parent < Example
      def self.options
        @options ||= [*super, 'Extra']
      end
    end
    

    To do something similar with constants is difficult. Imagine that your list of options is used in a class method, this would look like:

    class Example
      OPTIONS = ['Yes', 'No', 'Not sure']
    
      def self.foo(arg)
         puts "Available options:",
              self::OPTIONS  # The self:: is needed here
         # ...
      end
    end
    
    class Parent < Example
      OPTIONS = [*superclass::OPTIONS, 'Extra']
    end
    

    The tricky thing about constants, is that self::OPTIONS and OPTIONS are not the always same, while self.options and options are the same. Constants are usually used without specifying the scope (e.g. OPTIONS instead of self::OPTIONS) and inheritance will simply not work in that case.

    Note that the method gives you the opportunity to make the result dynamic (i.e. return different results depending on other circumstances) without changing the API.

    Final note: I'd recommend calling freeze on your array, to avoid anyone modifying it.

提交回复
热议问题