title: saveAll() Failing with CakePHP 2.3.1
body: <p>I am building a CakePHP 2.3 application, and can't for the life of me figure out why saveAll keeps failing.</p>
  
  <p>I have the following models:</p>
  
  <ul>
  <li><code>Artist</code> hasMany <code>ArtistPreview</code></li>
  <li><code>ArtistPreview</code> belongsTo <code>Artist</code></li>
  </ul>
  
  <p>I have no problem saving my <code>Artist</code> model with the <code>save()</code> function, however as soon as I try to use the <code>saveAll</code> method, Cake seems to fail validation - which is crazy because I have even totally removed all my validation rules from my models.</p>
  
  <p>Here's my view, nothing crazy:</p>
  
  <pre><code>&lt;?php
      echo $this-&gt;Form-&gt;create('Artist', array('inputDefaults' =&gt; array('class' =&gt; 'input-block-level')));
      echo $this-&gt;Form-&gt;input('Artist.name', array('label' =&gt; __('Name')));
      echo $this-&gt;Form-&gt;input('Artist.artist_section_id', array('label' =&gt; __('Section'), 'empty' =&gt; true));
  ?&gt;
  &lt;label&gt;Tags&lt;/label&gt;
  &lt;div class="checkboxes"&gt;
      &lt;?php echo $this-&gt;Form-&gt;input('Tag', array('label' =&gt; false, 'multiple' =&gt; 'checkbox', 'class' =&gt; false));; ?&gt;
  &lt;/div&gt;
  &lt;?php
      echo $this-&gt;Form-&gt;input('Artist.website', array('label' =&gt; __('Website')));
      echo $this-&gt;Form-&gt;input('ArtistPreview.0.url', array('label' =&gt; __('Artist Preview')));
      echo $this-&gt;Form-&gt;input('Artist.description', array('label' =&gt; __('Description')));
  ?&gt;
  &lt;?php
  
      echo $this-&gt;Form-&gt;submit(__('Add'), array('class' =&gt; 'btn btn-primary btn-large', 'div' =&gt; false)) . ' ';
      echo $this-&gt;Form-&gt;button(__('Cancel'), array('type' =&gt; 'button', 'class' =&gt; 'btn btn-large', 'div' =&gt; false, 'onclick' =&gt; 'closeDialog()'));
      echo $this-&gt;Form-&gt;end();
  ?&gt;
  </code></pre>
  
  <p>And here's my <code>add</code> controller method:</p>
  
  <pre><code>public function add() {
      $this-&gt;layout = 'form';
  
      if (!$this-&gt;request-&gt;is('ajax')) {
          throw new ForbiddenException();
      }
  
      if ($this-&gt;request-&gt;is('post')) {
          $this-&gt;setData($this-&gt;request-&gt;data['Artist'], array(
              'user_id' =&gt; AuthComponent::user('id'),
              'date' =&gt; $this-&gt;Date-&gt;gmt()
          ));
          if ($this-&gt;Artist-&gt;saveAll($this-&gt;request-&gt;data)) {
              $this-&gt;redirectAjax('/artists/view/' . $this-&gt;Artist-&gt;id);
          }
      }
  
      $this-&gt;set(array(
          'title_for_layout' =&gt; 'Add Artist',
          'artistSections' =&gt; $this-&gt;Artist-&gt;ArtistSection-&gt;find('list', array('order' =&gt; 'name')),
          'tags' =&gt; $this-&gt;Artist-&gt;Tag-&gt;find('list', array('order' =&gt; 'name'))
      ));
  }
  </code></pre>
  
  <p>As I mentioned above, the saveAll method fails everytime. I have inspected what is getting output and Cake is outputting a bunch of blank <code>&lt;div&gt;</code>s with the <code>error-message</code> class, but there is no message. Every field on the form gets one of these divs.</p>
  
  <p>Now, when I change my code to use the <code>save</code> function instead of <code>saveAll</code>, everything gets saved properly except the <code>ArtistPreview</code> data, which is to be expected. Even my HABTM Tags are being saved properly, and nothing fails validation.</p>
  
  <p>I have been using Cake since the 1.3 days so I'm quite familiar with it, and have even done exactly what I'm asking in previous projects. I'm leaning towards this being a bug, unless I'm missing something here. Any ideas?</p>
  
  <hr>
  
  <p><strong>EDIT</strong></p>
  
  <p>I have also tried the <code>saveAssociated</code> method, along with setting the <code>deep</code> key to <code>true</code> when trying to save. This will let me save the artist, but it will not save the related data (ArtistPreview).</p>
  
  <hr>
  
  <p><strong>EDIT 2</strong></p>
  
  <p>As requested, here are the two tables:</p>
  
  <pre><code>-- -----------------------------------------------------
  -- Table `artists`
  -- -----------------------------------------------------
  DROP TABLE IF EXISTS `artists` ;
  
  CREATE  TABLE IF NOT EXISTS `artists` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
    `user_id` INT UNSIGNED NULL ,
    `artist_section_id` INT UNSIGNED NULL ,
    `artist_status_id` INT UNSIGNED NULL ,
    `name` VARCHAR(200) NULL ,
    `website` VARCHAR(500) NULL ,
    `description` TEXT NULL ,
    `date` DATETIME NULL ,
    `comment_count` INT UNSIGNED NOT NULL DEFAULT 0 ,
    PRIMARY KEY (`id`) ,
    INDEX `FK_artists_users_idx` (`user_id` ASC) ,
    INDEX `FK_artists__artist_sections_idx` (`artist_section_id` ASC) ,
    INDEX `FK_artists__artist_statuses_idx` (`artist_status_id` ASC) ,
    CONSTRAINT `FK_artists__users`
      FOREIGN KEY (`user_id` )
      REFERENCES `users` (`id` )
      ON DELETE SET NULL
      ON UPDATE CASCADE,
    CONSTRAINT `FK_artists__artist_sections`
      FOREIGN KEY (`artist_section_id` )
      REFERENCES `artist_sections` (`id` )
      ON DELETE SET NULL
      ON UPDATE CASCADE,
    CONSTRAINT `FK_artists__artist_statuses`
      FOREIGN KEY (`artist_status_id` )
      REFERENCES `artist_statuses` (`id` )
      ON DELETE SET NULL
      ON UPDATE CASCADE)
  ENGINE = InnoDB;
  
  
  -- -----------------------------------------------------
  -- Table `artist_previews`
  -- -----------------------------------------------------
  DROP TABLE IF EXISTS `artist_previews` ;
  
  CREATE  TABLE IF NOT EXISTS `artist_previews` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
    `artist_id` INT UNSIGNED NULL ,
    `url` VARCHAR(500) NULL ,
    `date` DATETIME NULL ,
    PRIMARY KEY (`id`) ,
    INDEX `FK_artist_previews__artists_idx` (`artist_id` ASC) ,
    CONSTRAINT `FK_artist_previews__artists`
      FOREIGN KEY (`artist_id` )
      REFERENCES `artists` (`id` )
      ON DELETE CASCADE
      ON UPDATE CASCADE)
  ENGINE = InnoDB;
  </code></pre>
  
  <p>Here is my <code>setData</code> function, which just merges two arrays. Instead of using hidden fields, I set fields in the controller which aren't populated by user input:</p>
  
  <pre><code>public function setData(&amp;$original, $new) {
      $original = array_merge($original, $new);
  }
  </code></pre>