title: Rails 4: form object for update action for 2 models
body: <p>I have a form object that handles 2 associated objects. I'm trying to get some validation working on the form object, but am not having much success.</p>
  
  <p>I think the issue is that the attributes I'm validating are delegated to the model objects, but I'm not sure how else to handle this situation: when the form is displayed, these attributes need to pull from the actual models to show the values on the form in edit mode, but when I update the form, I need to validate the submitted parameters, not the values being pulled from the models themselves.</p>
  
  <p>One thought I have is using a <code>EditBorrowerForm</code> object that pulls attributes from associated models and a <code>UpdateBorrowerForm</code> that performs all the validations and updates the models.  But that seems like a lot of extra work for something trivial.</p>
  
  <p>I've seen a lot of form objects used for CREATE actions (where you only validate fields before passing them to the models), but haven't seen any good examples of UPDATE actions (where you need to both pull fields from models as well as update them).</p>
  
  <p>Here are the models I'm working with:</p>
  
  <pre><code>class Client &lt; ActiveRecord::Base
    has_many :borrowers
  end
  
  class Borrower &lt; ActiveRecord::Base
    belongs_to :client
  end
  </code></pre>
  
  <p>And my form object:</p>
  
  <pre><code>class BorrowerForm
    include ActiveModel::Model
  
    attr_accessor :client, :borrower
  
    delegate :first_name, :last_name, :date_of_birth, to: :client
    delegate :citizenship, :marital_status, to: :borrower
  
    validates :first_name, :last_name, :citizenship, presence: true
  
    def initialize(borrower)
      @borrower = borrower
      @client = @borrower.client
    end
  
    def update_attributes(params)
      # Never validates properly...
      if valid?
        ActiveRecord::Base.transaction do
          borrower.update_attributes(params.slice(:citizenship, :marital_status)
          client.update_attributes(params.slice(:first_name, :last_name, :date_of_birth)
        end
  
        true
      else
        false
      end
    end
  end
  </code></pre>
  
  <p>And the controller:</p>
  
  <pre><code>class BorrowersController &lt; ApplicationController
    def edit
      @borrower = BorrowerForm.new(Borrower.find(params[:id])
    end
  
    def update
      @borrower = BorrowerForm.new(Borrower.find(params[:id])
  
      if @borrower.update_attributes(params)
        redirect_to :index
      else
        render :edit
      end
    end
  end
  </code></pre>