Null Values from Nested Form

Posted this on Stack overflow and copied my post (it’s huge) here.

I’m in Rails 3.2.6

We have a nested form that was functioning up until recently (not entirely certain when the error started occurring). Now the queries are passing in nulls.

Example output:

Started POST "/articles" for 127.0.0.1 at 2012-07-12 11:04:16 -0600
Processing by ArticlesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"thing=", "article"=>{"asset_attributes"=>{"name"=>"asdf", "short_desc"=>"asdfasdfsadg", "publish_date"=>"2012-07-12 11:4", "content_section_attributes"=>{"section_id"=>"1", "primary_section"=>"1"}, "section_ids"=>[""], "author_id"=>"", "display_authorbiography"=>"1", "last_modified_by"=>"1", "by_line"=>"", "content_image_attributes"=>{"image_id"=>""}, "keywords_string"=>"", "public_keywords_string"=>"", "meta_public_keywords"=>"", "meta_page_title"=>"", "meta_description"=>"", "meta_url_name"=>"", "guid"=>"", "canonical"=>"", "partner_id"=>"", "tagline"=>"", "series_id"=>"", "display_adsense"=>"1", "sweepstakes"=>""}, "content"=>"<p>asdfasgasg</p>"}, "img_size"=>"i01", "show_cap"=>"1", "img_pos"=>"left", "commit"=>"Create"}
  User Load (0.2ms)  SELECT `people`.* FROM `people` WHERE `people`.`type` IN ('User') AND `people`.`id` = 1 LIMIT 1 /*application:TmnCoreCms,controller:articles,action:create*/
  Section Load (0.1ms)  SELECT `sections`.* FROM `sections` /*application:TmnCoreCms,controller:articles,action:create*/
  Site Load (0.1ms)  SELECT `sites`.* FROM `sites` WHERE `sites`.`id` IN (1) /*application:TmnCoreCms,controller:articles,action:create*/
  Site Load (0.1ms)  SELECT `sites`.* FROM `sites` /*application:TmnCoreCms,controller:articles,action:create*/
  Section Load (0.1ms)  SELECT `sections`.* FROM `sections` WHERE `sections`.`site_id` IN (1) /*application:TmnCoreCms,controller:articles,action:create*/
  Role Load (0.1ms)  SELECT `roles`.* FROM `roles` INNER JOIN `user_roles` ON `roles`.`id` = `user_roles`.`role_id` WHERE `user_roles`.`user_id` = 1 /*application:TmnCoreCms,controller:articles,action:create*/
   (0.1ms)  BEGIN /*application:TmnCoreCms,controller:articles,action:create*/
   (0.1ms)  COMMIT /*application:TmnCoreCms,controller:articles,action:create*/
   (0.1ms)  BEGIN /*application:TmnCoreCms,controller:articles,action:create*/
   (0.1ms)  COMMIT /*application:TmnCoreCms,controller:articles,action:create*/
   (0.1ms)  BEGIN /*application:TmnCoreCms,controller:articles,action:create*/
  SQL (0.2ms)  INSERT INTO `articles` (`content`, `created_at`, `static_url`, `updated_at`) VALUES ('<p>asdfasgasg</p>', '2012-07-12 17:04:16', NULL, '2012-07-12 17:04:16') /*application:TmnCoreCms,controller:articles,action:create*/
  Article Load (0.3ms)  SELECT `articles`.* FROM `articles` WHERE `articles`.`id` = 25 LIMIT 1 /*application:TmnCoreCms,controller:articles,action:create*/
{}
  SQL (0.0ms)  INSERT INTO `assets` (`aasm_state`, `author_id`, `by_line`, `canonical`, `content_id`, `content_type`, `created_at`, `creator_id`, `display_adsense`, `display_authorbiography`, `guid`, `last_modified_by`, `legacyid`, `live_date`, `meta_description`, `meta_page_title`, `meta_public_keywords`, `meta_url_name`, `migration_guid`, `name`, `partner_id`, `publish_date`, `publish_version`, `series_id`, `short_desc`, `sweepstakes`, `tagline`, `updated_at`, `url_name`) VALUES ('new', NULL, NULL, NULL, 25, 'Article', '2012-07-12 17:04:16', NULL, 1, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2012-07-12 17:04:16', NULL) /*application:TmnCoreCms,controller:articles,action:create*/
  SQL (0.2ms)  INSERT INTO `content_sections` (`content_id`, `content_type`, `created_at`, `primary_section`, `section_id`, `updated_at`) VALUES (53, 'Asset', '2012-07-12 17:04:16', 1, NULL, '2012-07-12 17:04:16') /*application:TmnCoreCms,controller:articles,action:create*/
   (33.6ms)  COMMIT /*application:TmnCoreCms,controller:articles,action:create*/
Redirected to http://localhost:3000/articles/53-
Completed 302 Found in 63ms (ActiveRecord: 35.3ms)

So as you can see the attributes are being sent. Our controller looks like this.

def new
    @article = Article.new
    @asset = @article.build_asset
  end

  def create
    @article = Article.new(params[:article])
    if @article.save
      flash[:notice] = 'Article was successfully created.'
      redirect_to @article
    else
      render :action => "new"
    end
  end

Relevant Model information:

class ContentType < ActiveRecord::Base
  self.abstract_class = true
  validates_presence_of :asset, :message => "Must have an asset"
  has_one :asset, :as => :content, :dependent => :destroy
  delegate :name, :url_name, :author, :creator, :publish_date, :short_desc,
           :aasm_state, :live_date, :keywords,
           :to => :asset, :allow_nil => true
  delegate :keywords_string, :public_keywords_string,
           :to => :asset,
           :allow_nil => true

  def initialize(*args)
    super(*args)
  end

  def to_param
    "#{asset.id}-#{url_name}"
  end
end

class Asset < ActiveRecord::Base
  include AASM
  include Keywordable
  attr_accessible :author_id,
                  :by_line,
                  :canonical,
                  :content_image_attributes,
                  :content_section_attributes,
                  :creator_id,
                  :display_adsense,
                  :display_authorbiography,
                  :guid,
                  :keywords,
                  :keywords_string,
                  :last_modified_by,
                  :meta_description,
                  :meta_page_title,
                  :meta_public_keywords,
                  :meta_url_name,
                  :name,
                  :partner_id,
                  :public_keywords_string,
                  :publish_date,
                  :related_content_attributes,
                  :section_ids,
                  :series_id,
                  :short_desc,
                  :sweepstakes,
                  :syndication_partner_ids,
                  :tagline,
                  :url_name

  belongs_to :author,  :class_name => 'Person'
  belongs_to :content, :polymorphic => true
  has_many :content_sections, :as => :content,  :conditions => {:primary_section => nil},  :dependent => :destroy

class Article < ContentType
  attr_accessible :images_attributes,
                  :content_images_attributes,
                  :content_text,
                  :content,
                  :asset_attributes,
                  :content_attributes

I really dislike this association set up but it is what it is. What’s happening is that the nested form

<%= f.fields_for :asset do |asset| %>
    <fieldset class="span8">
        <legend>Asset Description</legend>
        <div id='a_title'>
            <%= asset.label :name, "Title <span class='req'>*</span>".html_safe %>
            <%= asset.text_field :name, :class => 'asset_textarea counter', "data-max" => 255 %>
            <br/><span></span>
        </div>
        <div id='a_desc'>
            <%= asset.label :short_desc, "Teaser<span class='req'>*</span>".html_safe %>
                    <%= asset.text_area :short_desc, :class => "span7 asset_textarea counter", "data-max" => 255, :rows => 7 %>
                    <br/><span></span>
        </div>
    </fieldset>
<% end %>

Is somehow passing the fields and Rails is putting nulls in. I have no attr_accessible warnings. If I do an update on the article it will save the asset data. So something is going wrong on the initialization I think but I’m not sure what.

TLDR Rails is not passing values into sql query despite attr_accessible having the nested attributes.

Roll back your version control system (git or whatever you are using) to find at what point the problem was introduced. Then you will know what caused it.

Colin