Benny Lin
Benny Lin

Reputation: 3

Nested attributes validation on updating

I have two model Product and ProductBoxing, product has many product_boxings.

product.rb

class Product < ActiveRecord::Base
   has_many   :product_boxings
   accepts_nested_attributes_for :product_boxings 
   validates :name, presence: { presence: true, message: 'please give a name' }, on: :update
end

product_boxing.rb

class ProductBoxing < ActiveRecord::Base
   belongs_to :product
   validates :quantity, presence: { presence: true, message: 'please fill in quantity' }, on: :update 
end

_form.html.erb

<%= form_for(@product, html: {class: "form-horizontal", role: "form", multipart: true}) do |f| %>
  <%= f.text_field :name%>
  <%= f.fields_for :product_boxings do |g| %>        
      <%= g.text_field :quantity %>     
  <% end %>     
<% end %>

For some reasons, I create both product and product_boxing without validation first. After that, I want to validate both on updating. The validation works for Product, but not for ProductBoxing.

Are there any problem in my code? or it is a rails issue?

BTW, I remove validation option on: :update and validate both on creating, the validations work for both.

update

At first, user will ran the follow code

 def new
   product = Product.new
   p_b= product.product_boxings.build() 
   product.save!    
   redirect_to edit_product_path(product)
 end

then

 def edit
 end

and post form

 def update
   @product.update(product_params)

   unless @product.errors.any?  
     redirect_to products_url      
   else  
     render 'edit'
   end   
 end

other info

def product_params
    params.require(:product).permit(:name, product_boxings_attributes:[:id, :quantity] )
end

Upvotes: 0

Views: 777

Answers (1)

Fran Martinez
Fran Martinez

Reputation: 3052

You should ensure the validation of your associated model:

class Product < ActiveRecord::Base
   has_many   :product_boxings
   validates_associated :product_boxings
   #  ...
end

http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates_associated

TEST THE MODELS WITH THE CONSOLE

> p = Product.new
> p.valid?
> p.errors
> p.product_boxings.each { |pb| pb.valid?; pb.errors }

If you want to see this product_boxings messages in the error list, you should create a custom validation.

validate :associated_product_boxings

def associated_product_boxings
  product_boxings.each do |product_boxing|
     errors.add (...) unless product_boxing.valid?
  end
end

Upvotes: 0

Related Questions