Home > Back-end >  how to break chain with yield_self
how to break chain with yield_self

Time:12-19

Is it possible to break yield_self (then) chain in ruby?

"a".then { |str| <break> if break_condition }.then { |str| str << "b" } # => I need "a"

CodePudding user response:

You could move the whole code into another method and "break" the chain with a simple return:

def foo
  "a".then { |str| return str if break_condition ; str }
     .then { |str| str << "b" }
end

You could utilize catch and throw:

catch do |brk|
  "a".then { |str| throw(brk, str) if break_condition ; str }
     .then { |str| str << "b" }
end

Alternatively, you could not use then in the first place:

str = "a"
str << "b" unless break_condition

CodePudding user response:

I don't think that you can "break" the chain without raising an exception but you can pass a tagged value from the first block to the second one:

"a".
    then { |str| [str, !break_condition] }.
    then { |str,do_it| do_it ? str << "b" : str }

edit: An other form that might be easier to work with:

"a".
    then { |str| break [str,true] if break_condition; str }.
    then { |str,broken| break str if broken; str << "b" }

CodePudding user response:

You can refactor your chain with using just one then like this

result =
  "a".then do |str|
    next str if break_condition
    str << "b"
  end

or

result =
  "a".then do |str|
    break str if break_condition
    str << "b"
  end

CodePudding user response:

This might be silly, but since you can't break or return, I guess raise should do it:

def broken break_condition
  begin
    "a"
      .then { |str| break_condition ? raise(str) : str }
      .then { |str| str << "b" }
  rescue RuntimeError => e
    str = e.message
  end
end

>> broken true
=> "a"
>> broken false
=> "ab"

One liner works too:

>> "a".then { |str| true ? raise(str) : str }.then { |str| str << "b" } rescue $!.message
=> "a"
>> "a".then { |str| false ? raise(str) : str }.then { |str| str << "b" } rescue $!.message
=> "ab"

Best silly solution I could come up with:

>> "a".then{@a=_1}.then { |s| s if false }&.then { |s| s << "b" }||@a
=> "a"
>> "a".then{@a=_1}.then { |s| s if true }&.then { |s| s << "b" }||@a
=> "ab"
  •  Tags:  
  • ruby
  • Related