如何构建链式方法,如:should_receive(:something).with(:params,values).and_return(:something_else)

时间:2011-06-02 17:47:31

标签: ruby-on-rails ruby rspec rspec-rails

我试图让我的代码变得更小,构建一个看起来像RSpec的should_receive的方法,这里的情况是我正在测试一个状态机,我有几个方法,代码如下:

context "State is unknown" do
  before do
    @obj = create_obj(:state => 'unknown')
  end
  context "Event add" do
    it 'should transition to adding if not in DB' do
      @obj.add
      @obj.state.should == 'adding'
    end

    it 'should transition to linking if already in DB' do
      create_obj_in_db
      @obj.add
      @obj.state.should == 'linking'
    end
  end
end

我想将这些代码行替换为类似的代码:

@obj.should_receive(:add).and_transition_to('adding')
@obj.should_receive(:modify).and_transition_to('modifying')

这些方法是如何构建的?

3 个答案:

答案 0 :(得分:2)

简单:

class Obj
  def should_receive(msg)
    self.send(msg.to_sym)
    self
  end
  def and_transition_to(state)
    @state == state
  end
  def add
    @state = 'adding'
  end
end  

现在你可以运行:

obj = Obj.new
obj.should_receive(:add).and_transition_to('adding')
=> true

答案 1 :(得分:0)

它不是ruby-on-rails,但this article给出了Fluent Interface的示例。

public class Pipeline
{
    private Image image;
    public Image CurrentImage
    {
        get { return image; }
        set { image = value; }
    }

    public Pipeline(string inputFilename)
    {
        image = Bitmap.FromFile(inputFilename);
    }

    public Pipeline Rotate(float Degrees)
    {
        RotateFilter filter = new RotateFilter();
        filter.RotateDegrees = Degrees;
        image = filter.ExecuteFilter(image);
        return this;
    }
    :

答案 2 :(得分:0)

链接的重要部分是从对象返回self,因此下一个调用仍然可以在对象上工作。

class Foo
  def one
    puts "one"
    self
  end

  def two
     puts "two"
     self
  end

  def three
     puts "three"
     self
  end
end

a=Foo.new
a.one.two.three