Nils and method chaining

后端 未结 9 2427
忘了有多久
忘了有多久 2021-02-14 19:21

I\'m just breaking into the ruby world and I could use a helping hand.

Suppose b is nil.

I\'d like the following code to return n

相关标签:
9条回答
  • 2021-02-14 19:38

    To use a safe_nils similar to that you wrote:

    def safe_nils &blk
      return blk.call
    rescue NoMethodError
      return nil
    end
    
    safe_nils { a.b.c("d").e }
    
    0 讨论(0)
  • 2021-02-14 19:40

    Remark in advance: b is a method, not a variable. So b 'is' not nil, it returns nil.

    When 'b' is a method, why not modify b, so it returns something, what can handle nil.

    See below for an example.


    You may define the missing methods:

    class A
      def b
        nil
      end
    end
    class NilClass
      def c(p);nil;end
      def e;nil;end
    end
    a = A.new
    
    a.b.c("d").e
    

    But I think, a rescue may fit your need better:

    class A
      def b
        nil
      end
    end
    a = A.new
    x = begin a.c.c("d").e 
    rescue NoMethodError
      nil
    end
    

    An example, how you may define a nil-like example.

    class A
      def b
        MyNil.new
      end
    end
    
    class MyNil
      def method_missing(m, *args, &block)
          if nil.respond_to?(m)
            nil.send(m)
        else
          self
        end
      end
      #Simulate nils bahaviour.
      def nil?;true;end
      def inspect;nil.inspect;end
      def to_s;nil;end
    end
    
    a = A.new
    x = a.b.c("d").e 
    p x
    puts x
    p x.nil?
    
    0 讨论(0)
  • 2021-02-14 19:42

    One approach is to use inline assignment to local variables:

    a && (ab = a.b) && (abcd = ab.c("d")) && abcd.e
    

    For as long a chain as you've got here it isn't very elegant, but for a shorter chain it can be useful:

    def date_updated(entry)
      (updated = entry.updated) && updated.content
    end
    
    0 讨论(0)
  • 2021-02-14 19:44

    I think you can find a great solution in rails but that solution follows a different approach. Take a look at the try method. It's a clean approach.

    0 讨论(0)
  • 2021-02-14 19:45

    Starting from ruby v2.3.0 there is another way built into the language, the safe navigation operator (&.) You can write: a&.b&.c&.d and you will safely get nil if one of the calls in the chain returns nil. You can read more about it here: http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/

    0 讨论(0)
  • 2021-02-14 19:46

    Check Ick's maybe:

    a.b.maybe.c("d").maybe.e
    

    or using a block:

    a.b.maybe { |b| b.c("d").e }
    
    0 讨论(0)
提交回复
热议问题