以下是模型关系:
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关联。我想通过POST工具的属性集来测试它们(包括几个嵌套的LossRatios,就好像它们是在表单中提交的一样)。我正在使用FactoryGirl,但它似乎没有办法构建类似params的属性哈希(attributes_for忽略了关联,看起来这种行为不会改变)。 有没有办法做到这一点?
(我知道标题很乱,但我无法想到更好更短的内容......)
答案 0 :(得分:0)
好的,这是我把头发拉了半天后想出来的:
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哈希消耗品。我在我的控制器规格中使用它,如:
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
从片段中可以看出,该方法仅填充has-many关联的属性(并忽略has-many-through关联)。我想它可能会扩展到任何一种关系,但到目前为止这对我有用(除非有更好的方式做我想做的事)...