Asociación polimórfica de niña de fábrica con error de establecedor de atributos

I've been banging my head on this one for a while. Someone please resque me.

Guión

Tengo los siguientes modelos

class House < ActiveRecord::Base
  has_one :tenancy, :dependent => :destroy, :as => :tenant
end

class LeaseAgreement < ActiveRecord::Base
  has_many :tenancies
end

class Tenancy < ActiveRecord::Base
  belongs_to :tenant, :polymorphic => true
  belongs_to :lease_agreement

  def lease=(lease)
    if lease.rent_amount > 10000
      # do something here
    else
      # do something else here
    end

    self.lease_agreement = lease
  end
end

My factories

Factory.define :lease_agreement do |l|
  l.name "Foo"
  l.rent_amount 5000
end

Factory.define :tenancy do |t|
  t.name "Foo"
  t.association :tenant, :factory => :house
  t.after_build { |tenancy| tenancy.lease = Factory.create(:lease_agreement) }
end

también probé esto

Factory.define :tenancy do |t|
  t.name "Foo"
  t.association :tenant, :factory => :house
  t.after_build { |tenancy| tenancy.lease = Factory.create(:lease_agreement, :tenant => tenancy) }
end

Both ways in my spec tests when I try this; @house = Factory(:house) Obtuve el siguiente error

NoMethodError: undefined method `rent_amount' for nil:NilClass
from /home/kibet/.rvm/gems/ruby-1.8.7-p352/gems/activesupport-3.0.5/lib/active_support/whiny_nil.rb:48:in `method_missing'
from /home/kibet/code/ruby/stuff/app/models/tenancy.rb:44:in `lease='

¿Cómo haría esto?

preguntado el 09 de marzo de 12 a las 14:03

2 Respuestas

It looks like an order of operations problem, I think lease is being set to nil before it evaluates your after_build hook where lease is a legit LeaseAgreement instance.

You code can't handle a nil lease being passed in, which is a legitimate value if you want to clear the association. Try handling the nil like so:

class Tenancy < ActiveRecord::Base
  belongs_to :tenant, :polymorphic => true
  belongs_to :lease_agreement

  def lease=(lease)
    if lease.present? && lease.rent_amount > 10000
      # do something here
    else
      # do something else here
    end

    self.lease_agreement = lease
  end
end

The code as written will always produce an error with a nil lease passed in.

respondido 12 mar '12, 18:03

thanks for taking the time @Winfield. Your proposal got it working and I've resorted to what you've suggested but I still wonder why my factories didn't work. - Kibet Yegon

I think if you write your factory like this:

Factory.define :tenancy do |t|
  t.name "Foo"
  t.association :tenant, :factory => :house
  t.after_build { |tenancy| tenancy.lease = Factory.create(:lease_agreement) }
end

tu :lease_agreement will then be created correctly, and it should work. There is no tenancy para acceder a una lease_agreement.

respondido 12 mar '12, 22:03

That didn't work, I had already tried that (looks like the logical thing to do in this case) but funny enough it didn't work. Got the same error. - Kibet Yegon

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.