0

Today I was trying to write a nested form with House and Address.

# app/models/house.rb
class House < ApplicationRecord
  has_one :address

  accepts_nested_attributes_for :address
end

# app/models/address.rb
class Address < ApplicationRecord
  belongs_to :house
end

Here is the some part of the schema.rb

# db/schema.rb
create_table "addresses", force: :cascade do |t|
  t.string "state", null: false
  # ...
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

create_table "houses", force: :cascade do |t|
  t.integer "rent", null: false
  # ...
  t.bigint "address_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.index ["address_id"], name: "index_houses_on_address_id"
end

add_foreign_key "houses", "addresses"

Here it's the what I was trying

<div class="col-md-6 mx-auto">
  <%= form_for @house do |form| %>
    <div class="form-row">
      <div class="form-group col-6">
        <%= form.label :rent %>
        <%= form.text_field :rent, class: "form-control" %>
      </div>
    </div>
    <%= form.fields_for :address do |address_form| %>
      <div class="form-row">
        <div class="form-group col-4">
          <%= address_form.label :state %>
          <%= address_form.text_field :state %>
        </div>
      </div>
    <% end %>
    <%= form.submit "Submit", class: "btn btn-primary" %>
  <% end %>
</div>

I'm trying to write a form which has address field; however, when I run this piece of code, it doesn't return a form. Any tip about nested form would be great!

Thank you.


When I turned back to code, I added <%= form.fields_for :addresses do |address| %>. Is it good practices?


class HousesController < ApplicationController
  #...
  def new
    @house = House.new
  end

  def create
    @house = House.new house_params
    @house.user = current_user

    if @house.save
      redirect_to root_path
    else
      render :new
    end
  end
  # ...
end
  • Yes. using `form.fields_for` is the way you should use form for nested attributes. and try adding `@house.address.build` or `@house.build_address` in you controller. – Charith H Jul 19 '18 at 00:33
  • @CharithH I added a piece of `Controller`. Also, you can check the original app on GitHub. – Berkhan Berkdemir Jul 19 '18 at 02:01
  • I have added an answer below. Please check. btw, Your GitHub link isn't working :) – Charith H Jul 19 '18 at 02:41
  • I added the link top of the question, @CharithH – Berkhan Berkdemir Jul 19 '18 at 02:55
  • Check the fix [here](https://github.com/charithhewage/list-of-houses/commit/c957a5035fff5ffd71ac0bc4aeeb556ec1600f37). And add database.yml file to .gitignore or use .env file for sensitive information like password and username – Charith H Jul 19 '18 at 03:17
  • Thank you for you suggestion, but I use `docker-compose.yml` for that reason I keep my username and password in that file. Also, those are for development and testing. BTW I saw the fork. Thank you again! – Berkhan Berkdemir Jul 19 '18 at 03:39

1 Answers1

4

Step by step guide to build this association.
Add reference to house in address migration file t.belongs_to :house, index: true.

class CreateAddressses < ActiveRecord::Migration[5.2]
  def change
    create_table :addressses do |t|
      t.belongs_to :house, index: true
      t.string :state
      t.timestamps
    end
  end
end

Add @house.build_address to HousesController new method

def new
  @house = House.new
  @house.build_address
end

Accept address params,

def house_params
  params.require(:house).permit(:name, address_attributes: [:state])
end

Other sections of your code are correct including models. Follow this tutorial on railscasts

Charith H
  • 345
  • 1
  • 13
  • What is the difference between migrated `belongs_to` and model one? – Berkhan Berkdemir Jul 19 '18 at 03:02
  • `belongs_to` is an alias of references. this will add `house_id` as a forign_key to address table. [Read More](http://vaidehijoshi.github.io/blog/2015/07/14/writing-smart-migrations-references-reversible-and-indexes/) – Charith H Jul 19 '18 at 03:25