Spade Ace
Spade Ace

Reputation: 3

What is the best way to validate association in Rails?

I have two associated models: Apartment and Lessor. And I need to be able to create Lessor from Apartment form.

In Apartment model:

belongs_to :lessor
before_save :save_lessor
...
def lessor_cellphone= val
  @cellphone = val
end
...
private
def save_lessor
  if Lessor.exists? :cellphone => @cellphone
    self.lessor = Lessor.find_by_cellphone @cellphone
  else
    self.create_lessor :cellphone => @cellphone
  end
  @cellphone = nil
end

In Lessor model:

validates :cellphone, :format => {:with => /\d{11}/}, :uniqueness => true
has_many :apartments, :dependent => :nullify

But when I trying to create Apartment with invalid cellphone, Lessor is not created becouse validation fails, but `Apartment is created.

What is the best way to validate cellphone (and maybe more) and rise error in the Apartment form?

Upvotes: 0

Views: 246

Answers (1)

Vapire
Vapire

Reputation: 4588

I think maybe a better solution would be to use accepts_nested_attributes_for to create a nested model through the form of an other.

See http://railscasts.com/episodes/196-nested-model-form-part-1 or http://asciicasts.com/episodes/196-nested-model-form-part-1 for the text version.

Nontheless, if you want to use your existing solution: If you return false in a before_* callback all the later callbacks and the associated action are cancelled, see http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

So I guess it would be something like

def create_lessor(data)
  # validate data here
  return false if # data not valid
end

def save_lessor
  rc = true
  if Lessor.exists? :cellphone => @cellphone
    self.lessor = Lessor.find_by_cellphone @cellphone
  else
    rc = self.create_lessor(:cellphone => @cellphone)
  end
  @cellphone = nil
  rc  # return the return code
end

It's not a beautiful solution AT ALL, but I think you get the idea...

Upvotes: 2

Related Questions