2012-05-03 78 views
0

這裏是模型中的關係:正確地從工廠建設PARAMS嵌套協會RSpec的控制器測試

class Tool < ActiveRecord::Base 
    ... 
    has_many :loss_ratios, :dependent => :destroy, :order => "loss_ratios.starts_at DESC" 

    validates_associated :loss_ratios 
    accepts_nested_attributes_for :loss_ratios, :allow_destroy => true 

    attr_accessible :name, :text, :service_id, :supplier_id, :loss_ratios_attributes 
end 

class LossRatio < ActiveRecord::Base 
    belongs_to :tool 

    validates :rate, :starts_at, :tool, :presence => true 
    validates_uniqueness_of :starts_at, :scope => :tool_id 
    validates_numericality_of :rate 
    validates_inclusion_of :rate, :in => (0..1) 
    ... 
end 

我管理在創建/更新ToolsController行動LossRatio協會。我想通過發佈工具的屬性集(包括幾個嵌套LossRatios,就好像它們是在表單中提交的那樣)來測試這些屬性。我使用的是FactoryGirl,但它似乎沒有構建類似參數的屬性散列(attributes_for忽略關聯,看起來這種行爲不會改變)。 有沒有辦法做到這一點?

(我知道標題是一個爛攤子,但我想不出有什麼更好的和更短......)這裏

回答

0

OK是我想出拉我的頭髮了半天后, :

def params_for(factory_name) 
    exclude_params = [ "id", "created_at", "updated_at" ] 
    f = FactoryGirl.build(factory_name) 

    params = f.attributes.except(*exclude_params).dup 

    f.reflections.select { |k,v| 
    v.macro == :has_many && !v.instance_of?(ActiveRecord::Reflection::ThroughReflection) 
    }.each_key do |k| 
    assoc_collection = f.send(k) 

    unless assoc_collection.empty? 
     params["#{k.to_s}_attributes"] = {} 

     assoc_collection.each_with_index do |assoc_obj,idx| 
     params["#{k.to_s}_attributes"][idx.to_s] = assoc_obj.attributes.except(*exclude_params << "#{f.class.name.underscore}_id") 
     end 
    end 
    end 

    params 
end 

這是一個輔助方法,用於通過控制器的CRUD操作構建params hash消耗品。我用它在我的控制器的規格如下所示:

subject { post :create, :tool => params_for(:tool_with_lr_history) } 

it "creates a new tool" do 
    expect { subject }.to change(Tool, :count).by(1) 
end 

由於從片段可見,方法只用於填充有一對多的關聯屬性(而忽略了一對多,通過協會)。我想這可能會延長任何類型的關係,但目前爲止我的作品(除非有更好的方式做我想做的事)...

相關問題