0

モデルの関係は次のとおりです。

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することによってそれらをテストしたいと思います(フォームで送信されたかのようにネストされたLossRatioをいくつか含みます)。FactoryGirlを使用していますが、属性のparamsのようなハッシュを作成する方法がないようです(attributes_forは関連付けを無視し、この動作は変更されないようです)。これを行う方法はありますか?

(タイトルがめちゃくちゃだとは思いますが、これ以上短いものは考えられませんでした...)

4

1 に答える 1

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ハッシュを構築するために使用されるヘルパーメソッドです。私は次のようにコントローラーの仕様でそれを使用しています:

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アソシエーションは無視します)。私はそれがどんな種類の関係にも拡張されるかもしれないと思います、しかしそれは今のところ私のために働きます(私が望むことをするより良い方法がない限り)...

于 2012-05-04T07:28:14.980 に答える