Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ rvm:
- 2.0.0
- 2.1.2
script: bundle exec rspec
before_install:
- gem install bundler
5 changes: 3 additions & 2 deletions lib/monads/eventually.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
require 'monads/monad'

module Monads
Eventually = Struct.new(:block) do
class Eventually
include Monad
attr_reader :block

def initialize(&block)
super(block)
@block = block
end

def run(&success)
Expand Down
7 changes: 6 additions & 1 deletion lib/monads/many.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
require 'monads/monad'

module Monads
Many = Struct.new(:values) do
class Many
include Monad
attr_reader :values

def initialize(values)
@values = values
end

def and_then(&block)
block = ensure_monadic_result(&block)
Expand Down
6 changes: 6 additions & 0 deletions lib/monads/monad.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ def method_missing(*args, &block)
end
end

def respond_to_missing?(method_name, include_private=false)
within do |value|
value.respond_to?(method_name, include_private)
end || super
end

private

def ensure_monadic_result(&block)
Expand Down
7 changes: 6 additions & 1 deletion lib/monads/optional.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
require 'monads/monad'

module Monads
Optional = Struct.new(:value) do
class Optional
include Monad
attr_reader :value

def initialize(value)
@value = value
end

def and_then(&block)
block = ensure_monadic_result(&block)
Expand Down
13 changes: 13 additions & 0 deletions spec/monads/eventually_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,26 @@ module Monads
it 'forwards any unrecognised message to the block’s value' do
expect(value).to receive(:challenge)
Eventually.new { |success| success.call(value) }.challenge.run {}
expect { Eventually.new { |success| success.call(value) }.method(:challenge) }.not_to raise_error
expect(Eventually.new { |success| success.call(value) }).to respond_to(:challenge)
end

it 'returns the message’s result wrapped in an Eventually' do
@result = nil
Eventually.new { |success| success.call(value) }.challenge.run { |result| @result = result }
expect(@result).to eq response
end

context 'when value is Enumerable' do
let(:value) { [1, 2, 3] }

it 'forwards any unrecognised message to the value' do
expect(Eventually.new { |success| success.call(value) }.first).to be_a(Eventually)
expect(Eventually.new { |success| success.call(value) }.first.run { |value| value }).to eq 1
expect(Eventually.new { |success| success.call(value) }.last).to be_a(Eventually)
expect(Eventually.new { |success| success.call(value) }.last.run { |value| value }).to eq 3
end
end
end
end
end
13 changes: 13 additions & 0 deletions spec/monads/many_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,24 @@ module Monads
expect(value).to receive(:challenge)
end
many.challenge
expect { many.method(:challenge) }.not_to raise_error
expect(many).to respond_to(:challenge)
end

it 'returns the messages’ results wrapped in a Many' do
expect(many.challenge.values).to eq responses
end

context 'when values are Enumerable' do
let(:values) { [[1, 2], [3, 5]] }

it 'forwards any unrecognised message to the value' do
expect(many.first).to be_a(Many)
expect(many.first.values).to eq [1, 3]
expect(many.last).to be_a(Many)
expect(many.last.values).to eq [2, 5]
end
end
end
end
end
13 changes: 13 additions & 0 deletions spec/monads/optional_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,24 @@ module Monads
it 'forwards any unrecognised message to the value' do
expect(value).to receive(:challenge)
optional.challenge
expect { optional.method(:challenge) }.not_to raise_error
expect(optional).to respond_to(:challenge)
end

it 'returns the message’s result wrapped in an Optional' do
expect(optional.challenge.value).to eq response
end

context 'when value is Enumerable' do
let(:value) { [1, 2, 3] }

it 'forwards any unrecognised message to the value' do
expect(optional.first).to be_a(Optional)
expect(optional.first.value).to eq 1
expect(optional.last).to be_a(Optional)
expect(optional.last.value).to eq 3
end
end
end
end
end