2014-12-04 30 views
0

在我的rails(4.1.6)應用程序,我有一個contact模型has_one :address, :email如何驗證單個事務中的多個模型?

我使用fields_for構建單一形式的接觸及相關地址和電子郵件:

的意見/聯繫人/新。 html.erb

<%= form_for @contact, ... %> 
    ... 
    <%= fields_for :address do |address_fields| %> 
     <%= address_fields.text_field :street, ... %> 
     <%= address_fields.text_field :city, ... %> 
     ... 
    <% end %> 

    <%= fields_for :email do |email_fields| %> 
     <%= email_fields.text_field :display_name, ... %> 
     <%= email_fields.text_field :mail_id, ... %> 
    <% end %> 
    ... 

<% end %> 

我想需要的電子郵件,而地址是可選的。換句話說,如果沒有提供電子郵件,則不應創建3個模型,但如果僅提供電子郵件,則必須創建電子郵件和聯繫人。這不工作

一種方式是手工驗證其PARAMS在#構建任何東西之前創建contacts_controller和閃存[:錯誤]和返回,不保存,如果沒有指定電子郵件,或保存它,如果一切都很好:

contacts_controller.rb

def create 
    @contact = Contact.new 
    if(params_email_valid? params) 
    @contact.save! 
    @email = Email.create(...) 
    @email.save! 
    ... 
    else 
    flash[:error] = 'Email must be specified to save a contact' 
    redirect_to :root 
    end 
end 

private: 
    def params_email_valid? params 
    !(params[:email][:display_name].blank? || params[:email][:mail_id].blank?) 
    end 

可能工作的另一種方法是將下降到SQL,並通過交易直接SQL調用驗證一切。

但是,這些都不是'軌道方式',因爲驗證屬於模型。所以,我正在嘗試使用validates_presence_of,validates_associated和自定義驗證器的一些組合來驗證此場景。這裏的問題在於,關聯模型的模型級別驗證要求自己已經保存在數據庫中,或者需要將相關模型保存在數據庫中。有沒有辦法在單個事務中驗證所有這些模型?

回答

1

考慮你在模型適當的驗證:

class Contact < 
    has_many :addresses 
    has_many :emails 
    #add 
    accepts_nested_attributes_for :addresses, :emails #you can add some validations here to like reject_all if blank? see the docs 
end 

class Address < 
    belongs_to :contact 
end 

class Email < 
    belongs_to :contact 
end 

在你CompaniesController

def new 
    @contact = Contact.new 
    @contact.addresses.new 
    @contact.emails.new 
end 

def create 
    @contact = Contact.new(contact_params) 
    if @contact.save 
    #redirect add flash 
    else 
    #add flash 
    #render action: new 
end 

protected 
    def contact_params 
    #permit(#contact_fields, address_attributes: [#address_fields], email_attributes: [#email_fields]) 
    end 

你想修改表單這樣

<%= form_for @contact, ... do|f| %> 
    ... 
    <%= f.fields_for :address do |address_fields| %> 
     <%= address_fields.text_field :street, ... %> 
     <%= address_fields.text_field :city, ... %> 
     ... 
    <% end %> 

    <%= f.fields_for :email do |email_fields| %> 
     <%= email_fields.text_field :display_name, ... %> 
     <%= email_fields.text_field :mail_id, ... %> 
    <% end %> 
    ... 

<% end %> 

所以accepts_nested_attributes幫助您驗證孩子以及父母和廣告ds [child]_attributes吸氣劑和吸附劑,所以通常在你的表格中contact[email][display_name]將會變成contact[email_attributes][display_name]