title: Saving/updating a model with nested attributes and single table inheritance
body: <p>I have a model, <code>ModelRun</code>, that accepts nested attributes for another model, <code>ParameterValue</code>. (<code>ModelRun has_many :parameter_values</code>.) However, <code>ParameterValue</code> also employs single-table inheritance to save two subclasses: <code>NumericParameter</code> and <code>FileParameter</code>. <code>FileParameter</code> uses <a href="https://github.com/jnicklas/carrierwave" rel="nofollow noreferrer">CarrierWave</a> to store a file.</p>
  
  <p>The problem is that in <code>ModelRunController</code> when saving or updating a <code>ModelRun</code>, by default, <code>@model_run.save</code> or <code>@model_run.update_attributes</code> does not identify the type of <code>ParameterValue</code> attributes - it just tries to store them as <code>ParameterValue</code>. This works for <code>NumericParameter</code> values, but it raises an exception for <code>FileParameters</code> because the <a href="https://stackoverflow.com/a/8310758/81554">CarrierWave uploader doesn't get mounted</a> to handle the file upload so ActiveRecord fails when trying to serialize the file to the database.</p>
  
  <p>What's the cleanest way to handle this problem? The only solution that occurred to me was to manually populate the <code>@model_run.parameter_values</code> collection in the controller's <code>create</code> and <code>update</code> methods, since I can tell which type each <code>ParameterValue</code> should be and create the correct objects one by one. However, this seems like reimplementing a lot of Rails magic since I can't just use <code>ModelRun.new(params[:model_run])</code> or <code>@model_run.update_attributes</code> anymore - seems like it throws away much of the advantage of using <code>accepts_nested_attributes_for</code> in the first place. Is there a better way, a Rails Way&trade;?</p>
  
  <p>Relevant parts of each model are copied below.</p>
  
  <h3>model_run.rb</h3>
  
  <pre><code>class ModelRun &lt; ActiveRecord::Base
    has_many :parameter_values, dependent: :destroy
  
    accepts_nested_attributes_for :parameter_values, allow_destroy: true
  
    attr_accessible :name, 
                    :description, 
                    :geometry_description, 
                    :run_date, 
                    :run_date_as_string, 
                    :parameter_values_attributes
  end
  </code></pre>
  
  <h3>parameter_value.rb</h3>
  
  <pre><code>class ParameterValue &lt; ActiveRecord::Base
    belongs_to :model_run
  
    attr_accessible :type,
                    :parameter_id, 
                    :description, 
                    :numeric_value,
                    :model_run_id,
                    :parameter_file
  end
  </code></pre>
  
  <h3>numeric_parameter.rb</h3>
  
  <pre><code>class NumericParameter &lt; ParameterValue
    attr_accessible :numeric_value
  end
  </code></pre>
  
  <h3>file_parameter.rb</h3>
  
  <pre><code>class FileParameter &lt; ParameterValue
    mount_uploader :parameter_file, ParameterFileUploader
  
    attr_accessible :parameter_file
  end
  </code></pre>
  
  <h3>parameter_file_uploader.rb</h3>
  
  <pre><code>class ParameterFileUploader &lt; CarrierWave::Uploader::Base
    storage :file
  
    def store_dir
      "#{Rails.root}/uploads/#{model.class.to_s.underscore}/#{model.id}"
    end
  
    def cache_dir
      "#{Rails.root}/tmp/uploads/cache/#{model.id}"
    end
  
  end
  </code></pre>