Why Rails can use `if` as hash key but not in Ruby

后端 未结 3 1516
刺人心
刺人心 2021-01-18 20:57

In pure Ruby irb, one cannot type {if: 1}. The statement will not terminate, because irb thinks if is not a symbol but instead the beginning of an

3条回答
  •  野的像风
    2021-01-18 21:37

    The code in your example is part of the Rails DSL. What you are actually setting there is a hash which just happens to look a bit like code.

    Internally, Rails will evaluate this hash specifying conditions to the before_save call.

    In a very simplified version, Rails basically does this when saving:

    class ActiveRecord::Base
      @before_save_rules = []
      def self.before_save(method, options={})
        @before_save_rules << [method, options]
      end
    
      def self.before_save_rules
        @before_save_rules
      end
    
      def save
        # Evaluate the defined rules and decide if we should perform the
        # before_save action or not
    
        self.class.before_safe_rules.each do |method, options|
          do_perform = true
          if options.key?(:if)
            do_perform = false unless send(options[:if])
          end
    
          if options.key?(:unless)
            do_perform = false if send(options[:unless])
          end
    
          send(method) if do_perform
        end
    
        # now perform the actual save to the database
        # ...
      end
    end
    

    Again, this is very simplified and just in the spirit of actual code, but this is basically how it works.

提交回复
热议问题