2011-06-06 59 views
2

我有一張表,其中需要在運行時通過外部服務的附加數據更新數據。我想要做的是這樣的:如何在返回之前修改Rails ActiveRecord查詢結果?

MyModel.some_custom_scope.some_other_scope.enhance_with_external_data.each do |object| 
    puts object.some_attribute_from_external_data_source 
end 

即使我不能使用這個確切的語法,我想最終的結果要尊重我可以使用任何範圍。我已經試過這樣:

def self.enhance_with_external_data 
    external_data = get_external_data 
    Enumerator.new do |yielder| 
    # mimick some stuff I saw in ActiveRecord and don't quite understand: 
    relation.to_a.each do |obj| 
     update_obj_with_external_data(obj) 
     yielder.yield(obj) 
    end 
    end 
end 

這主要工作,除了它不尊重施加以往任何範圍,所以,如果我這樣做:

MyModel.some_custom_scope.some_other_scope.enhance_with_external_data 

它還給ALL MyModels,不只是由some_custom_scope和some_other_scope限定的那些。

希望我想要做的事情是有道理的。任何人都知道如何去做,或者我想把一個方形的釘子放在一個圓孔裏?

回答

2

我想出了一個辦法來做到這一點。的醜樣,但似乎工作:

def self.merge_with_extra_info 
    the_scope = scoped 
    class << the_scope 
    alias :base_to_a :to_a 
    def to_a 
     MyModel.enhance(base_to_a) 
    end 
    end 
    the_scope 
end 

def self.enhance(items) 
    items.each do |item| 
    item = add_extra_item_info(item) 
    end 
    items 
end 

這樣做是添加一個類的方法,以我的模型 - 其中原因不明我似乎也使其可用於的ActiveRecord ::關係實例。它僅覆蓋當前作用域對象的to_a方法,該方法被調用以獲取記錄。這讓我可以在返回之前爲每條記錄添加額外的信息。所以,現在我得到的所有chainability和一切都像:

MyModel.where(:some_attribute => some_value).merge_with_extra_info.limit(10).all 

我會喜歡能夠在它得到,因爲它列舉與後它置入喜歡這裏的數組,但無法弄清楚如何深入研究AR/Arel。

+0

這真的幫助。謝謝。我有點擔心「class << the_scope」位會覆蓋所有範圍的「to_a」。但它似乎並沒有。這很棒。 – kierantop 2014-10-28 12:30:38

0

我取得了一些類似的通過擴展的關係:

class EnhancedModel < DelegateClass(Model) 
    def initialize(model, extra_data) 
    super(model) 
    @extra_data = extra_data 
    end 

    def use_extra_data 
    @extra_data.whatever 
    end 
end 

module EnhanceResults 
    def to_a 
    extra_data = get_data_from_external_source(...) 
    super.to_a.map do |model_obj| 
     EnhancedModel.new(model_obj, extra_data) 
    end 
    end 
end 

models = Model.where('condition') 
models.extend(EnhanceResults) 
models.each do |enhanced_model| 
    enhanced_model.use_extra_data 
end 
相關問題