【问题标题】:Rails - How to validate Form with Nested Attributes?Rails - 如何使用嵌套属性验证表单?
【发布时间】:2014-12-03 03:33:33
【问题描述】:

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

<%= 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

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

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

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

    相反,假设您使用的是 Rails 4+,您希望使用 accepts_nested_attributes_for :customervalidates :customer, presence: true 以便在产品表单中输入客户字段。

    如果您使用的是 Rails 3,那么 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 字段,并且您的产品表单字段中没有:customer_id 字段,因此您每次成功提交产品表单时都会创建一个新客户。

    【讨论】:

    • 好的,我尝试添加validates :customer,现在该字段是必需的。但是当我输入该字段时,它说它丢失了。一定是因为我的参数。我看看能不能解决这个问题
    【解决方案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 符号而不是 @customer 实例变量。

    如@Charles 所说,在 Product 模型中使用 Accepts_nested_attributes_for 辅助方法

    【讨论】:

      【解决方案3】:

      作为其他答案的补充,我控制我在控制器中收到的内容,避免进一步的操作并注意一个值是否不是我想要的。

        def update
          if params[:customer][:product_attributes]["0"][:name] == ""
            redirect_to customer_path(@incident), alert: 'You need to add a name'
          else
            respond_to do |format|
              if @customer.update(customer_params)
                format.html { redirect_to customer_path(@customer), notice: 'Succesfully updated' }
                format.json { render :show, status: :ok, location: @customer }
              else
                format.html { render :edit }
                format.json { render json: @customer.errors, status: :unprocessable_entity }
              end
            end
          end
        end
      

      【讨论】:

        猜你喜欢
        • 2014-09-20
        • 1970-01-01
        • 1970-01-01
        • 2016-11-10
        • 1970-01-01
        • 2011-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多