Rails Activerecord, Nested Validations
<p>I've been worrying this bug for too many days and I'm not sure what I'm missing.</p>

<p>I have a parent model named 'product' and a child of it 'product_attachment'. 
Validation within child model is successful on create to disallow a blank image field via  /product_attachments#new</p>

<p>However, when using its parent form /product#new (files below) I'm expecting it to validate to successfully fail without an image. However, Activerecord is ignoring the error, and my controller is tryign to save as a result if the validation passing then complaining that my product_attachments is null.</p>

<p>I'm currently in the understanding that using the 'validates_associated' would validate the child model as part of the Parent's process but this has not been working.
Instead of passing a happy failed validation mid-form to allow user to take action, we leave form and the controller tries to process the create method which fails due to no attachment.
Since I should always have an attachment have been trying to fix this validation to no avail.</p>

<p>Any help appreciated, I've include similar code samples before for your feedback.
I'm fairly new to rails so I'm hoping I'm mis-using a key syntax or context.</p>

<p>Also curious what cause is and what best way was to troubleshoot as I'm still developing good debug practices.</p>

<p>product.rb</p>

<pre><code>class Product &lt; ActiveRecord::Base

  has_many :product_attachments
  validates_presence_of :title, :message =&gt;  "You must provide a name for this product."
  accepts_nested_attributes_for :product_attachments, allow_destroy: true#, 
  validates_associated :product_attachments
end
</code></pre>

<p>product_attachment.rb <em>(carrierwave to handle uploading used here, seems to work fine)</em></p>

<pre><code>class ProductAttachment &lt; ActiveRecord::Base
  belongs_to :product 
  mount_uploader :image, ImageUploader
  validates_presence_of :image, :message =&gt;  "You must upload an image to go with this item."
end
</code></pre>

<p>products_controller.rb</p>

<pre><code>class ProductsController &lt; ApplicationController
  before_action :set_product, only: [:show, :edit, :update, :destroy]

  def index
    @products = Product.all
  end

  def show
    @product_attachments = @product.product_attachments.all
  end

  def new
    @product = Product.new
    @product_attachment = @product.product_attachments.build
  end

  def edit
  end

  def create
    @product = Product.new(product_params)
    respond_to do |format|
      if @product.save
        params[:product_attachments]['image'].each do |a|
          @product_attachment = @product.product_attachments.create!(:image =&gt; a)
        end
        format.html { redirect_to @product, notice: 'Product was successfully created.' }
      else #- when would this fire?
        format.html { render :new }
      end
    end
  end

  def update
    respond_to do |format|
      if @product.update(product_params)
          params[:product_attachments]['image'].each do |a|
            @product_attachment = @product.product_attachments.create!(:image =&gt; a, :post_id =&gt; @post.id)
          end
        format.html { redirect_to @product, notice: 'Product was successfully updated.' }
      else #- when would this fire?
        format.html { render action: 'new' }
      end
    end
  end

  def destroy
    @product.destroy
    respond_to do |format|
      format.html { redirect_to @product, notice: 'Product was successfully destroyed.' }
    end
  end

  private
    def set_product
      @product = Product.find(params[:id])
    end
    # we pass the _destroy so the above model has the access to delete
    def product_params
      params.require(:product).permit(:id, :title, :price, :barcode, :description, product_attachment_attributes: [:id, :product_id, :image, :filename, :image_cache, :_destroy])
    end

end
</code></pre>

<p>product_attachments_controller.rb</p>

<pre><code>class ProductAttachmentsController &lt; ApplicationController
  before_action :set_product_attachment, only: [:show, :edit, :update, :destroy]

  def index
    @product_attachments = ProductAttachment.all
  end

  def show
  end

  def new
    @product_attachment = ProductAttachment.new
  end

  def edit
  end

  def create
    @product_attachment = ProductAttachment.new(product_attachment_params)

    respond_to do |format|
      if @product_attachment.save
        @product_attachment.image = params[:image]
        format.html { redirect_to @product_attachment, notice: 'Product attachment was successfully created.' }
      else
        format.html { render :new }
      end
    end
  end

  def update
    respond_to do |format|
      if @product_attachment.update(product_attachment_params)
        @product_attachment.image = params[:image]
        format.html { redirect_to @product_attachment.product, notice: 'Product attachment was successfully updated.' }
      else
        format.html { render :edit }
      end
    end
  end

  def destroy
    @product_attachment.destroy
    respond_to do |format|
      format.html { redirect_to product_attachments_url, notice: 'Product attachment was successfully destroyed.' }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_product_attachment
      @product_attachment = ProductAttachment.find(params[:id])
    end

    def product_attachment_params
      params.require(:product_attachment).permit(:id, :product_id, :image, :image_cache)
    end
end
</code></pre>

<p>_form.html.slim <em>(using simple_form + slim + cocoon here...)</em></p>

<pre><code>= simple_form_for @product do |f|

  - if @product.errors.any?
    #error_explanation
      h2
        = pluralize(@product.errors.count, "error")
        |  prohibited this product from being saved:
      ul 
        - @product.errors.each do |attribute, message|
          - if message.is_a?(String)
            li= message

  = f.input :title
  = f.input :price, required: true
  = f.input :barcode
  = f.input :description

  h3 attach product images
  #product_attachment
    = f.simple_fields_for :product_attachments do |product_attachment|
      = render 'product_attachment_fields', f: product_attachment
    .links
      = link_to_add_association 'add product attachment', f, :product_attachments
  = f.submit
</code></pre>

<p>_product_attachment_fields.html.slim
Noted I needed to name my file field this way for my controller to use files correctly, but unsure why still.</p>

<pre><code>.nested-fields
  = f.file_field :image , :multiple =&gt; true , name: "product_attachments[image][]"
  = link_to_remove_association "remove", f
</code></pre>

<p>Let me know if I can provide anything else. </p>

<p>Thank you for your time to read/reply.</p>

<p><strong>Edit1:</strong> My current method to debug I'm working through as of writing this is to strip out code chunks and test functionality by through browser. I've read I should be more familiar with rails console but have not got there yet.</p>

<p><strong>Edit2:</strong></p>

<pre><code>undefined method `[]' for nil:NilClass

        params[:product_attachments]['image'].each do |a|


app/controllers/products_controller.rb:47:in `block in create'
app/controllers/products_controller.rb:44:in `create'

Request

Parameters:

{"utf8"=&gt;"✓",
 "authenticity_token"=&gt;"{mytoken}",
 "product"=&gt;{"title"=&gt;"pleasefailwell",
 "commit"=&gt;"Create Product"}
</code></pre>

<p><strong>Edit3:</strong> Reworded original section for clarity</p>