Chr*_*ris 6 ruby ruby-on-rails lazy-evaluation method-chaining
阅读文章http://jeffkreeftmeijer.com/2011/method-chaining-and-lazy-evaluation-in-ruby/后,我开始寻找方法链和懒惰评估的更好解决方案.
我想我已经用以下五个规格封装了核心问题; 谁能让他们全部通过?
一切顺利:子类化,委托,元编程,但对后者不鼓励.
将依赖关系保持在最低限度是有利的:
require 'rspec'
class Foo
# Epic code here
end
describe Foo do
it 'should return an array corresponding to the reverse of the method chain' do
# Why the reverse? So that we're forced to evaluate something
Foo.bar.baz.should == ['baz', 'bar']
Foo.baz.bar.should == ['bar', 'baz']
end
it 'should be able to chain a new method after initial evaluation' do
foobar = Foo.bar
foobar.baz.should == ['baz', 'bar']
foobaz = Foo.baz
foobaz.bar.should == ['bar', 'baz']
end
it 'should not mutate instance data on method calls' do
foobar = Foo.bar
foobar.baz
foobar.baz.should == ['baz', 'bar']
end
it 'should behave as an array as much as possible' do
Foo.bar.baz.map(&:upcase).should == ['BAZ', 'BAR']
Foo.baz.bar.join.should == 'barbaz'
Foo.bar.baz.inject do |acc, str|
acc << acc << str
end.should == 'bazbazbar'
# === There will be cake! ===
# Foo.ancestors.should include Array
# Foo.new.should == []
# Foo.new.methods.should_not include 'method_missing'
end
it "should be a general solution to the problem I'm hoping to solve" do
Foo.bar.baz.quux.rab.zab.xuuq.should == ['xuuq', 'zab', 'rab', 'quux', 'baz', 'bar']
Foo.xuuq.zab.rab.quux.baz.bar.should == ['bar', 'baz', 'quux', 'rab', 'zab', 'xuuq']
foobarbaz = Foo.bar.baz
foobarbazquux = foobarbaz.quux
foobarbazquuxxuuq = foobarbazquux.xuuq
foobarbazquuxzab = foobarbazquux.zab
foobarbaz.should == ['baz', 'bar']
foobarbazquux.should == ['quux', 'baz', 'bar']
foobarbazquuxxuuq.should == ['xuuq', 'quux', 'baz', 'bar']
foobarbazquuxzab.should == ['zab', 'quux', 'baz', 'bar']
end
end
Run Code Online (Sandbox Code Playgroud)
这是受到Amadan答案的启发,但使用的代码更少:
class Foo < Array
def self.method_missing(message, *args)
new 1, message.to_s
end
def method_missing(message, *args)
dup.unshift message.to_s
end
end
Run Code Online (Sandbox Code Playgroud)
微不足道,不是吗?
class Foo < Array
def self.bar
other = new
other << 'bar'
other
end
def self.baz
other = new
other << 'baz'
other
end
def bar
other = clone
other.unshift 'bar'
other
end
def baz
other = clone
other.unshift 'baz'
other
end
end
Run Code Online (Sandbox Code Playgroud)
该to_s标准失败是因为 1.9 改变了工作方式Array#to_s。更改为兼容性:
Foo.baz.bar.to_s.should == ['bar', 'baz'].to_s
Run Code Online (Sandbox Code Playgroud)
我要蛋糕。
顺便说一句 - 这里的元编程将减少代码大小并极大地提高灵活性:
class Foo < Array
def self.method_missing(message, *args)
other = new
other << message.to_s
other
end
def method_missing(message, *args)
other = clone
other.unshift message.to_s
other
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
781 次 |
| 最近记录: |