title: How to declare objects for nested form in rails 4
body: <p>I'm approaching my 2nd week of using rails, and have almost gotten the structure of my app complete (I think/hope). I'm building a staff website for a charity, which as part of their work collects and wipes computers (before sending them to African schools!). </p>
  
  <p>I've set up my app to have staff, computer, and wipe models / classes, and nested the form for the wiping details inside the form for the computer details. When I create a new computer, I can enter the wiping details without a problem, and if I edit the wiping details of an existing computer <strong>that already has wiping details</strong> it also works great. But when I go to add wiping details to an existing computer <strong>without wiping details</strong> I get the following error:</p>
  
  <pre><code>undefined method `staff=' for nil:NilClass
  Extracted source (around line #49):
  </code></pre>
  
  <p>How do I correctly set computer.wipe.staff = to the current user. Note that to edit or submit wiping details a user must be logged in.</p>
  
  <p>My models are as follows (ignoring irrelevant validations, etc):</p>
  
  <pre><code>class Staff &lt; ActiveRecord::Base
    has_many :wipes
    before_save { self.staff_email = staff_email.downcase }
    validates :staff_name, presence: true, length: { minimum: 5, maximum: 50}
    has_secure_password
  end
  
  class Computer &lt; ActiveRecord::Base
    has_one :wipe, dependent: :destroy
    accepts_nested_attributes_for :wipe
  end
  
  class Wipe &lt; ActiveRecord::Base
    belongs_to :computer#, dependent: destroy
    belongs_to :staff
    validates :staff_id, presence: true
   #validates :computer_id, presence: true
    validates :action_taken, presence: true, length: { minimum: 2, maximum: 250 }
  end
  </code></pre>
  
  <p>My computer controller is as follows:</p>
  
  <pre><code>class ComputersController &lt; ApplicationController
    before_action :set_computer, only: [:edit, :update, :show]
    before_action :require_user, except: [:new, :create]
  
    layout :new_layout, only: [:new, :update]
  
    def new
      @computer = Computer.new
      @computer.build_wipe
    end
  
    def create
      @computer = Computer.new(computer_params)
      if logged_in?
        @computer.wipe.staff = current_user
      end
      if @computer.save
        flash[:success] = "You're computer's details have been submitted successfully!"
        redirect_to computers_path
      else
        render :new, layout: new_layout
      end
    end
  
    def edit
      unless @computer.wipe
        @computer.build_wipe
      end
    end
  
    def update
      @computer.wipe.staff = current_user #This is the line not working, yet seems to work correctly in the create action
      if @computer.update(computer_params)
        flash[:success] = "The computer's details have been updated successfully!"
        redirect_to computer_path(@computer)
      else
        render :edit
      end
    end
  
    private
  
      #Whitelisting variables
      def computer_params
        params.require(:computer).permit(:manufacturer, :computer_type, :specification, :donor, :model_no, :serial_no, :product_key, :turingtrack, :picture, wipe_attributes: [:id, :action_taken, :staff_id])
      end
  
      def set_computer
        @computer = Computer.find(params[:id])
      end
  
  end
  </code></pre>
  
  <p>My view is:</p>
  
  <pre><code>&lt;div class="row"&gt;
    &lt;div class="well col-md-8 col-md-offset-2"&gt;
      &lt;%= form_for(@computer, html: { multipart: true }) do |f| %&gt;
  
        &lt;%= f.label :manufacturer %&gt;
        &lt;%= f.text_field :manufacturer, :placeholder =&gt; "Toshiba" %&gt;
        &lt;%= f.label :computer_type, "Computer Type" %&gt;
        &lt;%= f.text_field :computer_type, :placeholder =&gt; "Laptop"%&gt;
  
        &lt;% if logged_in? %&gt;
          &lt;br&gt;&lt;strong&gt;Wiping Details:&lt;br&gt;&lt;br&gt;&lt;/strong&gt;
          &lt;%= f.fields_for :wipe do |wipe_form| %&gt;
            &lt;%= wipe_form.label :action_taken %&gt;
            &lt;%= wipe_form.text_field :action_taken %&gt;
          &lt;% end %&gt;
        &lt;% end %&gt;
  
        &lt;%= f.submit(@computer.new_record? ? "Submit Details" : "Submit Edited Details", class: "btn btn-success") %&gt;
      &lt;% end %&gt;
  
    &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>Furthermore, currently I am not setting the <code>computer_id</code> when using the nested wipe form inside the computer form, it seems to automatically assign it (e.g. If I created a new computer/edit one and enter the wiping details, the <code>computer_id</code> for that wipe is that of the computer also created/edited). Is this assumption correct? I read somewhere about not being able to validate parent's foreign keys, but it was too brief to really understand. It throws an error when I try to validate <code>computer_id</code> in the wipes model, hence the validation being commented out. Why is this, and is it okay practice to leave it like this?</p>
  
  <p>Thank you everyone</p>