Search code examples
ruby-on-railsrubysimple-formwizardformwizard

Nested attributes showing 'nil' in database


Been stuck on this for a while, I am using wizard gem and looking to save tenants attributes in a nested form. The attributes are being saved but are outputting nil in the database. Cant seem to understand why not sure if its the gem or, I am missing something obvious in the model or controller.

Parameters

Parameters: {"utf8"=>"✓", "authenticity_token"=>"xPqiDsUpnuLHCSnU+XuAUce4b/cTnM/gv6T7wxdIz4g=", "property"=>{"tenants_attributes"=>{"0"=>{"title"=>"Mr", "firstname"=>"Foo", "surname"=>"bar", "dateofbirth(1i)"=>"2013", "dateofbirth(2i)"=>"7", "dateofbirth(3i)"=>"21", "telno"=>"01143268375", "contact_type"=>"foo", "email"=>"example@gmail.com"}}}, "commit"=>"Create Tenant", "property_id"=>"58"}

here is the log showing tenant attributes as nil.

 INSERT INTO "tenants" ("contact_type", "created_at", "dateofbirth", "email", "firstname", "property_id", "surname", "telno", "title", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)  [["contact_type", nil], ["created_at", Sun, 21 Jul 2013 10:53:00 UTC +00:00], ["dateofbirth", nil], ["email", nil], ["firstname", nil], ["property_id", nil], ["surname", nil], ["telno", nil], ["title", nil], ["updated_at", Sun, 21 Jul 2013 10:53:00 UTC +00:00]]

properties/build Controller

class Properties::BuildController < ApplicationController


    include Wicked::Wizard 
    steps :tenant

    def show
      @property = Property.find(params[:property_id])
      @tenant = @property.tenants.new
      render_wizard
    end

    def update
     @property = Property.find(params[:property_id])
         @tenants = Tenant.find(params[:tenant])
        case step
      when :tenant 
        if @tenants.update_attributes(params[:tenants])
         render_wizard @tenant
        else
         render :action => 'edit'
        end
    end
end

def create
    @tenant = Tenant.create
    if @tenant.save
        flash[:success] = "Tenant Added"
        redirect_to wizard_path(steps.first, :tenant_id => @tenant.id)
    else
        render 'edit'
    end
end

end

property model

class Property < ActiveRecord::Base
  attr_accessible  :name, :address_attributes, :tenants_attributes
  belongs_to :user 

  has_one :address, :as => :addressable
  accepts_nested_attributes_for :address
  validates_associated :address

  has_many :tenants
  accepts_nested_attributes_for :tenants



  validates :name, presence: true,  length: { maximum: 200 }
  validates :address, presence: true
  validates :user_id, presence: true

end

Tenant form

<h2> Tenant Form</h2>


<%= simple_form_for @property, :url => url_for(:action => 'create', :controller =>   'properties/build'), :method => 'post' do |f| %>
<%= f.simple_fields_for :tenants do |f| %>
  <%= f.input :title %>
  <%= f.input :firstname %>
  <%= f.input :surname %>
  <%= f.input :dateofbirth %>
  <%= f.input :telno %>
  <%= f.input :contact_type %>
  <%= f.input :email %>
  <%= f.submit %>
<% end %>

Solution

  • You have several errors in your view. First, you are missing an end statement. Second, you are using f for the outer and inner form, so you are overriding outer with the inner. Try something like this:

    <%= simple_form_for @property, :url => url_for(:action => 'create', :controller =>   'properties/build'), :method => 'post' do |f| %>
      # Fields for property (f.input...)
      <%= f.simple_fields_for :tenants do |tenant| %>
        # Fields For tenant (tenant.input...)
      <% end %>
    <% end %>
    

    Also, I think you have an error here

    @tenant = Tenant.create
    if @tenant.save
      flash[:success] = "Tenant Added"
      redirect_to wizard_path(steps.first, :tenant_id => @tenant.id)
    else
      render 'edit'
    end
    

    When using if something.save, you must use something.new before it instead of something.create (create creates new record and saves it to the database, to there is no need to save it again, and new just creates the record, but you must save it manually).

    You probably need something like

    @property = Property.new(params[:property])
    if @property.save
      flash[:success] = "Tenant Added"
      redirect_to wizard_path(steps.first, :tenant_id => @tenant.id)
    else
      render 'edit'
    end