Rails / Rspec响应method_missing查找

时间:2016-03-22 15:15:10

标签: ruby-on-rails ruby rspec

我知道你们中的一些人已经怀疑我的理智了。我有一个ActiveRecord类,它使用缺少的方法来挖掘它所拥有的JSON属性。

  # app/models/request_interactor.rb

  ...

  def method_missing(method_sym, *arguments, &block)
    return self.request_params[method_sym.to_s] if self.request_params[method_sym.to_s]
    super
  end

测试看起来像这样

before(:each) do
  @ri = RequestInteractor.create(result: {magic_school: true, magic_learnt: 'all things magical'}, request_params: {application_id: 34, school_id: 20, school_name: 'Hogwarts', course_name: 'Defence against the Dark Arts.'})
end

it 'should respond to attributes set in the request parameters' do
  expect(@ri).to respond_to(:school_name)
  expect(@ri.school_name).to eq('Hogwarts')
end

我尝试在测试中绑定,@ri.school_name将eq 'Hogwarts',但当它运行responds_to时,它将失败,说没有这样的方法!肮脏,肮脏的骗子!

我尝试在模型中做这样的事情:

def respond_to?(method, include_private = false)
  super || self.respond_to?(method, include_private)
end

但是由于递归,这将导致堆栈级别太深,因为递归..所以现在我的命运掌握在你手中!启发我哦,伟大的。我如何测试缺失方法的响应。

1 个答案:

答案 0 :(得分:3)

使用respond_to_missing。更多信息here

现在,所有这一切都在说。如果你问我,你的模式看起来仍然是黑客。

<强> Refactors

Ruby有很多方法来清理它。

  1. 使用委托模式

    delegate :method_name, :to => :request_params

    (检查doc中的其他选项)。这可以通过在对象中使用方法来解决您的问题,以便respond_to?能够正常工作,并且您将避免覆盖method_missing

  2. 设置request_params(对访问者进行元编程)时生成访问方法。

  3. 使用OpenStruct,因为可以使用Hash request_params初始化这些内容。如果你在上面添加委托,你应该很酷。

  4. 希望这有帮助。