2016-03-22 160 views
0

我知道你們中有些人已經懷疑我的理智了。我有一個ActiveRecord類,它使用缺少的方法挖掘它擁有的JSON屬性。Rails/Rspec respond_to method_missing lookup

# 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 

但是,這將返回一個堆棧層太深,因爲遞歸,因爲遞歸的..所以現在我一天的命運掌握在你的手!啓迪我O'偉大的人。我將如何測試對缺少方法的迴應。

回答

2

使用respond_to_missing。更多信息here

現在,所有這一切都在說。如果你問我,你的模式仍然看起來ha ha。

Refactors

Ruby有噸的清潔方式這一點。

  1. 使用委託模式

    delegate :method_name, :to => :request_params

    (檢查其他選項DOC)。這應該通過在對象中使用方法來解決您的問題,這樣respond_to?就可以工作,並且您將避免重寫method_missing

  2. 設置request_params(對您的訪問器進行元編程)時生成您的訪問方法。

  3. 使用OpenStruct,因爲這些可以使用Hash進行初始化,例如您的request_params。如果你在上面添加代表團,你應該很酷。

希望這會有所幫助。

+0

嘿@muichkine感謝您的建議,我沒有考慮使用委託模式,我真的很喜歡它!我唯一使用的保留就是'request_params'是一個JSON對象,所以它將不得不像訪問它一樣訪問它。所以也許會遺漏方法,然後使用委託模式爲響應提供一個鉤子。請求參數被設置爲早期對象,並且RI對象僅在稍後保存,所以我將不得不使用'before_save'過濾器來對訪問器進行元化。讓我試試它的代表模式,它看起來像最好的:) TY – TheLegend