Rails - 如何使用嵌套属性验证表单?

时间:2014-12-03 03:33:34

标签: ruby-on-rails ruby

我正在使用来自不同模型的属性创建嵌套表单。在保存新对象之前,我希望所有必需的属性都有效。

<%= form for @product do |f| %>

  <%= f.fields_for @customer do |g| %>

    <%= g.label :name %>
    <%= g.text_field :name %>

    <%= g.label :email %>
    <%= g.text_field :email %>

    <%= g.label :city %>
    <%= g.text_field :city %>

    <%= g.label :state %>
    <%= g.text_field :state %>

    <%= g.label :zipcode %>
    <%= g.text_field :zipcode %>

  <% end %>

  <%= f.label :product %>
  <%= f.text_field :product %>

  <%= f.label :quantity %>
  <%= number_field(:quantity, in 1..10) %>

<% end %>

以下是我的模特

class Product < ActiveRecord::Base

  belongs_to :customer
  validates_associated :customer
  validates :product, :presence => "true"

end

class Customer < ActiveRecord::Base

  has_one :product
  validates :name, :email, presence: true
  validates :email, format: { with: /[A-Za-z\d+][@][A-Za-z\d+][.][A-Za-z]{2,20}\z/ }              
  validates :city, presence: true
  validates :zipcode, format: { with: /\A\d{5}\z/ }

end

我在产品型号中添加了validates_associated,因此我的form_for @product应该要求所有客户验证都通过。这意味着名称,电子邮件,城市和邮政编码必须在那里,并且必须正确格式化。

我摆弄并提交表格而未填写客户必填字段,表格被视为有效。

我不明白我的错误在哪里。

修改

好的,所以通过添加validates :customer,现在需要客户属性。但它们实际上并没有保存到数据库中。我认为这与我的参数有关

def product_params
  params.require(:product).permit(:product, :quantity)
end

我是否需要将我的客户参数添加到我允许的参数列表中?

2 个答案:

答案 0 :(得分:4)

如果对象存在,validates_associated方法仅验证关联的对象,因此如果将表单字段留空,则您正在创建/编辑的Product将验证,因为没有关联的{{ 1}}。

相反,假设您使用的是Rails 4+,您希望使用accepts_nested_attributes_for :customer以及Customer来获取产品表单中的客户字段。

如果您使用的是Rails 3,那么validates :customer, presence: true将不适用于accepts_nested_attributes_for关联。相反,您的belongs_to课程需要使用Customer,您需要相应地更改表单视图。

<强>更新

您还需要允许控制器操作接受accepts_nested_attributes_for :product关联的参数:

:customer

值得注意的是,由于您的客户表单字段中没有def product_params params.require(:product).permit(:product, :quantity, :customer_attributes => [:name, :email, :city, :state, :zipcode]) end 字段,而产品表单字段中没有:id字段,因此每次成功提交产品时都会创建新客户形式。

答案 1 :(得分:2)

试试这个:

在Controller中,按如下方式创建产品和关联客户的实例:

  @product = Product.new
  @customer = @product.build_customer

使用此代码表格

  <%= form for @product do |f| %>

  <%= f.fields_for :customer do |g| %>

    <%= g.label :name %>
    <%= g.text_field :name %>

    <%= g.label :email %>
    <%= g.text_field :email %>

    <%= g.label :city %>
    <%= g.text_field :city %>

    <%= g.label :state %>
    <%= g.text_field :state %>

    <%= g.label :zipcode %>
    <%= g.text_field :zipcode %>

  <% end %>

  <%= f.label :product %>
  <%= f.text_field :product %>

  <%= f.label :quantity %>
  <%= number_field(:quantity, in 1..10) %>

<% end %>

即使用:客户符号而不是@customer实例变量。

并在产品模型中使用accepts_nested_attributes_for辅助方法,因为@Charles说