Created
October 22, 2013 11:04
-
-
Save basgys/7098697 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UberRelation | |
include Enumerable | |
def initialize(scopes) | |
scopes.kind_of?(Array) or raise ArgumentError.new("Argument scopes is not an array!") | |
@scopes = scopes | |
end | |
def each(&block) | |
block_given? ? load.each{|scope| block.call(scope)} : load | |
end | |
def load | |
scopes.inject([]) {|result, scope| result += scope.load } | |
end | |
private | |
attr_reader :scopes | |
def method_missing(message, *args, &block) | |
dispatch(message, *args, &block) | |
self | |
end | |
def dispatch(message, *args, &block) | |
@scopes = scopes.map {|scope| scope.public_send(message, *args, &block)} | |
end | |
end | |
## ==== Specs ## | |
require "spec_helper" | |
require 'uber_relation' | |
describe UberRelation do | |
subject { described_class } | |
let(:scope) { double("scope") } | |
let(:scopes) { [scope, scope] } | |
let(:relation) { described_class.new(scopes) } | |
before(:each) do | |
allow(scope).to receive(:my_message) | |
allow(scope).to receive(:unknown_message).and_raise(NoMethodError) | |
allow(scope).to receive(:load).and_return(["record A", "record B"], ["record C"]) | |
end | |
describe "#initialize" do | |
it "initializes object successfuly" do | |
expect { described_class.new([]) }.to_not raise_error | |
end | |
it "raises an ArgumentError if scopes is not an array" do | |
expect { described_class.new(nil) }.to raise_error(ArgumentError) | |
end | |
end | |
describe "message distribution" do | |
it "send the message to all scopes successfuly" do | |
expect(scope).to receive(:my_message).twice | |
relation.my_message | |
end | |
it "raises an undefined method if a scope does not respond to the given message" do | |
expect { relation.unknown_message }.to raise_error(NoMethodError) | |
end | |
end | |
describe "chaining" do | |
it "chains a message successfuly" do | |
expect(relation.my_message).to be(relation) | |
end | |
end | |
describe "Enumerable" do | |
it "responds to #each" do | |
expect(relation.each).to be_kind_of(Enumerable) | |
end | |
it "responds to #map" do | |
expect(relation.map {|record| record}).to eq(["record A", "record B", "record C"]) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment